CallBackery

 view release on metacpan or  search on metacpan

lib/CallBackery/GuiPlugin/AbstractTable.pm  view on Meta::CPAN

             size        => 100,
         },
     ],
 );

Every entry adds one column and takes these keys:

=over

=item type

The kind of column to generate. Only C<qrCode> exists so far. It embeds the
content as a QR code image.

=item content

Where the content comes from: either the key of a field in the table data, or
a code reference which is called with the record hash reference and returns
the string to encode. A record whose content is undefined or empty gets no
image.

=item insertAfter

Optional. The zero based index in L</tableCfg> the new column is placed after.
The indices of all extra columns refer to the original L</tableCfg>, so
several extra columns cannot shift each other around. Without it the column
follows the column named by C<content>, which is therefore mandatory for a
code reference content.

=item label

Optional column heading, translated like any other label. It defaults to the
heading of the column named by C<content>.

=item size

Optional edge length of the image in pixels, 100 by default. The row height
and the column width are adjusted to fit.

=back

C<extraCols> is ignored for a CSV export, which has nowhere to put an image.

A C<qrCode> column needs L<Text::QRCode>, which is loaded on first use so that
installations without QR code exports do not have to carry it.

=cut

sub makeExportAction {
    my $self = shift;
    my %args = @_;
    my $type = $args{type} // 'XLSX';
    my $extraCols = $args{extraCols};
    my $label = $args{label} // trm("Export %1", $type);
    my $filename = $args{filename}
        // localtime->strftime('export-%Y-%m-%d-%H-%M-%S.').lc($type);

    return  {
        label            => $label,
        action           => 'download',
        addToContextMenu => true,
        key              => 'export_csv',
        actionHandler    => sub {
            my $self = shift;
            my $args = shift;
            my $data = $self->getTableData({
                formData => $args,
                firstRow => 0,
                lastRow => $self->getTableRowCount({ formData=>$args })
            });

            # Use the (translated) table headers in row 1.
            # Or the keys if undefined.
            my $loc = CallBackery::Translate->new(localeRoot=>$self->app->home->child("share"));
            $loc->setLocale($self->user->userInfo->{lang} // 'en');
            my $tCfg = $self->tableCfg;

            my $tra = sub {
                my $label = shift;
                return undef unless defined $label;
                return ref $label eq 'CallBackery::Translate'
                    ? $loc->tra($label->[0])
                    : $label;
            };

            my @titles = map { $tra->($_->{label}) // $_->{key} } @$tCfg;

            if ($type eq 'CSV') {
                my $csv = Text::CSV->new;
                $csv->combine(@titles);
                my $csv_str = $csv->string . "\n";
                for my $record (@$data) {
                    $csv->combine(map {
                        my $v = $record->{$_->{key}};
                        if ($_->{type} eq 'date') {
                            $v= localtime($v/1000)->strftime("%Y-%m-%d %H:%M:%S %z");
                        }
                        $v} @$tCfg);
                    $csv_str .= $csv->string . "\n";
                }
                my $asset = Mojo::Asset::Memory->new;
                $asset->add_chunk($csv_str);
                return {
                    asset    => $asset,
                    type     => 'text/csv',
                    filename => $filename,
                }
            }
            elsif ($type eq 'XLSX') {
                # a spreadsheet is the only export that can hold images, so
                # the extra columns exist here and are ignored for CSV
                my $plan = $self->_exportColumnPlan($tCfg, $extraCols);

                open my $xh, '>', \my $xlsx or die "failed to open xlsx fh: $!";
                my $workbook  = Excel::Writer::XLSX->new($xh);
                my $worksheet = $workbook->add_worksheet();

                my $col = 0;
                for my $p (@$plan) {
                    if (my $tc = $p->{col}) {
                        $worksheet->write(0, $col, $tra->($tc->{label}) // $tc->{key});



( run in 0.682 second using v1.01-cache-2.11-cpan-8dfa8b56332 )