summaryrefslogtreecommitdiff
path: root/lib/JWebmail/Plugin/Paginate.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/JWebmail/Plugin/Paginate.pm')
-rw-r--r--lib/JWebmail/Plugin/Paginate.pm145
1 files changed, 145 insertions, 0 deletions
diff --git a/lib/JWebmail/Plugin/Paginate.pm b/lib/JWebmail/Plugin/Paginate.pm
new file mode 100644
index 0000000..1a48ed3
--- /dev/null
+++ b/lib/JWebmail/Plugin/Paginate.pm
@@ -0,0 +1,145 @@
+package JWebmail::Plugin::Paginate;
+
+use Mojo::Base Mojolicious::Plugin;
+
+use List::Util qw(any max);
+use POSIX 'ceil';
+
+
+sub _clamp {
+ my ($x, $y, $z) = @_;
+
+ die '!($x <= $z)' unless $x <= $z;
+
+ if ($x <= $y && $y <= $z) {
+ return $y;
+ }
+
+ return $x if ($y < $x);
+ return $z if ($z < $y);
+}
+
+sub _paginate {
+ my %args = @_;
+
+ my $first_item = $args{first_item};
+ my $page_size = $args{page_size};
+ my $total_items = $args{total_items};
+
+ my $current_page = ceil($first_item/$page_size);
+ my $total_pages = ceil($total_items/$page_size);
+
+ my $page = sub {
+ my $page_ = shift;
+ return [0, 0] unless $total_items;
+ $page_ = _clamp(0, $page_, $total_pages-1);
+ [_clamp(0, $page_*$page_size, $total_items-1), _clamp(0, ($page_+1)*$page_size, $total_items)]
+ };
+
+ my $ret = {
+ total_items => $total_items,
+ page_size => $page_size,
+
+ total_pages => $total_pages,
+ current_page => $current_page,
+
+ first_page => $page->(0),
+ prev_page => $page->($current_page-1),
+ this_page => $page->($current_page),
+ next_page => $page->($current_page+1),
+ last_page => $page->($total_pages-1),
+ };
+
+ if ($total_items) {
+ $ret->{first_item} = $first_item;
+ $ret->{last_item} = _clamp($first_item, $first_item+$page_size-1, $total_items-1);
+ }
+
+ return $ret;
+}
+
+sub paginate {
+ my $c = shift;
+ my ($count) = @_;
+
+ my $v = $c->validation;
+ my $start = $v->optional('start')->num(0, undef)->param // 0;
+ my $psize = $v->optional('page_size')->num(1, undef)->param // 50;
+
+ $start = _clamp(0, $start, max($count-1, 0));
+ my $end = _clamp($start, $start+$psize, max($count, 0));
+
+ $c->stash(pgn => _paginate(
+ first_item => int($start/$psize)*$psize,
+ page_size => $psize,
+ total_items => $count,
+ ));
+
+ return $start, $end;
+}
+
+
+sub register {
+ my ($self, $app, $conf) = @_;
+ $conf //= {};
+
+ $app->helper(paginate => \&paginate);
+}
+
+
+1
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+JWebmail::Plugin::Paginate
+
+=head1 SYNOPSIS
+
+ sub my_route {
+ my ($c) = @_;
+
+ $c->stash($c->paginate(1234));
+ }
+
+=head1 DESCRIPTION
+
+L<JWebmail::Helper> provides useful helper functions and validator cheks and filter for
+L<JWebmail::Controller::All> and various templates.
+
+=head1 HELPERS
+
+=head2 paginate
+
+A helper for calculating page bounds.
+
+Takes the total number of items as argument.
+
+Reads in 'start' and 'page_size' query arguments.
+start is 0 based.
+
+Returns the calculated start and end points as 0 based inclusive range.
+
+Sets the stash values (all 1 based inclusive):
+
+ first_item
+ last_item
+ total_items
+ page_size
+ total_pages
+ current_page
+ first_page
+ prev_page
+ next_page
+ last_page
+
+=head1 SEE ALSO
+
+L<JWebmail>
+
+=head1 NOTICE
+
+This package is part of JWebmail.