view release on metacpan or search on metacpan
- Bug fixes
* Fixed some bugs in L<>
* Fixed note propagation bug
* Found cause of database connection bug (version of DBD::mysql)
* Fixed =begin count persistence bug
- Site structure and navigation
* Redirect perldoc.cgi
* Redirect when a dist has only one distver
* Added a pager in the front page
* Use 302 redirects by default
* /note mode that shows and edits version bindings for a note
* Use Lingua::EN::Inflect to avoid saying '1 notes'
* Support POD formatting in notes
* Added help to edit form
- RSS
* RSS of new dists
* Refactored RSS code into AnnoCPAN::Feed
- Backend / database
* Added CPANRatings data
* Added maturity data to distver table
* Added "creation_time" to dist table
- Miscelaneous features
* Compression
* Added note_id to note elements in XML dump
t/note.xml
t/pod.t
t/PodParser.t
t/PodToHtml.t
t/XMLCGI.t
tables.tt.sql
tt/about.html
tt/choose.html
tt/choose_dist.html
tt/contact.html
tt/edit.html
tt/error.html
tt/faq.html
tt/footer.html
tt/form.html
tt/header.html
tt/join_pod.html
tt/login_form.html
tt/main.html
tt/message.html
tt/motd.html
html/about.pod view on Meta::CPAN
new version. The paragraph to which the note was originally attached can be
compared to the paragraphs in the new version and, if one is similar enough
(preferably identical), the note is transferred.
If the system can't figure out where to put the old note, the author or a
moderator can move it to a place in the new version if the note still applies.
Hopefully some of the good notes will become obsolete once the author of the
module decides to update the documentation to address the issues mentioned in
the note.
Users are able to edit, move, and delete their own notes. Moderators are be
able to move or delete any note.
=head1 CURRENT STATUS
This test version already has essentially all the documentation found on CPAN,
except for occasional difficulties with the non-trivial problem of unpacking and
identifying the relevant content in distributions which were packed in many
different ways.
The current features include:
html/about.pod view on Meta::CPAN
=item *
List the most recent notes on the front page.
=item *
Authentication
=item *
Delete, move or edit notes (only the note's author can do this)
=item *
Handle versions; automatic updates
=item *
Generate RSS feeds or emails
=back
html/show.js view on Meta::CPAN
var Req;
var Form;
var Please_Wait;
var Hidden_Note;
var Edit_Buttons;
var Note_Links = [];
var Move_Msg;
function init() {
Form = document.getElementById('noteform');
Edit_Buttons = document.getElementById('edit_buttons');
Form.save_button.onclick = save_note;
Form.del_button.onclick = delete_note;
Form.hide_button.onclick = hide_note;
Move_Msg = document.createElement('div');
Move_Msg.innerHTML = "Moving note... please select destination";
Please_Wait = document.getElementById('plswait');
init_buttons(document);
}
html/show.js view on Meta::CPAN
var mode = '';
var note = '';
var notepos = '';
var section = '';
if (link.className == "cb") { // create
mode = 'create';
note = link;
Note_Links.push(link);
section = link.href.match(/section=(\d+)/)[1];
} else if (link.className.match(/button/)
&& (link.href.match(/mode=edit/)))
{ // edit
mode = 'edit';
note = link.parentNode.parentNode.parentNode;
notepos = link.href.match(/notepos=(\d+)/)[1];
} else if (link.className.match(/button/)
&& (link.href.match(/mode=move/)))
{ // move
note = link.parentNode.parentNode.parentNode;
notepos = link.href.match(/notepos=(\d+)/)[1];
link.onclick = move_link_onclick('move', note, notepos);
}
if (mode) {
link.onclick = edit_link_onclick(mode, note, notepos, section);
}
}
var help_link = document.getElementById('note_help_link');
help_link.onclick = function () {
window.open('/note_help', 'ac_help', 'width=500,height=450,resizable=yes,scrollbars=yes').focus();
return false;
}
}
// Shows the form when user clicks on edit or create note button
function edit_link_onclick (mode, note, notepos, section) {
return function () {
// move form here and show it
if (Hidden_Note) {
Hidden_Note.style.display = mode == 'create' ? 'inline' : 'block';
}
// alert('note='+note); return false;
Hidden_Note = note;
note.parentNode.insertBefore(Form, note);
note.parentNode.insertBefore(Please_Wait, note);
Form.notepos.value = notepos;
Form.section.value = section;
if (mode == 'create') {
Hidden_Note.style.display = "none";
Form.style.display = "block";
Form.note_text.value = ''; // XXX - may cause lost text
Edit_Buttons.style.display = 'none';
Form.note_text.focus();
} else if (mode == 'edit') {
set_note_plaintext(notepos);
Edit_Buttons.style.display = 'inline';
} else {
alert('there is a mysterious bug');
}
return false;
}
}
function move_link_onclick(mode, note, notepos) {
lib/AnnoCPAN/Control.pm view on Meta::CPAN
$vars ||= {};
my $distver = $vars->{distver} || $self->param_obj('DistVer');
({
distver => $distver,
%$vars,
}, "show_dist");
}
=item $obj->Edit
The edit screen (like Show, but includes the edit form).
=cut
sub Edit {
my ($self, $vars) = @_;
$vars ||= {};
my $notepos = $self->param_obj('NotePos');
({
podver => $notepos->podver,
note => $notepos->note,
%$vars,
#message => "here ($section, $podver)" . $podver->pod->name,
}, "edit");
}
sub Raw_note {
my ($self, $vars) = @_;
my $notepos = $self->param_obj('NotePos');
my $text = $notepos->note->note;
({ note => $text }, 'note.txt', 'text/plain');
}
sub Create {
my ($self, $vars) = @_;
$vars ||= {};
# get user, see if can edit
my $user = $self->user
or return $self->error("Not logged in; can't create note");
my $section = $self->param_obj('Section');
my $podver = $section->podver;
({
podver => $podver,
section => $section,
%$vars,
#message => "here ($section, $podver)" . $podver->name,
}, "edit");
}
sub _search_podver {
my ($self, $vars) = @_;
$vars ||= {};
my $pod_name = $self->param('name');
return $self->Main unless $pod_name;
my @pods = AnnoCPAN::DBI::Pod->search(name => $pod_name);
return $self->error("not found") unless @pods;
return $self->choose_podver($vars, \@pods);
lib/AnnoCPAN/Control.pm view on Meta::CPAN
return $self->Main($vars) if $vars->{error};
$self->Show($vars);
}
sub _do_move {
my ($self) = @_;
my $notepos = $self->param_obj('NotePos');
my $section = $self->param_obj('Section');
# get user, see if can edit
my $user = $self->user
or return $self->_error("Not logged in; can't move");
$user->can_move($notepos->note)
or return $self->_error("Move not authorized");
$section->podver eq $notepos->section->podver
or return $self->_error("Move not within the same document");
my $podver = $section->podver;
lib/AnnoCPAN/Control.pm view on Meta::CPAN
sub _hide {
my ($self) = @_;
my $notepos_id = $self->param('notepos');
my $notepos = $self->param_obj('NotePos');
my $note = $notepos->note;
my $section = $notepos->section;
# get user, see if can edit
my $user = $self->user
or return $self->_error("not logged in; can't move");
$user->can_hide($note)
or return $self->_error("move not authorized");
my $podver = $section->podver;
$podver->flush_cache;
$notepos->status(AnnoCPAN::DBI::Note::HIDDEN);
$notepos->update;
lib/AnnoCPAN/Control.pm view on Meta::CPAN
sub Save {
my ($self) = @_;
return $self->_save if $self->param('fast');
my ($vars) = $self->_save;
return $self->Main($vars) if $vars->{error};
$self->Show($vars);
}
# to save new note, need section and note text
# to save edited note, need notepos and note text
sub _save {
my ($self) = @_;
my $note_text = $self->param('note_text');
my ($note, $podver);
# get user, see if can edit
my $user = $self->user
or return $self->_error("Not logged in; can't save note");
if ($self->param('notepos')) { # edit existing note
my $notepos = $self->param_obj('NotePos');
$podver = $notepos->podver;
$note = $notepos->note;
$user->can_edit($note)
or return $self->_error("Edit not authorized");
$note->note($note_text);
$note->ip($ENV{REMOTE_ADDR});
#$note->time(time);
$note->update;
$note->remove_from_object_index;
} else { # create new note
my $section = $self->param_obj('Section');
$podver = $section->podver;
lib/AnnoCPAN/Control.pm view on Meta::CPAN
my ($self) = @_;
$self->delete_cookie('key');
$self->user(undef);
$self->redirect($self->param('from'));
return;
#$self->Main({message => "You have logged out"});
}
sub Prefs {
my ($self) = @_;
return $self->error("Can't edit prefs without logging in first!")
unless $self->user;
({}, 'prefs');
}
sub Save_prefs {
my ($self) = @_;
# XXX untaint
my $user = $self->user;
return $self->error("Can't edit prefs without logging in first!")
unless $user;
AnnoCPAN::DBI::Prefs->search(user => $user)->delete_all;
for my $name (@{AnnoCPAN::Config->option('prefs')}) {
AnnoCPAN::DBI::Prefs->create({user => $user, name => $name,
value => $self->param($name) || '' });
}
({ message => 'Preferences saved'}, 'prefs');
}
lib/AnnoCPAN/DBI.pm view on Meta::CPAN
Return true if the user has the authority to delete $note (an
AnnoCPAN::DBI::Note object).
=cut
sub can_delete {
my ($user, $note) = @_;
($user->privs > 1 or $user == $note->user);
}
=item $user->can_edit($note)
Return true if the user has the authority to edit $note (an
AnnoCPAN::DBI::Note object).
=cut
sub can_edit { shift->can_delete(@_) }
=item $user->can_move($note)
Return true if the user has the authority to move $note (an
AnnoCPAN::DBI::Note object).
=back
=cut
tt/faq.html view on Meta::CPAN
<h2>Frequently Asked Questions</h2>
<ol>
<li><a href="#what">What is AnnoCPAN?</a></li>
<li><a href="#who">Who's behind it?</a></li>
<li><a href="#how">How does it work?</a></li>
<li><a href="#others">How does this site relate with CPAN::Forum, CPANRatings, search.cpan.org, PerlMonks...?</a></li>
<li><a href="#create">How do I add a note?</a></li>
<li><a href="#pod">How can I format my notes?</a></li>
<li><a href="#edit">Can I edit my notes?</a></li>
<li><a href="#editall">Can I edit other people's notes?</a></li>
<li><a href="#delete">What's the difference between "hiding" and "deleting" a note?</a></li>
<li><a href="#unhide">How do I unhide a note?</a></li>
<li><a href="#author_rss">How can I know when someone posts a note to one of my modules?</a></li>
<li><a href="#author_update">What happens if I upgrade my documentation, making a note obsolete?</a></li>
<li><a href="#conf">What's the %confidence?</a></li>
<li><a href="#absurd">A note is in an absurd place! Why's that?</a></li>
<li><a href="#browser">What are the browser requirements?</a></li>
<li><a href="#uses">What does AnnoCPAN run on?</a></li>
<li><a href="#contact">Who can I contact?</a></li>
<li><a href="#missing">Why is <i>X</i> distribution missing, or module <i>Y</i> in the wrong place?</a></li>
tt/faq.html view on Meta::CPAN
want to add the note</p>
<a name="pod"></a><h3>How can I format my notes?</h3>
<p>Currently a subset of POD is allowed. You can use formatting sequences such
as L<> (link), B<> (bold), I<> (italic), C<> (code),
etc, and verbatim paragraphs (lines that start with a space). What you can't
use are the pod commands, such as =item, =head1, etc. For more information
about the POD format, see [% link_perldoc_name('perlpod') %]. </p>
<a name="edit"></a><h3>Can I edit my notes?</h3>
<p>Yes, just click on the edit button. Make sure you are logged in first!</p>
<a name="editall"></a><h3>Can I edit other people's notes?</h3>
<p>No, unless you somehow get moderator privileges.</p>
<a name="delete"></a><h3>What's the difference between "hiding" and "deleting" a note?</h3>
<p>Deletion is irreversible and global, meaning that the note will disappear
from all versions of the POD; hiding is reversible and local, meaning that
the note is hidden only for a specific version of the POD.</p>
<a name="unhide"></a><h3>How do I unhide a note?</h3>
tt/note.html view on Meta::CPAN
[% UNLESS all_notepos; note_index = 0; all_notepos = []; END;
next_note_index = note_index + 1; prev_note_index = note_index - 1 %]
[% UNLESS notepos && ! notepos.is_visible %]
<div class="note [% notepos.score_class %]" id="note_[% note.id %]">
<div class="note_header">
<div class="note_data">
[% link_user(note.user) %]
([% YMD_HMS.format(note.time) %])
<a class="button u_[% note.user.id %]" href="[% root_uri_rel %]/e/?mode=edit;notepos=[% notepos.id %]#noteform">[edit]</a>
<a class="button u_[% note.user.id %]" href="[% root_uri_rel %]/e/?mode=move;notepos=[% notepos.id %]#[% notepos.section.pos %]">[move]</a>
</div>
<div class="note_nav">
[% IF note_index > 0 %]<a href="#note_[% all_notepos.$prev_note_index.note.id %]" title="Previous note">«</a>[% END %]
<a href="[% podver_uri(podver) %]#note_[% note.id %]" title="Bookmarkable link to this note">§</a>
[% IF note_index < all_notepos.size - 1 %]<a href="#note_[% all_notepos.$next_note_index.note.id %]" title="Next note">»</a>[% END %]
</div>
</div> <!-- note_header -->
<div class="note_body">
[% IF log.size > 0 %]
tt/note_form.html view on Meta::CPAN
<div class="note_header">Edit note
<a href="[% root_uri_rel %]/note_help" target="_blank" id="note_help_link">[help]</a>
</div>
<div id="note_text"><textarea name="note_text" rows="5" cols="20">[% notepos.note.note | html %]</textarea></div>
<div id="note_buttons">
<button name="mode" value="save" id="save_button" title="Save note. The same text will apply to all versions of this document">Save</button>
[% UNLESS mode == 'Create' %]
<span id="edit_buttons">
<button name="mode" value="delete" id="del_button" title="This will delete the note from all versions of this document">Delete</button>
<button name="mode" value="hide" id="hide_button" title="This will hide this note for this version of this document only">Hide</button>
</span>
[% END %]
</div>
</form>
tt/policy.html view on Meta::CPAN
<h3>License</h3>
<p>By posting a note in this site, you agree that it may be used, modified, and
redistributed under the same terms as Perl itself. This is to make sure that
other sites can use the notes and so that they may be included as part of the
documentation for a module if the maintainer of the module wishes.
<h3>Moderation</h3>
<p>Notes that are blatantly irrelevant or flaming may be edited or deleted.
Spam will be deleted and spammers will be banned. For cleanup purposes, notes
may also be hidden or moved for versions other than the version to which they
were originally posted, when they are no longer relevant or the automagic
algorithm assigned them to the wrong paragraph.
[% PROCESS footer.html %]