From 93b79ef9ebafcfccd0d239ffd06e2b547e209e3d Mon Sep 17 00:00:00 2001 From: Yorhel Date: Thu, 8 Feb 2018 16:06:17 +0100 Subject: Store d+ pages in the DB as versioned entries + use markdown This touches a bunch of things: - Adds a new first-class database entry type - Removes the d+.+.+ BBCode link syntax, adds a new d+#+ and d+#+.+ link syntax (references have been updated where possible) - Adds a new dependency on Text::MultiMarkdown --- lib/VNDB/BBCode.pm | 8 +- lib/VNDB/DB/Docs.pm | 53 ++++++++++++ lib/VNDB/DB/Misc.pm | 4 +- lib/VNDB/Handler/Discussions.pm | 4 +- lib/VNDB/Handler/Docs.pm | 177 ++++++++++++++++++++++++++++++++++++++++ lib/VNDB/Handler/Misc.pm | 84 +++---------------- lib/VNDB/Handler/VNEdit.pm | 2 +- lib/VNDB/Util/CommonHTML.pm | 10 ++- lib/VNDB/Util/FormHTML.pm | 4 +- 9 files changed, 259 insertions(+), 87 deletions(-) create mode 100644 lib/VNDB/DB/Docs.pm create mode 100644 lib/VNDB/Handler/Docs.pm (limited to 'lib/VNDB') diff --git a/lib/VNDB/BBCode.pm b/lib/VNDB/BBCode.pm index d2f3135d..7ddfcd1b 100644 --- a/lib/VNDB/BBCode.pm +++ b/lib/VNDB/BBCode.pm @@ -14,7 +14,7 @@ our @EXPORT = qw/bb2html bb2text/; # [url=..] [/url] # [raw] .. [/raw] # link: http://../ -# dblink: v#, v#.#, d#.#.# +# dblink: v+, v+.+, d+#+, d+#+.+ # # Permitted nesting of formatting codes: # spoiler -> url, raw, link, dblink @@ -112,9 +112,9 @@ sub parse { while($raw =~ m{(?: \[ \/? (?i: spoiler|quote|code|url|raw ) [^\s\]]* \] | # tag - d[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]* | # d#.#.# - [tdvprcs][1-9][0-9]*\.[1-9][0-9]* | # v#.# - [tdvprcsugi][1-9][0-9]* | # v# + d[1-9][0-9]* \# [1-9][0-9]* (?: \.[1-9][0-9]* )? | # d+#+[.+] + [tdvprcs][1-9][0-9]*\.[1-9][0-9]* | # v+.+ + [tdvprcsugi][1-9][0-9]* | # v+ (?:https?|ftp)://[^><"\n\s\]\[]+[\d\w=/-] # link )}xg) { my $token = $&; diff --git a/lib/VNDB/DB/Docs.pm b/lib/VNDB/DB/Docs.pm new file mode 100644 index 00000000..27cabf6e --- /dev/null +++ b/lib/VNDB/DB/Docs.pm @@ -0,0 +1,53 @@ + +package VNDB::DB::Docs; + +use strict; +use warnings; +use Exporter 'import'; + +our @EXPORT = qw|dbDocGet dbDocGetRev dbDocRevisionInsert|; + + +# Can only fetch a single document. +# $doc = $self->dbDocGet(id => $id); +sub dbDocGet { + my $self = shift; + my %o = @_; + + my $r = $self->dbAll('SELECT id, title, content FROM docs WHERE id = ?', $o{id}); + return wantarray ? ($r, 0) : $r; +} + + +# options: id, rev +sub dbDocGetRev { + my $self = shift; + my %o = @_; + + $o{rev} ||= $self->dbRow('SELECT MAX(rev) AS rev FROM changes WHERE type = \'d\' AND itemid = ?', $o{id})->{rev}; + + my $r = $self->dbAll(q| + SELECT de.id, d.title, d.content, de.hidden, de.locked, + extract('epoch' from c.added) as added, c.requester, c.comments, u.username, c.rev, c.ihid, c.ilock, c.id AS cid, + NOT EXISTS(SELECT 1 FROM changes c2 WHERE c2.type = c.type AND c2.itemid = c.itemid AND c2.rev = c.rev+1) AS lastrev + FROM changes c + JOIN docs de ON de.id = c.itemid + JOIN docs_hist d ON d.chid = c.id + JOIN users u ON u.id = c.requester + WHERE c.type = 'd' AND c.itemid = ? AND c.rev = ?|, + $o{id}, $o{rev} + ); + return wantarray ? ($r, 0) : $r; +} + + +# Updates the edit_* tables, used from dbItemEdit() +# Arguments: { title content }, +sub dbDocRevisionInsert { + my($self, $o) = @_; + my %set = map exists($o->{$_}) ? (qq|"$_" = ?|, $o->{$_}) : (), qw|title content|; + $self->dbExec('UPDATE edit_docs !H', \%set) if keys %set; +} + + +1; diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm index d6389376..61bb71a2 100644 --- a/lib/VNDB/DB/Misc.pm +++ b/lib/VNDB/DB/Misc.pm @@ -21,7 +21,7 @@ sub dbStats { # Inserts a new revision into the database -# Arguments: type [vrp], itemid, rev, %options->{ editsum uid ihid ilock + db[item]RevisionInsert } +# Arguments: type [vrpcsd], itemid, rev, %options->{ editsum uid ihid ilock + db[item]RevisionInsert } # rev = changes.rev of the revision this edit is based on, undef to create a new DB item # Returns: { itemid, chid, rev } sub dbItemEdit { @@ -41,6 +41,7 @@ sub dbItemEdit { $self->dbReleaseRevisionInsert( \%o) if $type eq 'r'; $self->dbCharRevisionInsert( \%o) if $type eq 'c'; $self->dbStaffRevisionInsert( \%o) if $type eq 's'; + $self->dbDocRevisionInsert( \%o) if $type eq 'd'; return $self->dbRow('SELECT * FROM edit_!s_commit()', $type); } @@ -98,6 +99,7 @@ sub dbRevisionGet { UNION ALL SELECT 'r'::dbentry_type, chid, title, original FROM releases_hist UNION ALL SELECT 'p'::dbentry_type, chid, name, original FROM producers_hist UNION ALL SELECT 'c'::dbentry_type, chid, name, original FROM chars_hist + UNION ALL SELECT 'd'::dbentry_type, chid, title, '' AS original FROM docs_hist UNION ALL SELECT 's'::dbentry_type, sh.chid, name, original FROM staff_hist sh JOIN staff_alias_hist sah ON sah.chid = sh.chid AND sah.aid = sh.aid ) x(type, id, title, original) WHERE $w diff --git a/lib/VNDB/Handler/Discussions.pm b/lib/VNDB/Handler/Discussions.pm index f7f26a5e..f6b68c36 100644 --- a/lib/VNDB/Handler/Discussions.pm +++ b/lib/VNDB/Handler/Discussions.pm @@ -304,7 +304,7 @@ sub edit { !$tid || $num == 1 ? ( [ input => short => 'title', name => 'Thread title' ], [ input => short => 'boards', name => 'Board(s)' ], - [ static => content => 'Read d9.2 for information about how to specify boards.' ], + [ static => content => 'Read d9#2 for information about how to specify boards.' ], $self->authCan('boardmod') ? ( [ check => name => 'Locked', short => 'locked' ], ) : (), @@ -318,7 +318,7 @@ sub edit { ) : (), ) : (), [ text => name => 'Message
English please!', short => 'msg', rows => 25, cols => 75 ], - [ static => content => 'See d9.3 for the allowed formatting codes' ], + [ static => content => 'See d9#3 for the allowed formatting codes' ], (!$tid || $num == 1) ? ( [ static => content => '
' ], [ check => short => 'poll', name => 'Add poll' ], diff --git a/lib/VNDB/Handler/Docs.pm b/lib/VNDB/Handler/Docs.pm new file mode 100644 index 00000000..bc1166d5 --- /dev/null +++ b/lib/VNDB/Handler/Docs.pm @@ -0,0 +1,177 @@ + +package VNDB::Handler::Docs; + + +use strict; +use warnings; +use TUWF ':html'; +use VNDB::Func; +use Text::MultiMarkdown 'markdown'; + + +TUWF::register( + qr{d([1-9]\d*)(?:\.([1-9]\d*))?} => \&page, + qr{d([1-9]\d*)(?:\.([1-9]\d*))?/edit} => \&edit, +); + + +sub _html { + my $content = shift; + + $content =~ s{^:MODERATORS:$}{ + my $l = tuwf->dbUserGet(results => 100, sort => 'id', notperm => tuwf->{default_perm}, what => 'extended'); + my $admin = 0; + $admin |= $_ for values %{ tuwf->{permissions} }; + '
'.join('', map { + my $u = $_; + my $p = $u->{perm} >= $admin ? 'admin' : join ', ', sort map +($u->{perm} &~ tuwf->{default_perm}) & tuwf->{permissions}{$_} ? $_ : (), keys %{ tuwf->{permissions} }; + $p ? sprintf('
%s
%s
', $_->{id}, $_->{username}, $p) : () + } @$l).'
'; + }me; + $content =~ s{^:SKINCONTRIB:$}{ + my %users; + push @{$users{ tuwf->{skins}{$_}[1] }}, [ $_, tuwf->{skins}{$_}[0] ] + for sort { tuwf->{skins}{$a}[0] cmp tuwf->{skins}{$b}[0] } keys %{ tuwf->{skins} }; + my $u = tuwf->dbUserGet(uid => [ keys %users ]); + '
'.join('', map sprintf('
%s
%s
', + $_->{id}, $_->{username}, join(', ', map sprintf('%s', $_->[0], $_->[1]), @{$users{$_->{id}}}) + ), @$u).'
'; + }me; + + my $html = markdown $content, { + strip_metadata => 1, + img_ids => 0, + disable_footnotes => 1, + disable_bibliography => 1, + }; + + # Number sections and turn them into links + my($sec, $subsec) = (0,0); + $html =~ s{]+>(.*?)}{ + if($1 == 1) { + $sec++; + $subsec = 0; + qq{

$sec. $2

} + } elsif($1 == 2) { + $subsec++; + qq|

$sec.$subsec. $2

\n| + } + }ge; + + # Text::MultiMarkdown doesn't handle fenced code blocks properly. The + # following solution breaks inline code blocks, but I don't use those anyway. + $html =~ s//
/g;
+  $html =~ s##
#g; + + $html +} + + +sub page { + my($self, $id, $rev) = @_; + + my $method = $rev ? 'dbDocGetRev' : 'dbDocGet'; + my $d = $self->$method(id => $id, $rev ? ( rev => $rev ) : ())->[0]; + return $self->resNotFound if !$d->{id}; + + $self->htmlHeader(title => $d->{title}, noindex => $rev); + $self->htmlMainTabs(d => $d); + return if $self->htmlHiddenMessage('d', $d); + + if($rev) { + my $prev = $rev && $rev > 1 && $self->dbDocGetRev(id => $id, rev => $rev-1)->[0]; + $self->htmlRevision('d', $prev, $d, + [ title => 'Title', diff => 1 ], + [ content => 'Content', diff => qr/\s+/ ], + ); + } + + div class => 'mainbox'; + h1 $d->{title}; + div class => 'docs'; + ul class => 'index'; + li; b 'Guidelines'; end; + li; a href => '/d5', 'Editing Guidelines'; end; + li; a href => '/d2', 'Visual Novels'; end; + li; a href => '/d15', 'Special Games'; end; + li; a href => '/d3', 'Releases'; end; + li; a href => '/d4', 'Producers'; end; + li; a href => '/d16', 'Staff'; end; + li; a href => '/d12', 'Characters'; end; + li; a href => '/d10', 'Tags & Traits'; end; + li; a href => '/d13', 'Capturing Screenshots'; end; + li; b 'About VNDB'; end; + li; a href => '/d9', 'Discussion Board'; end; + li; a href => '/d6', 'FAQ'; end; + li; a href => '/d7', 'About Us'; end; + li; a href => '/d11', 'Database API'; end; + li; a href => '/d14', 'Database Dumps'; end; + end; + lit _html $d->{content}; + end; + end; + $self->htmlFooter; +} + + +sub edit { + my($self, $id, $rev) = @_; + + my $d = $self->dbDocGetRev(id => $id, rev => $rev)->[0]; + return $self->resNotFound if !$d->{id}; + $rev = undef if $d->{lastrev}; + + return $self->htmlDenied if !$self->authCan('dbmod'); + + my %b4 = map { $_ => $d->{$_} } qw|title content ihid ilock|; + my $frm; + + if($self->reqMethod eq 'POST') { + return if !$self->authCheckCode; + $frm = $self->formValidate( + { post => 'title', maxlength => 200 }, + { post => 'content', }, + { post => 'editsum', template => 'editsum' }, + { post => 'ihid', required => 0 }, + { post => 'ilock', required => 0 }, + { post => 'preview', required => 0 }, + ); + if(!$frm->{_err} && !$frm->{preview}) { + $frm->{ihid} = $frm->{ihid}?1:0; + $frm->{ilock} = $frm->{ilock}?1:0; + + return $self->resRedirect("/d$id", 'post') if !form_compare(\%b4, $frm); + my $nrev = $self->dbItemEdit(d => $id, $d->{rev}, %$frm); + return $self->resRedirect("/d$nrev->{itemid}.$nrev->{rev}", 'post'); + } + } + + !defined $frm->{$_} && ($frm->{$_} = $b4{$_}) for keys %b4; + $frm->{editsum} = sprintf 'Reverted to revision d%d.%d', $id, $rev if $rev && !defined $frm->{editsum}; + delete $frm->{_err} if $frm->{preview}; + + my $title = "Edit $d->{title}"; + $self->htmlHeader(title => $title, noindex => 1); + $self->htmlMainTabs('d', $d, 'edit'); + + if($frm->{preview}) { + div class => 'mainbox'; + h1 'Preview'; + div class => 'docs'; + lit _html $frm->{content}; + end; + end; + } + + $self->htmlForm({ frm => $frm, action => "/d$id/edit", editsum => 1, preview => 1 }, dedit => [ $title, + [ input => name => 'Title', short => 'title', width => 300 ], + [ static => nolabel => 1, content => q{ +
Contents (HTML and MultiMarkdown supported, which is + Markdown + with some extensions).} ], + [ textarea => short => 'content', name => 'Content', rows => 50, cols => 90, nolabel => 1 ], + ]); + $self->htmlFooter; +} + +1; diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index e3b67d52..771c9d83 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -4,18 +4,16 @@ package VNDB::Handler::Misc; use strict; use warnings; -use TUWF ':html', ':xml', 'xml_escape', 'uri_escape'; +use TUWF ':html', ':xml', 'uri_escape'; use VNDB::Func; -use POSIX 'strftime'; TUWF::register( - qr{}, \&homepage, - qr{(?:([upvrcs])([1-9]\d*)/)?hist},\&history, - qr{d([1-9]\d*)}, \&docpage, - qr{nospam}, \&nospam, - qr{xml/prefs\.xml}, \&prefs, - qr{opensearch\.xml}, \&opensearch, + qr{}, \&homepage, + qr{(?:([upvrcsd])([1-9]\d*)/)?hist},\&history, + qr{nospam}, \&nospam, + qr{xml/prefs\.xml}, \&prefs, + qr{opensearch\.xml}, \&opensearch, # redirects for old URLs qr{u([1-9]\d*)/tags}, sub { $_[0]->resRedirect("/g/links?u=$_[1]", 'perm') }, @@ -28,8 +26,6 @@ TUWF::register( sub { $_[0]->resRedirect("/v$_[1]", 'perm') }, qr{u/list(/[a-z0]|/all)?}, sub { my $l = defined $_[1] ? $_[1] : '/all'; $_[0]->resRedirect("/u$l", 'perm') }, - qr{d([1-9]\d*)\.([1-9]\d*)}, - sub { $_[0]->resRedirect("/d$_[1]#$_[2]", 'perm') } ); @@ -206,7 +202,7 @@ sub history { { get => 'p', required => 0, default => 1, template => 'page' }, { get => 'm', required => 0, default => !$type, enum => [ 0, 1 ] }, { get => 'h', required => 0, default => 0, enum => [ -1..1 ] }, - { get => 't', required => 0, default => '', enum => [qw|v r p c s a|] }, + { get => 't', required => 0, default => '', enum => [qw|v r p c s d a|] }, { get => 'e', required => 0, default => 0, enum => [ -1..1 ] }, { get => 'r', required => 0, default => 0, enum => [ 0, 1 ] }, ); @@ -218,6 +214,7 @@ sub history { $type eq 'r' ? $self->dbReleaseGet(id => $id)->[0] : $type eq 'c' ? $self->dbCharGet(id => $id)->[0] : $type eq 's' ? $self->dbStaffGet(id => $id)->[0] : + $type eq 'd' ? $self->dbDocGet(id => $id)->[0] : $type eq 'v' ? $self->dbVNGet(id => $id)->[0] : undef; return $self->resNotFound if $type && !$obj->{id}; my $title = $type ? 'Edit history of '.($obj->{title} || $obj->{name} || $obj->{username}) : 'Recent changes'; @@ -226,7 +223,7 @@ sub history { my($list, $np) = $self->dbRevisionGet( $type && $type ne 'u' ? ( type => $type, itemid => $id ) : (), $type eq 'u' ? ( uid => $id ) : (), - $f->{t} ? ( type => $f->{t} eq 'a' ? [qw|v r p s|] : $f->{t} ) : (), + $f->{t} ? ( type => $f->{t} eq 'a' ? [qw|v r p s d|] : $f->{t} ) : (), page => $f->{p}, results => 50, auto => $f->{m}, @@ -273,6 +270,7 @@ sub history { a $f->{t} eq 'p' ? (class => 'optselected') : (), href => $u->(t => 'p'), 'Only producers'; a $f->{t} eq 's' ? (class => 'optselected') : (), href => $u->(t => 's'), 'Only staff'; a $f->{t} eq 'c' ? (class => 'optselected') : (), href => $u->(t => 'c'), 'Only characters'; + a $f->{t} eq 'd' ? (class => 'optselected') : (), href => $u->(t => 'd'), 'Only docs'; a $f->{t} eq 'a' ? (class => 'optselected') : (), href => $u->(t => 'a'), 'All except characters'; end; p class => 'browseopts'; @@ -294,68 +292,6 @@ sub history { } -sub docpage { - my($self, $did) = @_; - - my $f = sprintf('%s/data/docs/%d', $VNDB::ROOT, $did); - my $F; - open($F, '<:utf8', $f) or return $self->resNotFound; - my @c = <$F>; - close $F; - - (my $title = shift @c) =~ s/^:TITLE://; - chomp $title; - - my($sec, $subsec) = (0,0); - for (@c) { - s{^:SUB:(.+)\r?\n$}{ - $sec++; - $subsec = 0; - qq|

$sec. $1

\n| - }e; - s{^:SUBSUB:(.+)\r?\n$}{ - $subsec++; - qq|

$sec.$subsec. $1

\n| - }e; - s{^:INC:(.+)\r?\n$}{ - $f = sprintf('%s/data/docs/%s', $VNDB::ROOT, $1); - open($F, '<:utf8', $f) or die $!; - my $ii = join('', <$F>); - close $F; - $ii; - }e; - s{^:MODERATORS:$}{ - my $l = $self->dbUserGet(results => 100, sort => 'id', notperm => $self->{default_perm}, what => 'extended'); - my $admin = 0; - $admin |= $_ for values %{$self->{permissions}}; - '
'.join('', map { - my $u = $_; - my $p = $u->{perm} >= $admin ? 'admin' : join ', ', sort map +($u->{perm} &~ $self->{default_perm}) & $self->{permissions}{$_} ? $_ : (), keys %{$self->{permissions}}; - $p ? sprintf('
%s
%s
', $_->{id}, $_->{username}, $p) : () - } @$l).'
'; - }e; - s{^:SKINCONTRIB:$}{ - my %users; - push @{$users{ $self->{skins}{$_}[1] }}, [ $_, $self->{skins}{$_}[0] ] - for sort { $self->{skins}{$a}[0] cmp $self->{skins}{$b}[0] } keys %{$self->{skins}}; - my $u = $self->dbUserGet(uid => [ keys %users ]); - '
'.join('', map sprintf('
%s
%s
', - $_->{id}, $_->{username}, join(', ', map sprintf('%s', $_->[0], $_->[1]), @{$users{$_->{id}}}) - ), @$u).'
'; - }e; - } - - $self->htmlHeader(title => $title); - div class => 'mainbox'; - h1 $title; - div class => 'docs'; - lit join '', @c; - end; - end; - $self->htmlFooter; -} - - sub nospam { my $self = shift; $self->htmlHeader(title => 'Could not send form', noindex => 1); diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index ce10611d..e08925f7 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -319,7 +319,7 @@ sub _form { @alist ? @{$self->dbStaffGet(aid => \@alist, results => 200)} : () }; div class => 'warning'; - lit 'Please check the staff editing guidelines. You can' + lit 'Please check the staff editing guidelines. You can' .' create a new staff entry if it is not in the database yet,' .' but please check for aliasses first.'; end; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index e8561e3c..dd129c18 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -18,7 +18,7 @@ our @EXPORT = qw| # generates the "main tabs". These are the commonly used tabs for # 'objects', i.e. VN/producer/release entries and users -# Arguments: u/v/r/p/g/i/c, object, currently selected item (empty=main) +# Arguments: u/v/r/p/g/i/c/d, object, currently selected item (empty=main) sub htmlMainTabs { my($self, $type, $obj, $sel) = @_; $sel ||= ''; @@ -27,7 +27,7 @@ sub htmlMainTabs { return if $type eq 'g' && !$self->authCan('tagmod'); ul class => 'maintabs'; - if($type =~ /[uvrpcs]/) { + if($type =~ /[uvrpcsd]/) { li $sel eq 'hist' ? (class => 'tabselected') : (); a href => "/$id/hist", 'history'; end; @@ -75,6 +75,7 @@ sub htmlMainTabs { if( $type eq 'u' && ($self->authInfo->{id} && $obj->{id} == $self->authInfo->{id} || $self->authCan('usermod')) || $type =~ /[vrpcs]/ && $self->authCan('edit') && ((!$obj->{locked} && !$obj->{hidden}) || $self->authCan('dbmod')) || $type =~ /[gi]/ && $self->authCan('tagmod') + || $type eq 'd' && $self->authCan('dbmod') ) { li $sel eq 'edit' ? (class => 'tabselected') : (); a href => "/$id/edit", 'edit'; @@ -132,12 +133,13 @@ sub htmlDenied { sub htmlHiddenMessage { my($self, $type, $obj) = @_; return 0 if !$obj->{hidden}; - my $board = $type =~ /[cs]/ ? 'db' : $type eq 'r' ? 'v'.$obj->{vn}[0]{vid} : $type.$obj->{id}; + my $board = $type =~ /[csd]/ ? 'db' : $type eq 'r' ? 'v'.$obj->{vn}[0]{vid} : $type.$obj->{id}; # fetch edit summary (not present in $obj, requires the db*GetRev() methods) my $editsum = $type eq 'v' ? $self->dbVNGetRev(id => $obj->{id})->[0]{comments} : $type eq 'r' ? $self->dbReleaseGetRev(id => $obj->{id})->[0]{comments} : $type eq 'c' ? $self->dbCharGetRev(id => $obj->{id})->[0]{comments} : $type eq 's' ? $self->dbStaffGetRev(id => $obj->{id})->[0]{comments} + : $type eq 'd' ? $self->dbDocGetRev(id => $obj->{id})->[0]{comments} : $self->dbProducerGetRev(id => $obj->{id})->[0]{comments}; div class => 'mainbox'; h1 $obj->{title}||$obj->{name}; @@ -156,7 +158,7 @@ sub htmlHiddenMessage { # Shows a revision, including diff if there is a previous revision. -# Arguments: v|p|r|c, old revision, new revision, @fields +# Arguments: v|p|r|c|d, old revision, new revision, @fields # Where @fields is a list of fields as arrayrefs with: # [ shortname, displayname, %options ], # Where %options: diff --git a/lib/VNDB/Util/FormHTML.pm b/lib/VNDB/Util/FormHTML.pm index a522599e..11de460b 100644 --- a/lib/VNDB/Util/FormHTML.pm +++ b/lib/VNDB/Util/FormHTML.pm @@ -54,7 +54,7 @@ sub htmlFormError { li "$field: Malformed data or invalid input" if $rule eq 'json'; li 'Invalid release date' if $rule eq 'rdate'; if($rule eq 'editsum') { - li; lit 'Please read the guidelines on how to use the edit summary.'; end; + li; lit 'Please read the guidelines on how to use the edit summary.'; end; } } } @@ -187,6 +187,7 @@ sub htmlFormPart { # nosubmit => 1/0, hides the submit button # editsum => 1/0, adds an edit summary field before the submit button # continue => 2/1/0, replace submit button with continue buttons +# preview => 1/0, add preview button # noformcode=> 1/0, remove the formcode field # The other arguments are a list of subforms in the form # of (subform-name => [form parts]). Each subform is shown as a @@ -265,6 +266,7 @@ sub htmlForm { input type => 'submit', name => 'continue_ign', value => 'Continue and ignore duplicates', class => 'submit', style => 'width: auto', tabindex => 10 if $options->{continue} == 2; } + input type => 'submit', value => 'Preview', id => 'preview', name => 'preview', class => 'submit', tabindex => 10 if $options->{preview}; end; end 'div'; } -- cgit v1.2.3