File Coverage

File:lib/Yukki/Web/View/Page.pm
Coverage:35.2%

linestmtbrancondsubpodtimecode
1package Yukki::Web::View::Page;
2
3
1
1
3348
10
use v5.24;
4
1
1
1
9
4
19
use utf8;
5
1
1
1
38
4
21
use Moo;
6
7
1
1
1
588
4
20
use Type::Utils;
8
9
1
1
1
1581
2
15
use namespace::clean;
10
11extends 'Yukki::Web::View';
12
13# ABSTRACT: render HTML for viewing and editing wiki pages
14
15 - 19
=head1 DESCRIPTION

Renders wiki pages.

=cut
20
21has blank_template => (
22    is          => 'ro',
23    isa         => class_type('Template::Pure'),
24    lazy        => 1,
25    builder     => '_build_blank_template',
26);
27
28sub _build_blank_template {
29    shift->prepare_template(
30
0
0
        template   => 'page/blank.html',
31        directives => [
32            '#yukkiname'        => 'page',
33            '#create-page@href' => 'link',
34            '#file-list'        => 'attachments | encoded_string',
35        ],
36    );
37}
38
39has view_template => (
40    is          => 'ro',
41    isa         => class_type('Template::Pure'),
42    lazy        => 1,
43    builder     => '_build_view_template',
44);
45
46sub _build_view_template {
47    shift->prepare_template(
48
1
28
        template   => 'page/view.html',
49        directives => [
50            '#yukkitext' => 'html | encoded_string',
51        ],
52    );
53}
54
55has history_template => (
56    is          => 'ro',
57    isa         => class_type('Template::Pure'),
58    lazy        => 1,
59    builder     => '_build_history_template',
60);
61
62sub _build_history_template {
63    shift->prepare_template(
64        template   => 'page/history.html',
65        directives => [
66            'form@action' => 'form_action',
67            '.revision'   => {
68                'rev<-revisions' => [
69                    '.first-revision input@value'  => 'rev.object_id',
70                    '.second-revision input@value' => 'rev.object_id',
71                    '.date'                        => 'rev.time_ago',
72                    '.author'                      => 'rev.author_name',
73                    '.diffstat'                    => '+={rev.lines_added}/-={rev.lines_removed}',
74                    '.comment'                     => 'rev.comment | default("(no comment)")',
75                    '.first-revision input'        => sub {
76
0
0
                        my ($t, $input, $vars) = @_;
77                        $input->attr(checked => 'checked')
78
0
0
                            if $vars->{index} == 2;
79                    },
80                    '.second-revision input'       => sub {
81
0
0
                        my ($t, $input, $vars) = @_;
82                        $input->attr(checked => 'checked')
83
0
0
                            if $vars->{index} == 1;
84                    },
85
0
0
                ],
86            },
87        ],
88    );
89}
90
91has diff_template => (
92    is          => 'ro',
93    isa         => class_type('Template::Pure'),
94    lazy        => 1,
95    builder     => '_build_diff_template',
96);
97
98sub _build_diff_template {
99    shift->prepare_template(
100
0
0
        template   => 'page/diff.html',
101        directives => [
102            '#diff' => 'html | encoded_string',
103        ],
104    );
105}
106
107has edit_template => (
108    is          => 'ro',
109    isa         => class_type('Template::Pure'),
110    lazy        => 1,
111    builder     => '_build_edit_template',
112);
113
114sub _build_edit_template {
115    shift->prepare_template(
116
0
0
        template   => 'page/edit.html',
117        directives => [
118            '#yukkiname'                => 'page',
119            '#yukkitext'                => 'source',
120            '#yukkitext_position@value' => 'position',
121            '#preview-yukkitext'        => 'html | encoded_string',
122            '#attachments-list'         => 'attachments | encoded_string',
123        ],
124    );
125}
126
127has rename_template => (
128    is          => 'ro',
129    isa         => class_type('Template::Pure'),
130    lazy        => 1,
131    builder     => '_build_rename_template',
132);
133
134sub _build_rename_template {
135    shift->prepare_template(
136
0
0
        template   => 'page/rename.html',
137        directives => [
138            '#yukkiname'           => 'page',
139            '#yukkiname_new@value' => 'page',
140        ],
141    );
142}
143
144has remove_template => (
145    is          => 'ro',
146    isa         => class_type('Template::Pure'),
147    lazy        => 1,
148    builder     => '_build_remove_template',
149);
150
151sub _build_remove_template {
152    shift->prepare_template(
153
0
0
        template   => 'page/remove.html',
154        directives => [
155            '.yukkiname'          => 'page',
156            '#cancel_remove@href' => 'return_link',
157        ],
158    );
159}
160
161has attachments_template => (
162    is          => 'ro',
163    isa         => class_type('Template::Pure'),
164    lazy        => 1,
165    builder     => '_build_attachments_template',
166);
167
168sub _build_attachments_template {
169    shift->prepare_template(
170
0
0
        template   => 'page/attachments.html',
171        directives => [
172            '.file' => {
173                'file<-files' => [
174                    '@id'       => 'file.file_id',
175                    '.filename' => 'file.file_name | encoded_string',
176                    '.size'     => 'file.file_size',
177                    '.action'   => 'file.action | encoded_string',
178                ],
179            },
180        ],
181    );
182}
183
184 - 191
=head1 METHODS

=head2 blank

Renders a page that links to the edit page for this location. This helps you
create the links.

=cut
192
193sub blank {
194
0
1
0
    my ($self, $ctx, $vars) = @_;
195
196
0
0
    my $link = "/page/edit/$vars->{repository}/$vars->{page}";
197
198
0
0
    $ctx->response->page_title($vars->{title});
199
0
0
    $ctx->response->breadcrumb($vars->{breadcrumb});
200
201    return $self->render_page(
202        template => $self->blank_template,
203        context  => $ctx,
204        vars     => {
205            page        => $vars->{page},
206            link        => $link,
207
0
0
            attachments => $self->attachments($ctx, $vars->{files}),
208        },
209    );
210}
211
212 - 216
=head2 page_navigation

Sets up the page navigation menu.

=cut
217
218sub page_navigation {
219
1
1
14
    my ($self, $response, $this_action, $vars) = @_;
220
221
1
4
    for my $action (qw( edit history rename remove )) {
222
4
21
        next if $action eq $this_action;
223
224        $response->add_navigation_item([ qw( page page_bottom ) ] => {
225            label => ucfirst $action,
226
4
24
            href  => join('/', 'page', $action, $vars->{repository}, $vars->{page}),
227            sort  => 20,
228        });
229    }
230
231
1
1
7
38
    for my $view_name (keys %{ $self->app->settings->page_views }) {
232
3
55
        my $view_info = $self->app->settings->page_views->{$view_name};
233
234
3
22
        next if $view_info->{hide};
235
236
2
5
        my $args = "?view=$view_name";
237
2
6
           $args = '' if $view_name eq 'default';
238
239        $response->add_navigation_item([ qw( page page_bottom ) ] => {
240            label => $view_info->{label},
241            href  => join('/', 'page/view', $vars->{repository}, $vars->{page})
242                   . $args,
243            sort  => $view_info->{sort},
244
2
13
        });
245    }
246}
247
248 - 252
=head2 view

Renders a page as a view.

=cut
253
254sub view {
255
1
1
6
    my ($self, $ctx, $vars) = @_;
256
1
5
    my $file = $vars->{file};
257
258
1
54
    $ctx->response->page_title($vars->{title});
259
1
80
    $ctx->response->breadcrumb($vars->{breadcrumb});
260
261
1
77
    my $html = $file->fetch_formatted($ctx, -1);
262
263
1
26
    $self->page_navigation($ctx->response, 'view', $vars);
264
265
1
23
    return $self->render_page(
266        template => $self->view_template,
267        context  => $ctx,
268        vars     => {
269            'html' => $html,
270        },
271    );
272}
273
274 - 278
=head2 history

Display the history for a page.

=cut
279
280sub history {
281
0
1
    my ($self, $ctx, $vars) = @_;
282
283
0
    $ctx->response->page_title($vars->{title});
284
0
    $ctx->response->breadcrumb($vars->{breadcrumb});
285
286
0
    $self->page_navigation($ctx->response, 'history', $vars);
287
288
0
    my $i = 0;
289    return $self->render_page(
290        template => $self->history_template,
291        context  => $ctx,
292        vars     => {
293            'form_action' => join('/', '/page/diff', $vars->{repository}, $vars->{page}),
294            'revisions'   => $vars->{revisions},
295        },
296
0
    );
297}
298
299 - 303
=head2 diff

Display a diff for a file.

=cut
304
305sub diff {
306
0
1
    my ($self, $ctx, $vars) = @_;
307
0
    my $file = $vars->{file};
308
309
0
    $ctx->response->page_title($vars->{title});
310
0
    $ctx->response->breadcrumb($vars->{breadcrumb});
311
312
0
    $self->page_navigation($ctx->response, 'diff', $vars);
313
314
0
    my $html = $file->fetch_formatted($ctx);
315
316
0
    return $self->render_page(
317        template => $self->diff_template,
318        context  => $ctx,
319        vars     => {
320            html => $html,
321        },
322    );
323}
324
325 - 329
=head2 edit

Renders the editor for a page.

=cut
330
331sub edit {
332
0
1
    my ($self, $ctx, $vars) = @_;
333
0
    my $file = $vars->{file};
334
335
0
    $ctx->response->page_title($vars->{title});
336
0
    $ctx->response->breadcrumb($vars->{breadcrumb});
337
338
0
    my $html = $file->fetch_formatted($ctx, $vars->{position});
339
340
0
    $self->page_navigation($ctx->response, 'edit', $vars);
341
342    return $self->render_page(
343        template => $self->edit_template,
344        context  => $ctx,
345        vars     => {
346            page        => $vars->{page},
347            source      => scalar $vars->{file}->fetch // '',
348            position    => $vars->{position},
349            html        => $html,
350
0
            attachments => $self->attachments($ctx, $vars->{attachments}),
351        },
352    );
353}
354
355 - 359
=head2 rename

Renders the rename form for a page.

=cut
360
361sub rename {
362
0
1
    my ($self, $ctx, $vars) = @_;
363
0
    my $file = $vars->{file};
364
365
0
    $ctx->response->page_title($vars->{title});
366
0
    $ctx->response->breadcrumb($vars->{breadcrumb});
367
368    $self->page_navigation($ctx->response, 'rename', $vars)
369
0
        unless $ctx->request->path_parameters->{file};
370
371    return $self->render_page(
372        template => $self->rename_template,
373        context  => $ctx,
374        vars     => {
375            page => $vars->{page},
376        },
377
0
    );
378}
379
380 - 384
=head2 remove

Renders the remove confirmation page.

=cut
385
386sub remove {
387
0
1
    my ($self, $ctx, $vars) = @_;
388
0
    my $file = $vars->{file};
389
390
0
    $ctx->response->page_title($vars->{title});
391
0
    $ctx->response->breadcrumb($vars->{breadcrumb});
392
393    $self->page_navigation($ctx->response, 'remove', $vars)
394
0
        unless $ctx->request->path_parameters->{file};
395
396    return $self->render_page(
397        template => $self->remove_template,
398        context  => $ctx,
399        vars     => {
400            page        => $vars->{page},
401            return_link => $vars->{return_link},
402        },
403
0
    );
404}
405
406 - 410
=head2 attachments

Renders the attachments table.

=cut
411
412sub attachments {
413
0
1
    my ($self, $ctx, $attachments) = @_;
414
415    return $self->render(
416        template   => $self->attachments_template,
417        context    => $ctx,
418        vars       => {
419            files => @$attachments ? [ map {
420
0
0
                my @links = $self->attachment_links($ctx, $_);
421
422
0
0
                my %primary_link = %{ $links[0] };
423
0
                $primary_link{label} = $_->file_name;
424
425
0
                my $file_name = $self->render_links(
426                    context => $ctx,
427                    links   => [ \%primary_link ],
428                );
429
430                {
431
0
                    file_id   => $_->file_id,
432                    file_name => $file_name,
433                    file_size => $_->formatted_file_size,
434                    action    => $self->render_attachment_links($ctx, \@links),
435                }
436            } @$attachments ] : undef,
437        },
438    );
439}
440
441 - 443
=head2 attachment_links

=cut
444
445sub attachment_links {
446
0
1
    my ($self, $ctx, $attachment) = @_;
447
448
0
    my @links;
449
450
0
    if ($attachment->has_format) {
451
0
        push @links, {
452            label => 'View',
453            href  => join('/', 'page', 'view',
454                    $attachment->repository_name,
455                    $attachment->full_path),
456        };
457    }
458    else {
459
0
        push @links, {
460            label => 'View',
461            href  => join('/', 'attachment', 'view',
462                    $attachment->repository_name,
463                    $attachment->full_path),
464        } if $attachment->media_type ne 'application/octet';
465
466
0
        push @links, {
467            label => 'Download',
468            href  => join('/', 'attachment', 'download',
469                    $attachment->repository_name,
470                    $attachment->full_path),
471        };
472    }
473
474
0
    push @links, {
475        label => 'Rename',
476        href  => join('/', 'attachment', 'rename',
477                $attachment->repository_name,
478                $attachment->full_path),
479    };
480
481
0
    push @links, {
482        label => 'Remove',
483        href  => join('/', 'attachment', 'remove',
484                $attachment->repository_name,
485                $attachment->full_path),
486    };
487
488
0
    return @links;
489}
490
491 - 495
=head2 render_attachment_links

Renders the links listed in the action column of the attachments table.

=cut
496
497sub render_attachment_links {
498
0
1
    my ($self, $ctx, $links) = @_;
499
0
    return $self->render_links(context => $ctx, links => $links);
500}
501
502 - 506
=head2 preview

Renders a preview of an edit in progress.

=cut
507
508sub preview {
509
0
1
    my ($self, $ctx, $vars) = @_;
510
0
    my $file = $vars->{file};
511
512
0
    my $html = $file->fetch_formatted($ctx);
513
514
0
    return $html;
515}
516
5171;