Editable item notes. Took more than you'd think.
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Thu, 11 Aug 2011 21:21:58 +0000 (17:21 -0400)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Fri, 12 Aug 2011 21:52:15 +0000 (17:52 -0400)
Had to fix open-ils.actor.container.item_note.cud, which can't possibly
have ever worked.

Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor/Container.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
Open-ILS/web/css/skin/default/opac/style.css
Open-ILS/web/templates/default/opac/myopac/lists.tt2

index ec381ab..537f35f 100644 (file)
@@ -131,29 +131,53 @@ __PACKAGE__->register_method(
 
 sub item_note_cud {
     my($self, $conn, $auth, $class, $note) = @_;
+
+    return new OpenILS::Event("BAD_PARAMS") unless
+        $note->class_name =~ /bucket_item_note$/;
+
     my $e = new_editor(authtoken => $auth, xact => 1);
     return $e->die_event unless $e->checkauth;
 
-    my $meth = 'retrieve_' . $ctypes{$class};
-    my $nclass = $note->class_name;
-    (my $iclass = $nclass) =~ s/n$//og;
+    my $meat = $ctypes{$class} . "_item_note";
+    my $meth = "retrieve_$meat";
 
-    my $db_note = $e->$meth($note->id, {
-        flesh => 2,
-        flesh_fields => {
-            $nclass => ['item'],
-            $iclass => ['bucket']
-        }
-    });
+    my $item_meat = $ctypes{$class} . "_item";
+    my $item_meth = "retrieve_$item_meat";
+
+    my $nhint = $Fieldmapper::fieldmap->{$note->class_name}->{hint};
+    (my $ihint = $nhint) =~ s/n$//og;
+
+    my ($db_note, $item);
+
+    if ($note->isnew) {
+        $db_note = $note;
+
+        $item = $e->$item_meth([
+            $note->item, {
+                flesh => 1, flesh_fields => {$ihint => ["bucket"]}
+            }
+        ]) or return $e->die_event;
+    } else {
+        $db_note = $e->$meth([
+            $note->id, {
+                flesh => 2,
+                flesh_fields => {
+                    $nhint => ['item'],
+                    $ihint => ['bucket']
+                }
+            }
+        ]) or return $e->die_event;
+
+        $item = $db_note->item;
+    }
 
-    if($db_note->item->bucket->owner ne $e->requestor->id) {
-        return $e->die_event unless 
-            $e->allowed('UPDATE_CONTAINER', $db_note->item->bucket);
+    if($item->bucket->owner ne $e->requestor->id) {
+        return $e->die_event unless $e->allowed("UPDATE_CONTAINER");
     }
 
-    $meth = 'create_' . $ctypes{$class} if $note->isnew;
-    $meth = 'update_' . $ctypes{$class} if $note->ischanged;
-    $meth = 'delete_' . $ctypes{$class} if $note->isdeleted;
+    $meth = 'create_' . $meat if $note->isnew;
+    $meth = 'update_' . $meat if $note->ischanged;
+    $meth = 'delete_' . $meat if $note->isdeleted;
     return $e->die_event unless $e->$meth($note);
     $e->commit;
 }
index 3cf6c41..8090d29 100644 (file)
@@ -1120,7 +1120,7 @@ sub load_myopac_bookbags {
     my $e = $self->editor;
     my $ctx = $self->ctx;
 
-    my $sorter = $self->cgi->param("sort");
+    my $sorter = $self->cgi->param("sort") || "";
     my $modifier = ($sorter =~ /\.(.+$)/) ? $1 : undef;
 
     $e->xact_begin; # replication...
@@ -1175,6 +1175,9 @@ sub load_myopac_bookbags {
             {
                 "target_biblio_record_entry" => $record_id_list,
                 "bucket" => $bookbag->id
+            }, {
+                flesh => 1,
+                flesh_fields => {"cbrebi" => ["notes"]}
             }
         ]) or do {
             $self->apache->log->warn(
@@ -1214,7 +1217,11 @@ sub load_myopac_bookbag_update {
     my $e = $self->editor;
     my $cgi = $self->cgi;
 
+    # save_notes is effectively another action, but is passed in a separate
+    # CGI parameter for what are really just layout reasons.
+    $action = 'save_notes' if $cgi->param('save_notes');
     $action ||= $cgi->param('action');
+
     $list_id ||= $cgi->param('list');
 
     my @add_rec = $cgi->param('add_rec') || $cgi->param('record');
@@ -1225,10 +1232,16 @@ sub load_myopac_bookbag_update {
     my $success = 0;
     my $list;
 
-    if($action eq 'create') {
+    # This url intentionally leaves off the edit_notes parameter, but
+    # may need to add some back in for paging.
+
+    my $url = "https://" . $self->apache->hostname .
+        $self->ctx->{opac_root} . "/myopac/lists";
+
+    if ($action eq 'create') {
         $list = Fieldmapper::container::biblio_record_entry_bucket->new;
         $list->name($name);
-        $list->name($description);
+        $list->description($description);
         $list->owner($e->requestor->id);
         $list->btype('bookbag');
         $list->pub($shared ? 't' : 'f');
@@ -1286,13 +1299,99 @@ sub load_myopac_bookbag_update {
             );
             last unless $success;
         }
+    } elsif ($action eq 'save_notes') {
+        $success = $self->update_bookbag_item_notes;
     }
 
-    return $self->generic_redirect if $success;
+    return $self->generic_redirect($url) if $success;
+
+    # XXX FIXME Bucket failure doesn't have a page to show the user anything
+    # right now. User just sees a 404 currently.
 
     $self->ctx->{bucket_action} = $action;
     $self->ctx->{bucket_action_failed} = 1;
     return Apache2::Const::OK;
 }
 
+sub update_bookbag_item_notes {
+    my ($self) = @_;
+    my $e = $self->editor;
+
+    my @note_keys = grep /^note-\d+/, keys(%{$self->cgi->Vars});
+    my @item_keys = grep /^item-\d+/, keys(%{$self->cgi->Vars});
+
+    # We're going to leverage an API call that's already been written to check
+    # permissions appropriately.
+
+    my $a = create OpenSRF::AppSession("open-ils.actor");
+    my $method = "open-ils.actor.container.item_note.cud";
+
+    for my $note_key (@note_keys) {
+        my $note;
+
+        my $id = ($note_key =~ /(\d+)/)[0];
+
+        if (!($note =
+            $e->retrieve_container_biblio_record_entry_bucket_item_note($id))) {
+            my $event = $e->die_event;
+            $self->apache->log->warn(
+                "error retrieving cbrebin id $id, got event " .
+                $event->{textcode}
+            );
+            $a->kill_me;
+            $self->ctx->{bucket_action_event} = $event;
+            return;
+        }
+
+        if (length($self->cgi->param($note_key))) {
+            $note->ischanged(1);
+            $note->note($self->cgi->param($note_key));
+        } else {
+            $note->isdeleted(1);
+        }
+
+        my $r = $a->request($method, $e->authtoken, "biblio", $note)->gather(1);
+
+        if (defined $U->event_code($r)) {
+            $self->apache->log->warn(
+                "attempt to modify cbrebin " . $note->id .
+                " returned event " .  $r->{textcode}
+            );
+            $e->rollback;
+            $a->kill_me;
+            $self->ctx->{bucket_action_event} = $r;
+            return;
+        }
+    }
+
+    for my $item_key (@item_keys) {
+        my $id = int(($item_key =~ /(\d+)/)[0]);
+        my $text = $self->cgi->param($item_key);
+
+        chomp $text;
+        next unless length $text;
+
+        my $note = new Fieldmapper::container::biblio_record_entry_bucket_item_note;
+        $note->isnew(1);
+        $note->item($id);
+        $note->note($text);
+
+        my $r = $a->request($method, $e->authtoken, "biblio", $note)->gather(1);
+
+        if (defined $U->event_code($r)) {
+            $self->apache->log->warn(
+                "attempt to create cbrebin for item " . $note->item .
+                " returned event " .  $r->{textcode}
+            );
+            $e->rollback;
+            $a->kill_me;
+            $self->ctx->{bucket_action_event} = $r;
+            return;
+        }
+    }
+
+    $a->kill_me;
+    return 1;   # success
+}
+
 1
index 7df710c..60647dd 100644 (file)
@@ -1021,3 +1021,4 @@ a.dash-link:hover { text-decoration: underline !important; }
     padding-bottom: 1ex;
 }
 .cn_browse_item { padding: 2ex; }
+.bookbag-item-row td { vertical-align: top; }
index c805334..6ba2ac8 100644 (file)
                     <big><strong>
                     [% IF bbag.pub == 't' %]
                         [% url = 'http://' _ ctx.hostname _ '/opac/extras/feed/bookbag/html-full/' _ bbag.id %]
-                        <a target='_blank' href='[% url %]'>[% bbag.name %]</a>
+                        <a target='_blank' href='[% url %]'>[% bbag.name | html %]</a>
                     [% ELSE %]
-                    [% bbag.name %]
+                    [% bbag.name | html %]
                     [% END %]
                     </strong></big>
+                    [% IF bbag.description %]<br /><em>[% bbag.description | html %]</em>[% END %]
                 </div>
                 <div class="bookbag-controls">
                     [% IF bbag.pub == 't'; %]
                                     inputs[i].checked = this.checked;}"/>
 
                         </td>
-                        <td width="49%" style="padding-left: 5px;">
+                        <td width="32%" style="padding-left: 5px;">
                             <a href="[% ctx.opac_root %]/myopac/lists?sort=titlesort">[% l('Title') %]</a>
                         </td>
-                        <td width="49%">
+                        <td width="33%">
                             <a href="[% ctx.opac_root %]/myopac/lists?sort=authorsort">[% l('Author(s)') %]</a>
                         </td>
+                        <td width="32%">
+                            [% l('Notes') %]
+                            [% IF CGI.param("edit_notes") != bbag.id %]
+                            | <a href="[% ctx.opac_root %]/myopac/lists?edit_notes=[% bbag.id %]">[% l('Edit') %]</a>
+                            [% END %]
+                        </td>
                         <td width="1%" class="nowrap">
                             <select class="opac-auto-179" name="action">
                                 <option>[% l('-- Actions for this list --') %]</option>
                         rec_id = item.target_biblio_record_entry;
                         attrs = {marc_xml => ctx.bookbags_marc_xml.$rec_id};
                         PROCESS get_marc_attrs args=attrs %]
-                    <tr>
+                    <tr class="bookbag-item-row">
                         <td class="opac-auto-097b" style="padding-left: 10px;"><input type="checkbox" name="del_item" value="[% item.id %]" bbag='[% bbag.id %]'/></td>
                         <td class="opac-auto-097b" style="padding-left: 5px;">[% attrs.title %]</td>
                         <td class="opac-auto-097b">[% attrs.author %]</td>
+                        [% IF CGI.param("edit_notes") == bbag.id %]
+                        <td class="opac-auto-097b">
+                            [% FOR note IN item.notes %]
+                            <input type="text" name="note-[% note.id %]" value="[% note.note | html %]" />
+                            [% END %]
+                            <input type="text" name="item-[% item.id %]" />
+                        </td>
+                        [% ELSE %]
+                        <td class="opac-auto-097b">
+                            [% FOR note IN item.notes %]
+                            <div>[% note.note | html %]</div>
+                            [% END %]
+                        </td>
+                        [% END %]
+                    </tr>
+                    [% END %]
+                    [% IF CGI.param("edit_notes") == bbag.id %]
+                    <tr>
+                        <td colspan="3"><!-- All space left of notes column --></td>
+                        <td>
+                            <input type="submit" name="save_notes" value="[% l('Save Notes') %]" />
+                        </td>
                     </tr>
                     [% END %]
                 </tbody>