add a marker and a notice if the table did not contain any rows
[scpubgit/JSON-Tree-Viewer.git] / br.pl
diff --git a/br.pl b/br.pl
index 054a5ec..f900028 100644 (file)
--- a/br.pl
+++ b/br.pl
@@ -5,13 +5,14 @@ use Module::Runtime qw(use_module);
 use Scalar::Util qw(blessed);
 use IO::All;
 use JSON;
+use URI::Escape;
 
 has root => (is => 'lazy');
 
 has json => (is => 'lazy');
 
 sub _build_root {
-  io->dir("/home/matthewt/tmp/introspection-data/host/services-dev/stable/node/host/")
+  io->dir( $ENV{JTV_ROOT} || die "JTV_ROOT env var not set" )
 }
 
 sub _build_json {
@@ -32,14 +33,18 @@ sub dispatch_request {
   },
   sub (/) {
     sub (?@host=) {
-      [ 302, [ 'Location', '/'.join('+', @{$_[1]}) ], [] ];
+      [ 302, [ 'Location', '/'.join('+', @{$_[1]}).'/' ], [] ];
     },
     sub () {
       $self->root_structure;
     },
   },
   sub (/**/) {
-    $self->structure(split '/', $_[1]);
+    $self->structure(map {
+      s{\\/}{/}g;
+      s{\\\\}{\\}g;
+      $_;
+    } split qr{(?<!\\)/}, $_[1]);
   },
 }
 
@@ -128,6 +133,17 @@ sub mangle_structure {
       columns => [ 'key', 'value' ],
       data => [ map +{ key => $_, value => $data->{$_} }, sort keys %$data ],
     }];
+  } elsif (ref($data) eq 'ARRAY') {
+    if (not grep { not ref($_) eq 'HASH' } @$data) {
+      my %key;
+      $key{$_} = 1
+        for map { keys %$_ } @$data;
+      return [{
+        columns => [sort keys %key],
+        show_columns => 1,
+        data => $data,
+      }];
+    }
   } elsif (blessed($data) and $data->isa('IO::All::Dir')) {
     return [{
       columns => [ 'name', 'explore' ],
@@ -143,11 +159,15 @@ sub mangle_structure {
 sub link_to {
   my ($self, @to) = @_;
   use HTML::Tags;
-  s/\//\./g for my @link = @to;
+  my @link = map {
+    s{\\}{\\\\}g;
+    s{/}{\\/}g;
+    $_;
+  } @to;
   my $link = join('/', @link, '');
   my $to = $to[-1];
   my $html = join '', HTML::Tags::to_html_string(
-    <a href="${link}">, "Explore $to", </a>
+    <a href="./${link}">, "Explore $to", </a>
   );
   return \$html;
 }
@@ -159,8 +179,8 @@ sub descend {
     $target = $self->json->decode(scalar $target->all);
   }
   return $target unless @path;
-  (my $undot = my $step = shift @path) =~ s/\./\//g;
-  $self->descend($target->{$step}||$target->{$undot}, @path);
+  my $step = shift @path;
+  $self->descend($target->{$step}, @path);
 }
 
 sub render_table {
@@ -175,13 +195,17 @@ sub render_table {
       <html>, <body>, "\n",
       ($data->{wrapper}||sub{@_})->(
         '', <table>, "\n",
-          (map { my $el = $_;
-            '  ', <tr>,
-              (map {
-                <td>, $self->render_el($el, $_, $el->{$_}), </td>
-              } @{$data->{columns}}),
-            </tr>, "\n"
-          } @rows),
+          @rows
+          ? (map { my $el = $_;
+              '  ', ($el->{key} eq '__error__') ? <tr class="error"> : <tr>,
+                (map {
+                  <td>, $self->render_el($el, $_, $el->{$_}), </td>
+                } @{$data->{columns}}),
+              </tr>, "\n"
+            } @rows)
+          : (<tr class="no-rows">,
+              <td>, 'No entries in this data structure', </td>,
+            </tr>),
         '', </table>, "\n",
       ),
       </body>, </html>, "\n",
@@ -192,7 +216,17 @@ sub render_table {
 sub render_el {
   my ($self, $whole, $key, $part) = @_;
   if (ref($part) eq 'ARRAY') {
-    return join(', ', @$part);
+    if (grep { ref($_) eq 'HASH' } @$part) {
+      if ($whole->{key}) {
+        return $self->link_to($whole->{key})
+      } elsif ($whole->{name}) {
+        return $self->link_to($whole->{name}, $key);
+      }
+    }
+    return join ', ', @$part
+      if @$part < 5;
+    use HTML::Tags;
+    return <ul>, (map { (<li>, $_, </li>) } @$part), </ul>;
   }
   if (ref($part) eq 'HASH') {
     if ($whole->{key}) {