From d6865e7b42cc6f427b58d42a6cbd5a10cb3d112a Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 30 Mar 2012 13:50:56 +0200 Subject: [PATCH] s/issue/bug/g + updated ncdc-share-report --- Issue.pm => Bug.pm | 122 ++++++++++++++++++++++----------------------- dat/dump | 4 +- dat/ncdc-faq | 2 +- index.cgi | 74 ++++++++++++++------------- style.css | 38 +++++++------- 5 files changed, 121 insertions(+), 119 deletions(-) rename Issue.pm => Bug.pm (64%) diff --git a/Issue.pm b/Bug.pm similarity index 64% rename from Issue.pm rename to Bug.pm index 3c35a30..ec27808 100644 --- a/Issue.pm +++ b/Bug.pm @@ -22,7 +22,7 @@ # TODO: Atom feed? -package TUWF::Issue; +package TUWF::Bug; use TUWF ':html', 'html_escape'; @@ -100,21 +100,21 @@ sub dbSave { # TODO: pagination / filtering sub htmlListing { my($s, $l, $lnk) = @_; - table class => 'issue_listing'; + table class => 'bug_listing'; thead; Tr; - td class => 'issue_col_id', 'Id'; - td class => 'issue_col_type', 'Type'; - td class => 'issue_col_status', 'Status'; - td class => 'issue_col_date', 'Updated'; - td class => 'issue_col_summary','Summary'; + td class => 'bug_col_id', 'Id'; + td class => 'bug_col_type', 'Type'; + td class => 'bug_col_status', 'Status'; + td class => 'bug_col_date', 'Updated'; + td class => 'bug_col_summary','Summary'; end; end; for(@$l) { - Tr $_->{closed} ? (class => 'issue_closed') : (); - td class => 'issue_col_id', $_->{issue}; - td class => 'issue_col_type', $_->{type}; - td class => 'issue_col_status', $_->{status}; - td class => 'issue_col_date', $_->{date}; - td class => 'issue_col_summary'; + Tr $_->{closed} ? (class => 'bug_closed') : (); + 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_summary'; a href => $lnk->($_->{issue}), $_->{summary}; end; end; @@ -138,16 +138,16 @@ sub _escape_url { sub htmlItem { my($s, $d) = @_; my $last = $d->[$#$d]; - dl class => 'issue_status'; + dl class => 'bug_status'; dt 'Id'; dd $last->{issue}; dt 'Messages'; dd $#$d+1; dt 'Type'; dd $last->{type}; dt 'Status'; dd $last->{status}; end; - div class => 'issue_item'; + div class => 'bug_item'; my $num = -1; for my $m (@$d) { - div class => 'issue_message'; + div class => 'bug_message'; h1 !++$num ? 'Description' : "Reply $num"; dl; dt !$num ? 'Created' : 'Added'; dd $m->{date}; @@ -172,49 +172,49 @@ sub htmlItem { sub htmlForm { my($s, $l, $url) = @_; # TODO: anti-spam JS - form class => 'issue_frm', action => $url, method => 'post'; + form class => 'bug_frm', action => $url, method => 'post'; fieldset; - input type => 'hidden', name => 'issue_id', value => $l ? $l->{issue} : 0; - legend $l ? 'Reply' : 'Report a new issue'; + input type => 'hidden', name => 'bug_id', value => $l ? $l->{issue} : 0; + legend $l ? 'Reply' : 'Report a new bug'; ul; - li class => 'issue_frm_summary'; - label for => 'issue_summary', 'Summary'; - input type => 'text', name => 'issue_summary', id => 'issue_summary', size => 45, value => $l?$l->{summary}:''; + li class => 'bug_frm_summary'; + label for => 'bug_summary', 'Summary'; + input type => 'text', name => 'bug_summary', id => 'bug_summary', size => 45, value => $l?$l->{summary}:''; end; - li class => 'issue_frm_mail'; - label for => 'issue_email', 'Email'; - input type => 'text', name => 'issue_email', id => 'issue_email', size => 20; + li class => 'bug_frm_mail'; + label for => 'bug_email', 'Email'; + input type => 'text', name => 'bug_email', id => 'bug_email', size => 20; lit ' '; txt 'Optional, only used for notifications.'; end; if($l) { - li class => 'issue_frm_admin'; - label for => 'issue_type', 'Admin'; - Select name => 'issue_type'; + li class => 'bug_frm_admin'; + label for => 'bug_type', 'Admin'; + Select name => 'bug_type'; option value => $_, $_ eq $l->{type} ? (selected => 'selected') : (), $_ for @{$s->{types}}; end; - Select name => 'issue_status'; + Select name => 'bug_status'; option value => $_, $_ eq $l->{status} ? (selected => 'selected') : (), $_ for @{$s->{statusses}}; end; - Select name => 'issue_closed'; + Select name => 'bug_closed'; option value => 0, !$l->{closed} ? (selected => 'selected') : (), 'Open'; option value => 1, $l->{closed} ? (selected => 'selected') : (), 'Closed'; end; - input type => 'password', name => 'issue_code', id => 'issue_code', size => 10, value => 'code'; + input type => 'password', name => 'bug_code', id => 'bug_code', size => 10, value => 'code'; end; } else { - li class => 'issue_frm_type'; - label for => 'issue_type', 'Type'; - Select name => 'issue_type'; + li class => 'bug_frm_type'; + label for => 'bug_type', 'Type'; + Select name => 'bug_type'; option value => $_, $_ eq $s->{default_type} ? (selected => 'selected') : (), $_ for @{$s->{types}}; end; end; } - li class => 'issue_frm_message'; - textarea name => 'issue_message';end; br; + li class => 'bug_frm_message'; + textarea name => 'bug_message';end; br; lit 'Please use a pastebin if you want to include large chunks of code or program output.'; end; - li class => 'issue_frm_submit'; + li class => 'bug_frm_submit'; input type => 'submit', value => 'Submit'; end; end 'ul'; @@ -226,60 +226,60 @@ sub htmlForm { sub handleForm { my($s, $url) = @_; my $f = $TUWF::OBJ->formValidate( - { post => 'issue_id', min => 0 }, - { post => 'issue_summary', maxlength => 200, minlength => 2 }, - { post => 'issue_email', required => 0, regex => qr/^[^@<>]+@[^@.<>]+(?:\.[^@.<>]+)+$/ }, - { post => 'issue_code', required => 0, default => '' }, - { post => 'issue_message', maxlength => 256*1024, minlength => 1 }, + { post => 'bug_id', min => 0 }, + { post => 'bug_summary', maxlength => 200, minlength => 2 }, + { post => 'bug_email', required => 0, regex => qr/^[^@<>]+@[^@.<>]+(?:\.[^@.<>]+)+$/ }, + { post => 'bug_code', required => 0, default => '' }, + { post => 'bug_message', maxlength => 256*1024, minlength => 1 }, ); return($f, undef) if $f->{_err}; my $l; # Reply - if($f->{issue_id} > 0) { - $l = $s->dbListing(id => $f->{issue_id})->[0]; - push @{$f->{_err}}, ['issue_id', 'db_check', ''] and return($f, undef) if !$l; + if($f->{bug_id} > 0) { + $l = $s->dbListing(id => $f->{bug_id})->[0]; + push @{$f->{_err}}, ['bug_id', 'db_check', ''] and return($f, undef) if !$l; # Check admin things - if(grep $_ eq $f->{issue_code}, @{$s->{admins}}) { + if(grep $_ eq $f->{bug_code}, @{$s->{admins}}) { my $fa = $TUWF::OBJ->formValidate( - { post => 'issue_type', enum => $s->{types} }, - { post => 'issue_status', enum => $s->{statusses} }, - { post => 'issue_closed', enum => [0,1] }, + { post => 'bug_type', enum => $s->{types} }, + { post => 'bug_status', enum => $s->{statusses} }, + { post => 'bug_closed', enum => [0,1] }, ); $f = { %$f, %$fa }; return($f, $l) if $f->{_err}; } else { - $f->{issue_type} = $l->{type}; - $f->{issue_status} = $l->{status}; - $f->{issue_closed} = $l->{closed}; + $f->{bug_type} = $l->{type}; + $f->{bug_status} = $l->{status}; + $f->{bug_closed} = $l->{closed}; } - # New issue + # New bug } else { - $f->{issue_status} = $s->{default_status}; - $f->{issue_closed} = 0; - my $fa = $TUWF::OBJ->formValidate({ post => 'issue_type', enum => $s->{types} }); + $f->{bug_status} = $s->{default_status}; + $f->{bug_closed} = 0; + my $fa = $TUWF::OBJ->formValidate({ post => 'bug_type', enum => $s->{types} }); $f = { %$f, %$fa }; return($f, $l) if $f->{_err}; } # No errors? Save! - my $id = $s->dbSave(map $f->{"issue_$_"}, qw|id closed summary email type status message|); + my $id = $s->dbSave(map $f->{"bug_$_"}, qw|id closed summary email type status message|); # For replies, send out notification emails if($l) { my $mails = $s->dbEmails($id); my $u = $url->($id); - for(grep $_ ne $f->{issue_email}, @$mails) { + for(grep $_ ne $f->{bug_email}, @$mails) { $TUWF::OBJ->mail( "Hello!\n\n". - "A new reply has been posted to an issue you have previously shown\n". + "A new reply has been posted to an bug you have previously shown\n". "an interest in. You can view the reply at the following URL:\n". " $u\n\n". "If you do not wish to receive any more notifications for this (and\n". - "perhaps other) issues, please reply to this email stating your intent.", - Subject => "Reply to $f->{issue_summary}", + "perhaps other) bugs, please reply to this email stating your intent.", + Subject => "Reply to $f->{bug_summary}", To => "$_", ); } diff --git a/dat/dump b/dat/dump index d8f4dab..5b57b5a 100644 --- a/dat/dump +++ b/dat/dump @@ -59,5 +59,5 @@ it. L December 2011. Playing around with the Go programming language, I wrote another transfer log parser and statistics generator for ncdc. -L (L). +L<0.3|http://p.blicky.net/h25z8> +(L<0.2|http://p.blicky.net/6yx2d>, L<0.1|http://p.blicky.net/ab4lm>). diff --git a/dat/ncdc-faq b/dat/ncdc-faq index 0d91612..88cd026 100644 --- a/dat/ncdc-faq +++ b/dat/ncdc-faq @@ -157,5 +157,5 @@ myself, though. I just run ncdc directly on my router. :-) Nothing like that is included in the release yet, but there is a simple Perl script available: L, and a short -Go program: L. +Go program: L. diff --git a/index.cgi b/index.cgi index 229430f..7857b1d 100755 --- a/index.cgi +++ b/index.cgi @@ -12,8 +12,9 @@ BEGIN { ($ROOT = abs_path $0) =~ s{index\.cgi$}{}; } my @changes = ( - [ '2012-03-24', '/ncdu/issue', 'Moved issue tracker from sourceforge to this site' ], - [ '2012-03-17', '/ncdc/issue', 'Wrote a small issue tracker for ncdc' ], + [ '2012-03-30', '/dump', 'Updated ncdc-share-report for Go 1' ], + [ '2012-03-24', '/ncdu/bug', 'Moved ncdu bug tracker from sourceforge to this site' ], + [ '2012-03-17', '/ncdc/bug', 'Wrote a small bug tracker for ncdc' ], [ '2012-03-14', '/ncdc', 'ncdc 1.9 released.' ], [ '2012-02-15', '/doc/commvis', 'Added an article on my new communication system.' ], [ '2012-02-13', '/ncdc', 'ncdc 1.8 released.' ], @@ -76,16 +77,16 @@ TUWF::register( qr{dump/grenamr} => sub { podpage(shift, 'dump-grenamr', 'dump', 'grenamr', 'GTK+ Mass File Renamer') }, qr{dump/nccolour} => sub { podpage(shift, 'dump-nccolour', 'dump', 'nccolour', 'Colours in NCurses') }, qr{feed\.atom} => \&atom, - qr{(ncdc|ncdu)/issue} => \&issue_list, - qr{(ncdc|ncdu)/issue/post} => \&issue_post, - qr{(ncdc|ncdu)/issue/new} => \&issue_new, - qr{(ncdc|ncdu)/issue/([1-9][0-9]*)} => \&issue_item, + qr{(ncdc|ncdu)/bug} => \&bug_list, + qr{(ncdc|ncdu)/bug/post} => \&bug_post, + qr{(ncdc|ncdu)/bug/new} => \&bug_new, + qr{(ncdc|ncdu)/bug/([1-9][0-9]*)} => \&bug_item, ); TUWF::set( logfile => '/www/err.log', error_404_handler => \¬found, - mail_from => 'Yorhel\'s issue tracker ', + mail_from => 'Yorhel\'s Bug Tracker ', # this is a fairly static site, allow some aggressive caching pre_request_handler => sub { $_[0]->resHeader('Cache-Control', 's-max-age=86400, max-age=3600'); 1; }, ); @@ -189,6 +190,7 @@ sub notfound { [ 'dump/grenamr', '/dump/grenamr' ], ); return $s->resRedirect("/$u", 'perm') if $u =~ s/\/$//; + return $s->resRedirect("/$1/bug$2", 'perm') if $u =~ /^(ncd[uc])\/issue(.*)$/; $s->resStatus(404); $s->htmlHeader(title => '404', page => '404'); txt 'Sorry, there is no page at this URI. Try one of the links from the menu to find the page you are looking for.'; @@ -198,69 +200,69 @@ sub notfound { -# Issue handling +# Bug tracker -sub _issue_init { - require "$ROOT/Issue.pm"; +sub _bug_init { + require "$ROOT/Bug.pm"; my($s, $p) = @_; $s->resHeader('Cache-Control', 'no-cache'); $s->_load_module('TUWF::DB'); $s->{_TUWF}{db_login} = [ undef, undef, undef ]; $s->dbInit; - return TUWF::Issue->new(prefix => $p.'_', admins => [ $ENV{ISSUE_CODE} ]); + return TUWF::Bug->new(prefix => $p.'_', admins => [ $ENV{ISSUE_CODE} ]); } -sub issue_list { +sub bug_list { my($s, $p) = @_; - my $is = _issue_init(@_); - $s->htmlHeader(title => "\u$p Issue tracker", page => $p, sec => 'issue'); - br; a href => "/$p/issue/new", 'Report new issue'; br; br; - $is->htmlListing((scalar $is->dbListing()), sub { "/$p/issue/".shift }); - br; a href => "/$p/issue/new", 'Report new issue'; br; br; + my $is = _bug_init(@_); + $s->htmlHeader(title => "\u$p Bug tracker", page => $p, sec => 'bug'); + br; a href => "/$p/bug/new", 'Report new bug'; br; br; + $is->htmlListing((scalar $is->dbListing()), sub { "/$p/bug/".shift }); + br; a href => "/$p/bug/new", 'Report new bug'; br; br; $s->htmlFooter; } -sub issue_new { +sub bug_new { my($s, $p) = @_; - my $is = _issue_init(@_); - $s->htmlHeader(title => "\u$p: Report new issue", page => $p, sec => 'issue'); - br; a href => "/$p/issue", 'Back to the issue index'; br; br; - $is->htmlForm(undef, "/$p/issue/post"); + my $is = _bug_init(@_); + $s->htmlHeader(title => "\u$p: Report new bug", page => $p, sec => 'bug'); + br; a href => "/$p/bug", 'Back to the bug index'; br; br; + $is->htmlForm(undef, "/$p/bug/post"); $s->htmlFooter; } -sub issue_post { +sub bug_post { my($s, $p) = @_; return $s->resNotFound if $s->reqMethod() ne 'POST'; - my $is = _issue_init($s, $p); - my($f, $l) = $is->handleForm(sub { "http://dev.yorhel.nl/$p/issue/".shift }); + my $is = _bug_init($s, $p); + my($f, $l) = $is->handleForm(sub { "http://dev.yorhel.nl/$p/bug/".shift }); if($f->{_err}) { - $s->htmlHeader(title => 'Error creating message', page => $p, sec => 'issue'); + $s->htmlHeader(title => 'Error creating message', page => $p, sec => 'bug'); p 'There was an error in the form. Please use the \'back\' button of your browser to go back to the form (hopefully) without losing your message. - There was an error in the following fields: '.join(', ', map {(my$f=$_->[0])=~s/issue_// ;"\u$f"} @{$f->{_err}}).'.'; + There was an error in the following fields: '.join(', ', map {(my$f=$_->[0])=~s/bug_// ;"\u$f"} @{$f->{_err}}).'.'; return $s->htmlFooter; } - $s->resRedirect("/$p/issue/$l->{issue}", 'post'); + $s->resRedirect("/$p/bug/$l->{bug}", 'post'); } -sub issue_item { +sub bug_item { my($s, $p, $i) = @_; - my $is = _issue_init($s, $p); + my $is = _bug_init($s, $p); my $item = $is->dbItem($i); return $s->resNotFound if !@$item; my $last = $item->[$#$item]; - $s->htmlHeader(title => "\u$p: $last->{summary}", page => $p, sec => 'issue'); - br; a href => "/$p/issue", 'Back to the issue index'; br; br; + $s->htmlHeader(title => "\u$p: $last->{summary}", page => $p, sec => 'bug'); + br; a href => "/$p/bug", 'Back to the bug index'; br; br; $is->htmlItem($item); - $is->htmlForm($last, "/$p/issue/post") if !$last->{closed}; - br; a href => "/$p/issue", 'Back to the issue index'; br; br; + $is->htmlForm($last, "/$p/bug/post") if !$last->{closed}; + br; a href => "/$p/bug", 'Back to the bug index'; br; br; $s->htmlFooter; } @@ -404,7 +406,7 @@ sub htmlMenu { $m->('/ncdu/man', 'Manual', $o{sec} eq 'man'); $m->('/ncdu/changes', 'Changelog', $o{sec} eq 'changes'); $m->('/ncdu/scr', 'Screenshots', $o{sec} eq 'scr'); - $m->('/ncdu/issue', 'Issue tracker', $o{sec} eq 'issue'); + $m->('/ncdu/bug', 'Bug tracker', $o{sec} eq 'bug'); }); $m->('/ncdc', 'Ncdc', $o{page} eq 'ncdc', sub { $m->('/ncdc', 'Info', !$o{sec}); @@ -412,7 +414,7 @@ sub htmlMenu { $m->('/ncdc/man', 'Manual', $o{sec} eq 'man'); $m->('/ncdc/changes', 'Changelog', $o{sec} eq 'changes'); $m->('/ncdc/scr', 'Screenshots', $o{sec} eq 'scr'); - $m->('/ncdc/issue', 'Issue tracker', $o{sec} eq 'issue'); + $m->('/ncdc/bug', 'Bug tracker', $o{sec} eq 'bug'); }); $m->('/tuwf', 'Tuwf', $o{page} eq 'tuwf', sub { $m->('/tuwf', 'Info', !$o{sec}); diff --git a/style.css b/style.css index 0d34403..c0e8252 100644 --- a/style.css +++ b/style.css @@ -65,23 +65,23 @@ textarea:focus, input:focus { background: #fff } table { border-collapse: collapse } table td { padding: 0 2px } table thead td { font-weight: bold } -.issue_listing tbody tr:nth-child(odd) { background-color: #f4f4f4 } -.issue_listing { width: 95% } -.issue_col_id, .issue_col_type, .issue_col_status, .issue_col_date { white-space: nowrap } -.issue_closed td { text-decoration: line-through } -.issue_status { display: block; height: 20px } -.issue_status dt { float: left; font-weight: bold } -.issue_status dd { float: left; } -.issue_item h1 { margin-top: 30px } -.issue_item dt { clear: left; float: left; font-weight: bold; width: 60px } -.issue_item dd { float: left; padding-right: 20px } -.issue_item p { clear: left; padding-top: 5px } -.issue_frm fieldset { border: 0; margin-top: 40px } -.issue_frm legend { font-size: 19px; color: #000; } -.issue_frm li { list-style-type: none; margin-left: 10px; clear: left; padding-top: 5px } -.issue_frm label { display: block; width: 80px; float: left } -.issue_frm input, .issue_frm select { float: left } -.issue_frm textarea { width: 100%; height: 200px } -.issue_frm_submit input { float: right; width: 200px } +.bug_listing tbody tr:nth-child(odd) { background-color: #f4f4f4 } +.bug_listing { width: 95% } +.bug_col_id, .bug_col_type, .bug_col_status, .bug_col_date { white-space: nowrap } +.bug_closed td { text-decoration: line-through } +.bug_status { display: block; height: 20px } +.bug_status dt { float: left; font-weight: bold } +.bug_status dd { float: left; } +.bug_item h1 { margin-top: 30px } +.bug_item dt { clear: left; float: left; font-weight: bold; width: 60px } +.bug_item dd { float: left; padding-right: 20px } +.bug_item p { clear: left; padding-top: 5px } +.bug_frm fieldset { border: 0; margin-top: 40px } +.bug_frm legend { font-size: 19px; color: #000; } +.bug_frm li { list-style-type: none; margin-left: 10px; clear: left; padding-top: 5px } +.bug_frm label { display: block; width: 80px; float: left } +.bug_frm input, .bug_frm select { float: left } +.bug_frm textarea { width: 100%; height: 200px } +.bug_frm_submit input { float: right; width: 200px } -.issue_status dt::after, .issue_item dt::after, .issue_frm label::after { content: ":" } +.bug_status dt::after, .bug_item dt::after, .bug_frm label::after { content: ":" }