Should have committed earlier
Lots of changes: - Article about IPC - New TUWF release - New ncdu release - Atom feeds for the bug tracker - Bug tracker switch to sqlite
This commit is contained in:
parent
3b837d8564
commit
7cf772d968
33 changed files with 978 additions and 159 deletions
104
Bug.pm
104
Bug.pm
|
|
@ -2,34 +2,25 @@
|
|||
=head1 SQL Schema
|
||||
|
||||
CREATE TABLE $p (
|
||||
id SERIAL PRIMARY KEY,
|
||||
issue integer NOT NULL,
|
||||
date timestamptz NOT NULL DEFAULT NOW(),
|
||||
summary varchar(200) NOT NULL,
|
||||
type varchar NOT NULL DEFAULT '',
|
||||
status varchar NOT NULL DEFAULT '',
|
||||
closed boolean NOT NULL DEFAULT false,
|
||||
email varchar NOT NULL DEFAULT '',
|
||||
message varchar NOT NULL DEFAULT '',
|
||||
admin boolean NOT NULL DEFAULT false,
|
||||
name varchar(200) NOT NULL DEFAULT ''
|
||||
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
issue integer NOT NULL,
|
||||
date integer NOT NULL,
|
||||
name text DEFAULT '' NOT NULL,
|
||||
email text DEFAULT '' NOT NULL,
|
||||
admin integer DEFAULT 0 NOT NULL,
|
||||
closed integer DEFAULT 0 NOT NULL,
|
||||
type text DEFAULT '' NOT NULL,
|
||||
status text DEFAULT '' NOT NULL,
|
||||
summary text NOT NULL,
|
||||
message text DEFAULT '' NOT NULL
|
||||
);
|
||||
|
||||
=head2 Update queries
|
||||
|
||||
ALTER TABLE ${p}messages RENAME TO $p;
|
||||
DROP TABLE ${p}issues;
|
||||
|
||||
ALTER TABLE ${p}messages ADD COLUMN admin boolean NOT NULL DEFAULT false;
|
||||
ALTER TABLE ${p}messages ADD COLUMN name varchar(200) NOT NULL DEFAULT '';
|
||||
|
||||
=cut
|
||||
|
||||
# TODO: Atom feed?
|
||||
|
||||
package TUWF::Bug;
|
||||
|
||||
use TUWF ':html', 'html_escape';
|
||||
use TUWF ':xml', ':html', 'html_escape';
|
||||
use POSIX 'strftime';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
|
|
@ -58,7 +49,7 @@ sub dbListing {
|
|||
my %where = (
|
||||
'NOT EXISTS(SELECT 1 FROM !s im WHERE im.id > m.id AND im.issue = m.issue)' => $self->{table},
|
||||
$o{id} ? ('issue = ?' => $o{id}) : (),
|
||||
$o{closed} != 2 ? ('!s closed' => !$o{closed} ? 'NOT' : '') : (),
|
||||
$o{closed} != 2 ? ('closed = ?' => $o{closed}?1:0) : (),
|
||||
);
|
||||
|
||||
my $order = sprintf {
|
||||
|
|
@ -66,7 +57,7 @@ sub dbListing {
|
|||
}->{$o{sort}||'date'}, $o{reverse} ? 'DESC' : 'ASC';
|
||||
|
||||
my($r, $np) = $TUWF::OBJ->dbPage(\%o, q{
|
||||
SELECT issue, summary, to_char(date, 'YYYY-MM-DD') AS date, type, status, closed
|
||||
SELECT issue, summary, date, type, status, closed
|
||||
FROM !s m
|
||||
!W
|
||||
ORDER BY !s}, $self->{table}, \%where, $order
|
||||
|
|
@ -78,7 +69,7 @@ sub dbListing {
|
|||
sub dbItem {
|
||||
my($self, $id) = @_;
|
||||
return $TUWF::OBJ->dbAll(q{
|
||||
SELECT issue, summary, to_char(date, 'YYYY-MM-DD HH24:MI:SS (tz)') AS date, type, status, closed, name, admin, message
|
||||
SELECT issue, summary, date, type, status, closed, name, admin, message
|
||||
FROM !s
|
||||
WHERE issue = ?
|
||||
ORDER BY id}, $self->{table}, $id
|
||||
|
|
@ -86,6 +77,16 @@ sub dbItem {
|
|||
}
|
||||
|
||||
|
||||
sub dbRecent {
|
||||
my $self = shift;
|
||||
return $TUWF::OBJ->dbAll(q{
|
||||
SELECT issue, summary, date, name
|
||||
FROM !s
|
||||
ORDER BY id DESC LIMIT 10}, $self->{table}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
sub dbEmails {
|
||||
my($self, $id) = @_;
|
||||
return [ map $_->{email}, @{$TUWF::OBJ->dbAll(q|SELECT DISTINCT email FROM !s WHERE issue = ? AND email <> ''|, $self->{table}, $id)} ];
|
||||
|
|
@ -96,14 +97,13 @@ sub dbSave {
|
|||
my($self, $id, $closed, @a) = @_;
|
||||
|
||||
# TODO: Issue ID allocation may currently cause two bug reports created at
|
||||
# the same time to get the same id. It'd be better to use a PostgreSQL
|
||||
# sequence...
|
||||
# the same time to get the same id.
|
||||
my $issue = $id ? '?' : '(SELECT COALESCE(MAX(issue)+1, 1) FROM !s)';
|
||||
|
||||
return $TUWF::OBJ->dbRow(
|
||||
"INSERT INTO !s (issue, closed, summary, name, email, type, status, message, admin) VALUES ($issue, ?, !l) RETURNING issue",
|
||||
$self->{table}, $id || $self->{table}, $closed?1:0, \@a
|
||||
)->{issue}
|
||||
$TUWF::OBJ->dbExec(
|
||||
"INSERT INTO !s (issue, date, closed, summary, name, email, type, status, message, admin) VALUES ($issue, ?, ?, !l)",
|
||||
$self->{table}, $id || $self->{table}, time(), $closed?1:0, \@a);
|
||||
return $TUWF::OBJ->dbRow('SELECT MAX(issue) AS issue FROM !s', $self->{table})->{issue};
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ sub htmlListing {
|
|||
td class => 'bug_col_id', $_->{issue};
|
||||
td class => 'bug_col_type', $_->{type};
|
||||
td class => 'bug_col_status', $_->{status};
|
||||
td class => 'bug_col_date', $_->{date};
|
||||
td class => 'bug_col_date', strftime '%Y-%m-%d', gmtime $_->{date};
|
||||
td class => 'bug_col_summary';
|
||||
a href => $lnk->($_->{issue}), $_->{summary};
|
||||
end;
|
||||
|
|
@ -166,7 +166,8 @@ sub htmlItem {
|
|||
dl;
|
||||
dt !$num ? 'Created' : 'Added';
|
||||
dd;
|
||||
txt "$m->{date} by ";
|
||||
txt strftime '%Y-%m-%d %T GMT', gmtime $m->{date};
|
||||
txt ' by ';
|
||||
txt $m->{name}||'Anonymous' if !$m->{admin};
|
||||
b $m->{name}||'Admin' if $m->{admin};
|
||||
end;
|
||||
|
|
@ -251,15 +252,16 @@ sub htmlForm {
|
|||
sub handleForm {
|
||||
my($s, $url) = @_;
|
||||
my $f = $TUWF::OBJ->formValidate(
|
||||
{ post => 'bug_id', min => 0 },
|
||||
{ post => 'bug_id', template => 'uint' },
|
||||
{ post => 'bug_summary', maxlength => 200, minlength => 2 },
|
||||
{ post => 'bug_name', required => 0, default => '', maxlength => 200 },
|
||||
{ post => 'bug_email', required => 0, regex => qr/^[^@<>]+@[^@.<>]+(?:\.[^@.<>]+)+$/ },
|
||||
{ post => 'bug_email', required => 0, template => 'email' },
|
||||
{ post => 'bug_code', required => 0, default => '' },
|
||||
{ post => 'bug_message', maxlength => 256*1024, minlength => 1 },
|
||||
);
|
||||
return($f, undef) if $f->{_err};
|
||||
return({ _err => [['bug_summary']], %$f}, undef) if $f->{bug_summary} =~ qr{http://}; # SPAM
|
||||
return({ _err => [['bug_summary']], %$f}, undef) if $f->{bug_message} =~ qr{(?:<a href=|\[url=|\[link=)}i; # SPAM
|
||||
|
||||
$f->{bug_code} = '' if $f->{bug_code} eq 'code';
|
||||
my $admin = grep($_ eq $f->{bug_code}, @{$s->{admins}}) ? 1 : 0;
|
||||
|
|
@ -326,4 +328,36 @@ sub handleForm {
|
|||
}
|
||||
|
||||
|
||||
sub atomFeed {
|
||||
my($s, $lnk) = @_;
|
||||
|
||||
my $r = $s->dbRecent();
|
||||
my $t = $r->[0]{date}||1463296545;
|
||||
|
||||
$TUWF::OBJ->resHeader('Last-Modified' => strftime '%a, %d %b %Y %H:%M:%S GMT', gmtime $t);
|
||||
$TUWF::OBJ->resHeader('Content-Type' => 'application/atom+xml');
|
||||
xml;
|
||||
tag feed => xmlns => 'http://www.w3.org/2005/Atom', 'xml:lang' => 'en', 'xml:base' => 'https://dev.yorhel.nl/';
|
||||
tag title => "\u$s->{table} Recent Comments";
|
||||
tag updated => strftime('%Y-%m-%dT%H:%M:%SZ', gmtime $t);
|
||||
tag id => $lnk->('feed.atom');
|
||||
tag link => rel => 'self', type => 'application/atom+xml', href => $lnk->('feed.atom'), undef;
|
||||
tag link => rel => 'alternate', type => 'text/html', href => $lnk->(''), undef;
|
||||
|
||||
for(@$r) {
|
||||
my $d = strftime('%Y-%m-%dT%H:%M:%SZ', gmtime $_->{date});
|
||||
tag 'entry';
|
||||
tag id => $lnk->($_->{issue})."#$d";
|
||||
tag title => $_->{summary};
|
||||
tag updated => $d;
|
||||
tag published => $d;
|
||||
tag 'author';
|
||||
tag name => $_->{name};
|
||||
end;
|
||||
tag link => rel => 'alternate', type => 'text/html', href => $lnk->($_->{issue}), undef;
|
||||
end 'entry';
|
||||
}
|
||||
end 'feed';
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue