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';
+}
+
+=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
} 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;
}
} 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
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, 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;
# Handle changes to owner-accessible parameters
my $m = $c->model('Directory');
my $changed;
- # Handle scalar params
- foreach my $param ( qw/ name language / ) {
- if( exists $params->{$param} ) {
- my $newval = delete $params->{$param};
- unless( $tradition->$param eq $newval ) {
- try {
- $tradition->$param( $newval );
- } catch {
- return _json_error( $c, 500, "Error setting $param to $newval" );
- }
+ # Handle name param - easy
+ if( exists $params->{name} ) {
+ my $newname = delete $params->{name};
+ unless( $tradition->name eq $newname ) {
+ try {
+ $tradition->name( $newname );
$changed = 1;
+ } catch {
+ return _json_error( $c, 500, "Error setting name to $newname" );
}
}
}
+ # Handle language param, making Default => null
+ my $langval = delete $params->{language} || 'Default';
+
+ unless( $tradition->language eq $langval || !$tradition->can('language') ) {
+ try {
+ $tradition->language( $langval );
+ $changed = 1;
+ } catch {
+ return _json_error( $c, 500, "Error setting language to $langval" );
+ }
+ }
+
# Handle our boolean
+ my $ispublic = $tradition->public;
if( delete $params->{'public'} ) { # if it's any true value...
$tradition->public( 1 );
+ $changed = 1 unless $ispublic;
+ } else { # the checkbox was unchecked, ergo it should not be public
+ $tradition->public( 0 );
+ $changed = 1 if $ispublic;
}
- # Handle ownership changes
- my $newuser;
+
+ # Handle ownership change
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->email eq $newownerid ) ) {
unless( $c->user->get_object->is_admin ) {
return _json_error( $c, 403,
"Only admin users can change tradition ownership" );
}
- $newuser = $m->lookup_user( $params->{'owner'} );
+ $newuser = $m->find_user({ email => $newownerid });
unless( $newuser ) {
- return _json_error( $c, 500, "No such user " . $params->{'owner'} );
+ 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;
my $textinfo = {
textid => $textid,
name => $tradition->name,
- language => $tradition->language,
- public => $tradition->public,
- owner => $tradition->user ? $tradition->user->id : undef,
+ #language => $tradition->language,
+ public => $tradition->public || 0,
+ owner => $tradition->user ? $tradition->user->email : undef,
witnesses => [ map { $_->sigil } $tradition->witnesses ],
};
- my @stemmasvg = map { $_->as_svg({ size => [ 500, 375 ] }) } $tradition->stemmata;
+ if( $tradition->can('language') ) {
+ $textinfo->{'language'} = $tradition->language;
+ }
+ my @stemmasvg = map { $_->as_svg() } $tradition->stemmata;
map { $_ =~ s/\n/ /mg } @stemmasvg;
$textinfo->{stemmata} = \@stemmasvg;
$c->stash->{'result'} = $textinfo;
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;
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;
try {
if( $stemmaid eq 'n' ) {
# We are adding a new stemma.
+ $stemmaid = $tradition->stemma_count;
$stemma = $tradition->add_stemma( 'dot' => $dot );
+ } 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 );
# For a GET or a successful POST request, return the SVG representation
# of the stemma in question, if any.
- $c->log->debug( "Received Accept header: " . $c->req->header('Accept') );
if( !$stemma && $tradition->stemma_count > $stemmaid ) {
$stemma = $tradition->stemma( $stemmaid );
}
- $c->stash->{'result'} = $stemma
- ? $stemma->as_svg( { size => [ 500, 375 ] } ) : '';
- $c->forward('View::SVG');
+ 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') ) {
+ $c->log->debug( "Received Accept header: $accept_header" );
+ foreach my $type ( split( /,\s*/, $accept_header ) ) {
+ # If we were first asked for XML, return SVG
+ last if $type =~ /^(application|text)\/xml$/;
+ # If we were first asked for JSON, return JSON
+ if( $type eq 'application/json' ) {
+ $return_view = 'JSON';
+ last;
+ }
+ }
+ }
+ if( $return_view eq 'SVG' ) {
+ $c->stash->{'result'} = $stemma_xml;
+ $c->forward('View::SVG');
+ } else { # JSON
+ $stemma_xml =~ s/\n/ /mg;
+ $c->stash->{'result'} = { 'stemmaid' => $stemmaid, 'stemmasvg' => $stemma_xml };
+ $c->forward('View::JSON');
+ }
}
=head2 stemmadot
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' } ) };
$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
####################