render items using table or list
[MojoFacets.git] / lib / MojoFacets / Data.pm
index 6db5aa2..de1a226 100644 (file)
@@ -9,6 +9,7 @@ use Data::Dump qw(dump);
 use File::Slurp;
 use JSON;
 use Encode;
+use locale;
 
 sub index {
        my $self = shift;
@@ -156,22 +157,28 @@ sub filter {
 
        $self->session( 'offset' => 0 );
 
-       $self->redirect_to('/data/table');
+       $self->redirect_to('/data/items');
 }
 
 sub _filter_item {
        my ( $self, $filters, $i ) = @_;
        my $pass = 1;
        foreach my $n ( keys %$filters ) {
-               # filter must exists in element
-               if ( ! defined $i->{$n} ) {
-                       $pass = 0;
-                       last;
+               my @filter_values = @{ $filters->{$n} };
+               my $include_missing = grep { /^_missing/ } @filter_values;
+               if ( ! exists $i->{$n} ) {
+                       if ( $include_missing ) {
+                               $pass = 1;
+                               next;
+                       } else {
+                               $pass = 0;
+                               last;
+                       }
                }
                # and match any of values in element
                my $have_values = 0;
                foreach my $v ( @{ $i->{$n} } ) { # FIXME not array?
-                       $have_values ||= 1 if grep { m/^\Q$v\E$/ } @{ $filters->{$n} };
+                       $have_values ||= 1 if grep { m/^\Q$v\E$/ } @filter_values;
                }
                if ( ! $have_values ) {
                        $pass = 0;
@@ -189,7 +196,7 @@ sub _data_items {
        } @{ $data->{items} };
 }
 
-sub table {
+sub items {
     my $self = shift;
 
        $self->redirect_to('/data/index') unless $data->{items};
@@ -197,19 +204,28 @@ sub table {
        my @columns = $self->_perm_array('columns');
        $self->redirect_to('/data/columns') unless @columns;
        my $order   = $self->_perm_scalar('order', $columns[0]);
+       my $sort    = $self->_perm_scalar('sort', 'a');
        my $offset  = $self->_perm_scalar('offset', 0);
        my $limit   = $self->_perm_scalar('limit', 20);
 
+       # fix offset when changing limit
+       $offset = int( $offset / $limit ) * $limit;
+
+       # FIXME - multi-level sort
+       my $numeric = $self->_is_numeric($order);
+       my $missing = $numeric ? 0 : '';
+       no warnings qw(numeric);
        my @sorted = sort {
-               ( $a->{$order} || '' ) cmp ( $b->{$order} || '' ) # FIXME - multi-level sort
+               my $v1 = exists $a->{$order} ? join('', @{$a->{$order}}) : $missing;
+               my $v2 = exists $b->{$order} ? join('', @{$b->{$order}}) : $missing;
+               ($v1,$v2) = ($v2,$v1) if $sort eq 'd';
+               $numeric ? $v1 <=> $v2 : $v1 cmp $v2 ;
        } $self->_data_items;
 
 #      warn "# sorted ", dump @sorted;
 
        my $rows = $#sorted + 1;
 
-       warn "$rows $offset $limit";
-
        $self->render(
                order => $order,
                offset => $offset,
@@ -217,11 +233,27 @@ sub table {
                sorted => [ splice @sorted, $offset, $limit ],
                columns => [ @columns ],
                rows => $rows,
+               numeric => { map { $_, $self->_is_numeric($_) } @columns },
        );
 
 }
 
 
+sub order {
+       my $self = shift;
+       $self->session('order', $self->param('order'));
+       $self->session('sort', $self->param('sort'));
+       $self->redirect_to('/data/items');
+}
+
+sub _is_numeric {
+       my ( $self, $name ) = @_;
+
+       # sort facet numerically if more >50% elements are numeric
+       defined $stats->{$name}->{numeric} &&
+               $stats->{$name}->{numeric} > $stats->{$name}->{count} / 2;
+}
+
 sub facet {
        my $self = shift;
 
@@ -229,15 +261,16 @@ sub facet {
                my $f = $self->session('filters');
                delete $f->{$remove};
                $self->session( 'filters' => $f );
-               $self->redirect_to( '/data/table' );
+               $self->redirect_to( '/data/items' );
        }
 
        my $facet;
        my $name = $self->param('name') || die "no name";
 
        foreach my $i ( $self->_data_items ) {
-               next unless exists $i->{$name};
-               if ( ref $i->{$name} eq 'ARRAY' ) {
+               if ( ! exists $i->{$name} ) {
+                       $facet->{ _missing }++;
+               } elsif ( ref $i->{$name} eq 'ARRAY' ) {
                        $facet->{$_}++ foreach @{ $i->{$name} };
                } else {
                        $facet->{ $i->{$name} }++;
@@ -256,8 +289,7 @@ sub facet {
        my $sort = $self->param('sort') || 'c';
 
        # sort facet numerically if more >50% elements are numeric
-       my $numeric = defined $stats->{$name}->{numeric} &&
-               $stats->{$name}->{numeric} > $stats->{$name}->{count} / 2;
+       my $numeric = $self->_is_numeric($name);
 
        my @facet_names = sort {
                if ( $sort =~ m/a/i ) {