can download plant phenotype data in the same way as plot phenotype data
[sgn.git] / lib / SGN / Controller / JavaScript.pm
blob3ead51746ff5909eea4b90c1cddc3c64563733cd
1 =head1 NAME
3 SGN::Controller::JavaScript - controller for serving minified
4 javascript
6 =cut
8 package SGN::Controller::JavaScript;
9 use Moose;
10 use namespace::autoclean;
11 use Moose::Util::TypeConstraints;
13 use HTTP::Status;
14 use File::Spec;
16 use Fcntl qw( S_ISREG S_ISLNK );
18 use JSAN::ServerSide;
19 use List::MoreUtils qw/ uniq first_index /;
21 BEGIN { extends 'Catalyst::Controller' }
23 __PACKAGE__->config(
24 namespace => 'js',
25 js_include_path => SGN->path_to('js'),
29 my $inc = subtype as 'ArrayRef';
30 coerce $inc, from 'Defined', via { [$_] };
32 has 'js_include_path' => (
33 is => 'ro',
34 isa => $inc,
35 coerce => 1,
39 =head1 PUBLIC ACTIONS
41 =head2 default
43 Serve a single (minified) javascript file from our js path.
45 =cut
47 sub default :Path {
48 my ( $self, $c, @args ) = @_;
50 my $rel_file = File::Spec->catfile( @args );
52 # support caching with If-Modified-Since requests
53 my $full_file = File::Spec->catfile( $self->js_include_path->[0], $rel_file );
54 my ( $modtime ) = (stat( $full_file ))[9];
55 $c->throw_404 unless $modtime && -f _;
57 my $ims = $c->req->headers->if_modified_since;
58 if( $ims && $modtime && $ims >= $modtime ) {
59 $c->res->status( RC_NOT_MODIFIED );
60 $c->res->body(' ');
61 } else {
62 $c->stash->{js} = [ $rel_file ];
63 $c->forward('View::JavaScript');
68 =head1 PRIVATE ACTIONS
70 =head2 resolve_javascript_classes
72 =cut
74 sub resolve_javascript_classes :Private {
75 my ( $self, $c ) = @_;
77 my $files = $c->stash->{js_classes}
78 or return;
80 my @files = uniq @$files; #< do not sort, load order might be important
81 for (@files) {
82 s/\.js$//;
83 s!\.!/!g;
85 # if prototype is present, move it to the front to prevent it
86 # conflicting with jquery
87 my $prototype_idx = first_index { /Prototype$/i } @files;
88 if( $prototype_idx > -1 ) {
89 my ($p) = splice @files, $prototype_idx, 1;
90 unshift @files, $p;
93 # add in JSAN.use dependencies
94 @files = $self->_resolve_jsan_dependencies( \@files );
96 $c->stash->{js_uris} = \@files;
99 ########## helpers #########
101 sub _resolve_jsan_dependencies {
102 my ( $self, $files ) = @_;
103 local $_; #< stupid JSAN writes to $_
105 # resolve JSAN dependencies of these files
106 my $jsan = $self->new_jsan;
107 for my $f (@$files) {
108 $jsan->add( $f );
111 return $jsan->uris;
114 has _jsan_params => ( is => 'ro', isa => 'HashRef', lazy_build => 1 );
115 sub _build__jsan_params {
116 my ( $self ) = @_;
117 my $inc_path = $self->js_include_path;
118 die "multi-dir js_include_path not yet supported" if @$inc_path > 1;
119 my $js_dir = $inc_path->[0];
120 -d $js_dir or die "configured js_include_path '$js_dir' does not exist!\n";
121 return {
122 js_dir => "$js_dir",
123 uri_prefix => '/js',
126 sub new_jsan {
127 JSAN::ServerSide->new( %{ shift->_jsan_params } );