AnnoCPAN

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

        - 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

MANIFEST  view on Meta::CPAN

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&lt;&gt; (link), B&lt;&gt; (bold), I&lt;&gt; (italic), C&lt;&gt; (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 %]



( run in 0.628 second using v1.01-cache-2.11-cpan-de7293f3b23 )