Serials: alert notes when receiving
authorDan Wells <dbw2@calvin.edu>
Tue, 10 Sep 2013 22:33:23 +0000 (18:33 -0400)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Tue, 17 Sep 2013 18:55:12 +0000 (14:55 -0400)
This commit adds the ability to flag serial notes as receive-time
alerts, and also adds the interface widgets necessary to check for
and see these alerts in the serial control receiving interface.

notes.xul was modified extensively to allow for an arbitrary pile of
notes to be displayed, rather than just displaying the notes for a
single object (which it still can do).

As it stands, the notes are compiled locally from already retrieved
objects, but it would also be reasonable to add a middle-layer
function to do roughly the same thing.  Depending on how this is done
it could require a fair amount of logic duplication, so it might be
better done as part of a larger interface/back-end combined
refactoring.

This commit also tidies up a few other minor things in
manage_items.js, including adding automatic refresh when notes are
added/edited/deleted, and also removing a duplicate function.

Alerting the notes in the batch-receive interface is still TODO, but
should be fairly simple to add once this commit is in place.

Signed-off-by: Dan Wells <dbw2@calvin.edu>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/sql/Pg/210.schema.serials.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.serial_note_alerts.sql [new file with mode: 0644]
Open-ILS/xul/staff_client/server/locale/en-US/serial.properties
Open-ILS/xul/staff_client/server/serial/manage_items.js
Open-ILS/xul/staff_client/server/serial/manage_items.xul
Open-ILS/xul/staff_client/server/serial/notes.xul
Open-ILS/xul/staff_client/server/skin/media/images/bell.png [new file with mode: 0644]
Open-ILS/xul/staff_client/server/skin/media/images/bell_disabled.png [new file with mode: 0644]
Open-ILS/xul/staff_client/server/skin/media/images/licenses.txt [new file with mode: 0644]

index f639fc0..1a63a12 100644 (file)
@@ -4444,6 +4444,7 @@ SELECT  usr,
                        <field reporter:label="Creator" name="creator" reporter:datatype="link"/>
                        <field reporter:label="Create Date" name="create_date" reporter:datatype="timestamp"/>
                        <field reporter:label="Public?" name="pub" reporter:datatype="bool"/>
+                       <field reporter:label="Alert?" name="alert" reporter:datatype="bool"/>
                        <field reporter:label="Title" name="title" reporter:datatype="text"/>
                        <field reporter:label="Value" name="value" reporter:datatype="text"/>
                </fields>
@@ -4505,6 +4506,7 @@ SELECT  usr,
                        <field reporter:label="Creator" name="creator" reporter:datatype="link"/>
                        <field reporter:label="Create Date" name="create_date" reporter:datatype="timestamp"/>
                        <field reporter:label="Public?" name="pub" reporter:datatype="bool"/>
+                       <field reporter:label="Alert?" name="alert" reporter:datatype="bool"/>
                        <field reporter:label="Title" name="title" reporter:datatype="text"/>
                        <field reporter:label="Value" name="value" reporter:datatype="text"/>
                </fields>
@@ -4751,6 +4753,7 @@ SELECT  usr,
                        <field reporter:label="Creator" name="creator" reporter:datatype="link"/>
                        <field reporter:label="Create Date" name="create_date" reporter:datatype="timestamp"/>
                        <field reporter:label="Public?" name="pub" reporter:datatype="bool"/>
+                       <field reporter:label="Alert?" name="alert" reporter:datatype="bool"/>
                        <field reporter:label="Title" name="title" reporter:datatype="text"/>
                        <field reporter:label="Value" name="value" reporter:datatype="text"/>
                </fields>
index d025d5e..620d57e 100644 (file)
@@ -53,6 +53,7 @@ CREATE TABLE serial.subscription_note (
                            DEFERRABLE INITIALLY DEFERRED,
        create_date  TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
        pub          BOOL   NOT NULL DEFAULT FALSE,
+       alert        BOOL   NOT NULL DEFAULT FALSE,
        title        TEXT   NOT NULL,
        value        TEXT   NOT NULL
 );
@@ -133,6 +134,7 @@ CREATE TABLE serial.distribution_note (
                            DEFERRABLE INITIALLY DEFERRED,
        create_date  TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
        pub          BOOL   NOT NULL DEFAULT FALSE,
+       alert        BOOL   NOT NULL DEFAULT FALSE,
        title        TEXT   NOT NULL,
        value        TEXT   NOT NULL
 );
@@ -290,6 +292,7 @@ CREATE TABLE serial.item_note (
                            DEFERRABLE INITIALLY DEFERRED,
        create_date TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
        pub         BOOL    NOT NULL    DEFAULT FALSE,
+       alert       BOOL    NOT NULL    DEFAULT FALSE,
        title       TEXT    NOT NULL,
        value       TEXT    NOT NULL
 );
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.serial_note_alerts.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.serial_note_alerts.sql
new file mode 100644 (file)
index 0000000..003a2da
--- /dev/null
@@ -0,0 +1,14 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+ALTER TABLE serial.subscription_note
+       ADD COLUMN alert BOOL NOT NULL DEFAULT FALSE;
+
+ALTER TABLE serial.distribution_note
+       ADD COLUMN alert BOOL NOT NULL DEFAULT FALSE;
+
+ALTER TABLE serial.item_note
+       ADD COLUMN alert BOOL NOT NULL DEFAULT FALSE;
+
+COMMIT;
index d41adb7..bf4e631 100644 (file)
@@ -70,6 +70,8 @@ staff.serial.manage_items.notes_column.label=Notes (Item/Dist/Sub)
 staff.serial.manage_items.set_claimed_success=Successfully claimed %1$s item(s)
 staff.serial.manage_items.set_not_held_success=Successfully set %1$s item(s) to 'Not Held'
 staff.serial.manage_items.set_not_published_success=Successfully set %1$s item(s) to 'Not Published'
+staff.serial.manage_items.alert_button.label=1 Alert
+staff.serial.manage_items.alert_button.plural.label=%1s Alerts
 staff.serial.manage_subs.add.error=error adding object in manage_subs.js:
 staff.serial.manage_subs.delete.error=error deleting object in manage_subs.js:
 staff.serial.manage_subs.delete_scap.confirm=Are you sure you would like to delete this caption and pattern?
index 08a7135..696d819 100644 (file)
@@ -201,6 +201,8 @@ serial.manage_items.prototype = {
             false
         );
 
+        obj.set_alert_notes_button();
+
                JSAN.use('util.controller'); obj.controller = new util.controller();
                obj.controller.init(
                        {
@@ -376,6 +378,16 @@ serial.manage_items.prototype = {
                             alert('Subscription selection needed here'); //FIXME: make this prompt, or discard this feature
                         }
                     ],
+                    'cmd_read_alerts' : [
+                        ['command'],
+                        function() {
+                            try {
+                                obj.view_alert_notes();
+                            } catch(E) {
+                                obj.error.standard_unexpected_error_alert('cmd_read_alerts failed!',E);
+                            }
+                        }
+                    ],
                     'cmd_receive_items' : [
                         ['command'],
                         function() {
@@ -571,7 +583,7 @@ serial.manage_items.prototype = {
                     ],
                     'cmd_items_print' : [ ['command'], function() { obj.items_print(obj.selected_list); } ],
                                        'cmd_items_export' : [ ['command'], function() { obj.items_export(obj.selected_list); } ],
-                                       'cmd_refresh_list' : [ ['command'], function() { obj.retrieve_ssubs_and_sdists(); obj.refresh_list('main'); obj.refresh_list('workarea'); } ]
+                                       'cmd_refresh_list' : [ ['command'], function() { obj.refresh_all(); } ]
                                }
                        }
                );
@@ -890,33 +902,19 @@ serial.manage_items.prototype = {
                );
     },
 
-       'refresh_list' : function(list_name) {
+       'refresh_all' : function() {
         var obj = this;
 
-        //TODO Optimize this?
-        obj.retrieve(list_name);
+        obj.retrieve_ssubs_and_sdists();
+        obj.refresh_list('main');
+        obj.refresh_list('workarea');
     },
 
-    // accepts a list of ids or a list of objects
-    'refresh_rows' : function(list) {
+    'refresh_list' : function(list_name) {
         var obj = this;
 
-        var id_list;
-
-        if (typeof list[0] == 'object') {
-            id_list = util.functional.map_list(
-                list,
-                function(o) {
-                    return o.id()
-                }
-            );
-        } else {
-            id_list = list;
-        }
-
-        for (var i = 0; i < id_list.length; i++) {
-            obj.lists[obj.selected_list].refresh_row(obj.row_map[id_list[i]]);
-        }
+        //TODO Optimize this?
+        obj.retrieve(list_name);
     },
 
     // accepts a list of ids or a list of objects
@@ -1003,6 +1001,7 @@ serial.manage_items.prototype = {
                obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');*/
 
                obj.retrieve_ids = list;
+               obj.set_alert_notes_button();
        },
 
     'process_unit_selection' : function(menuitem) {
@@ -1066,18 +1065,170 @@ serial.manage_items.prototype = {
         }
 
         var seen_ids = {};
+        var notes_window;
+        var sitem_ids = [];
         for (var i = 0; i < obj.retrieve_ids.length; i++) {
-            var item = obj.list_sitem_map[obj.retrieve_ids[i].sitem_id];
-            var obj_id = object_id_fn(item);
+            var sitem_id = obj.retrieve_ids[i].sitem_id;
+            var sitem = obj.list_sitem_map[sitem_id];
+            sitem_ids.push(sitem_id);
+            var obj_id = object_id_fn(sitem);
             if (seen_ids[obj_id]) continue;
             JSAN.use('util.window'); var win = new util.window();
-            win.open(
+            notes_window = win.open(
                 urls.XUL_SERIAL_NOTES,
                 '','chrome,resizable,modal',
-                { 'object_id' : obj_id, 'function_type' : function_type, 'object_type' : object_type, 'constructor' : constructor, 'title' : $('serialStrings').getString('staff.serial.'+type+'_editor.notes') + ' -- ' + title_fn(item) }
+                { 'object_id' : obj_id, 'function_type' : function_type, 'object_type' : object_type, 'constructor' : constructor, 'title' : $('serialStrings').getString('staff.serial.'+type+'_editor.notes') + ' -- ' + title_fn(sitem) }
             );
             seen_ids[obj_id] = 1;
         }
+        if (notes_window.notes_updated) { // we changed some notes
+            if (notes_window.notes_updated.sdistn || notes_window.notes_updated.ssubn) {
+                obj.refresh_all();
+            } else {
+                obj.refresh_rows(sitem_ids);
+            }
+        }
+    },
+
+    '_fetch_alert_notes' : function() {
+        var obj = this;
+
+        JSAN.use('util.functional');
+        var notes = [];
+
+        var alert_ids = {
+            "ssub" : [],
+            "sdist" : [],
+            "sitem" : []
+        };
+
+        //gather selected item alerts
+        if (obj.retrieve_ids) {
+            var related_obj_ids = {'ssub' : {}, 'sdist' : {}};
+            for (var i = 0; i < obj.retrieve_ids.length; i++) {
+                var item = obj.list_sitem_map[obj.retrieve_ids[i].sitem_id];
+                var my_notes = util.functional.filter_list(
+                    item.notes(),
+                    function (o) {
+                        return get_bool(o.alert());
+                    }
+                );
+
+                related_obj_ids.ssub[item.issuance().subscription().id()] = 1;
+                related_obj_ids.sdist[item.stream().distribution()] = 1;
+
+                if (my_notes.length) {
+                    alert_ids['sitem'].push(item.id());
+                    notes = notes.concat(my_notes);
+                }
+            }
+
+            // gather related object (sub/dist) alerts
+            ['sdist', 'ssub'].forEach(function(type) {
+                var obj_ids = related_obj_ids[type];
+                var type_map = obj[type + '_map'];
+                for (my_id in obj_ids) {
+                    var my_notes = util.functional.filter_list(
+                        type_map[my_id].notes(),
+                        function (o) {
+                            return get_bool(o.alert());
+                        }
+                    );
+
+                    if (my_notes.length) {
+                        alert_ids[type].push(my_id);
+                        notes = notes.concat(my_notes);
+                    }
+                }
+            });
+        }
+
+        return {
+            "notes" : notes,
+            "alert_ids" : alert_ids
+        };
+    },
+
+    'set_alert_notes_button' : function() {
+        var obj = this;
+        var alert_data = obj._fetch_alert_notes();
+
+        var num_alerts = alert_data.notes.length;
+        if (num_alerts > 0) {
+            $('serial_alert_button').setAttribute('disabled','false');
+            $('serial_alert_button_image').src = '/xul/server/skin/media/images/bell.png';
+            if (num_alerts == 1) {
+                $('serial_alert_button_label').value = $('serialStrings').getString('staff.serial.manage_items.alert_button.label');
+            } else {
+                $('serial_alert_button_label').value = $('serialStrings').getFormattedString('staff.serial.manage_items.alert_button.plural.label', num_alerts);
+            }
+        } else {
+            $('serial_alert_button').setAttribute('disabled','true');
+            $('serial_alert_button_image').src = '/xul/server/skin/media/images/bell_disabled.png';
+            $('serial_alert_button_label').value = $('serialStrings').getFormattedString('staff.serial.manage_items.alert_button.plural.label', 0);
+        }
+    },
+
+    'view_alert_notes' : function() {
+        var obj = this;
+
+        JSAN.use('util.functional');
+        var alert_data = obj._fetch_alert_notes();
+        var notes = alert_data.notes;
+        var alert_ids = alert_data.alert_ids;
+
+        if (notes.length <= 0) return;
+
+        // create titles for each alerted objects notes
+        var section_titles = {
+            "ssubn" : [],
+            "sdistn" : [],
+            "sin" : []
+        }
+        for (type in alert_ids) {
+            var typed_ids = alert_ids[type];
+            for (var i = 0; i < typed_ids.length; i++) {
+                var my_id = typed_ids[i];
+                var title_chunk = '';
+                var fm_class = '';
+                switch(type) {
+                    case 'sitem':
+                        fm_class = 'sin';
+                        break;
+                    case 'ssub':
+                        title_chunk = obj.ssub_map[my_id].owning_lib().shortname();
+                        fm_class = 'ssubn';
+                        break;
+                    case 'sdist':
+                        title_chunk = obj.sdist_map[my_id].label()
+                            + ' -- '
+                            + obj.sdist_map[my_id].holding_lib().shortname();
+                        fm_class = 'sdistn';
+                        break;
+                }
+                section_titles[fm_class].push(
+                    $('serialStrings').getString('staff.serial.'+ type +'_editor.notes')
+                    + ' -- ' + title_chunk + ' ('
+                    + fieldmapper.IDL.fmclasses[type].field_map.id.label
+                    + ' ' + my_id + ')'
+                );
+            }
+        }
+
+        JSAN.use('util.window'); var win = new util.window();
+        var notes_window = win.open(
+            urls.XUL_SERIAL_NOTES,
+            '','chrome,resizable,modal',
+            { 'notes' : notes, 'section_titles' : section_titles, 'title' : "Serial Alerts", 'disable_create' : true, 'section_id_names' : { 'ssubn' : 'subscription', 'sdistn' : 'distribution', 'sin' : 'item'} }
+        );
+        if (notes_window.notes_updated) { // we changed some notes
+            if (notes_window.notes_updated.sdistn || notes_window.notes_updated.ssubn) {
+                obj.refresh_all();
+            } else {
+                obj.refresh_rows(alert_ids["sitem"]);
+            }
+        }
+        return;
     },
 
     'set_items_special_status' : function(new_status, message) {
index 6a838c0..3217ef0 100644 (file)
@@ -102,7 +102,10 @@ vim:noet:sw=4:ts=4:
             <label style="font-weight: bold" value="&staff.serial.manage_items.workarea_showing;"/>
             <label id="serial_workarea_mode_label" value="&staff.serial.manage_items.workarea_recently_received;"/>
             <spacer flex="1"/>
-            <button label="&staff.serial.manage_items.receive_move.label;" command="cmd_receive_items"/>
+            <hbox>
+                <button id="serial_alert_button" command="cmd_read_alerts"><image id="serial_alert_button_image" src="/xul/server/skin/media/images/bell_disabled.png"/><label id="serial_alert_button_label" value="" /></button>
+                <button label="&staff.serial.manage_items.receive_move.label;" command="cmd_receive_items"/>
+            </hbox>
         </hbox>
         <hbox align="center">
             <label style="font-weight: bold" value="&staff.serial.manage_items.workarea_current_unit;"/>
index 4e2d960..d6ec108 100644 (file)
 
                                g.error.sdump('D_TRACE','my_init() for notes.xul');
 
-                               g.object_type = xul_param('object_type');
-                               g.object_id = xul_param('object_id');
-                               g.function_type = xul_param('function_type');
-                               g.constructor = xul_param('constructor');
+                               g.notes = xul_param('notes');
+                               g.disable_create = xul_param('disable_create');
+                               // in the code below, by default, function_type and
+                               // fm_type (aka classname) are assumed the same other
+                               // than case
+                               if (g.notes) { // we have the notes passed in
+                                       g.function_type_map = xul_param('function_type_map');
+                                       if (!g.function_type_map) { // didn't get one, build one
+                                               g.function_type_map = {};
+                                               for (i = 0; i < g.notes.length; i++) {
+                                                       g.function_type_map[g.notes[i].classname] = g.notes[i].classname.toUpperCase();
+                                               }
+                                       }
+                                       g.section_titles = xul_param('section_titles');
+                                       g.section_id_names = xul_param('section_id_names');
+                               } else { // we need to retreieve the notes
+                                       g.object_type = xul_param('object_type');
+                                       g.object_id = xul_param('object_id');
+                                       function_type = xul_param('function_type');
+                                       g.fm_type = xul_param('fm_type');
+                                       if (!g.fm_type) {
+                                               g.fm_type = function_type.toLowerCase();
+                                       }
+                                       g.function_type = function_type;
+                                       g.function_type_map = {};
+                                       g.function_type_map[g.fm_type] = function_type;
+                                       g.constructor = xul_param('constructor');
+                               }
 
                                var window_title = xul_param('title',{'modal_xulG':true});
                                if (window_title) {
                }
 
                function retrieve_notes() {
+                       if (g.notes) return;
                        g.notes = g.network.simple_request(
-                               'FM_' + g.function_type + '_RETRIEVE_ALL', [
+                               'FM_' + g.function_type_map[g.fm_type] + '_RETRIEVE_ALL', [
                                        { 'authtoken' : ses(), 'object_id' : g.object_id }
                                ]
                        );
                                function(n) {
                                        switch(n.nodeName) {
                                                case 'description' : n.appendChild( document.createTextNode( value ) ); break;
-                                               case 'label' : n.value = value; break;
+                                               case 'image' : n.src = value; break;
                                                default : n.value = value; break;
                                        }
                                }
                function render_notes() {
                        JSAN.use('util.widgets'); util.widgets.remove_children('notes_panel');
                        var np = $('notes_panel');
+                       if (!g.disable_create) {
                                var hbox = document.createElement('hbox'); np.appendChild(hbox);
                                        var btn = document.createElement('button'); hbox.appendChild(btn);
                                                btn.setAttribute('label', $('catStrings').getString('staff.cat.copy_notes.render_notes.label'));
                                                btn.setAttribute('accesskey', $('catStrings').getString('staff.cat.copy_notes.render_notes.accesskey'));
                                                btn.setAttribute('oncommand','new_note()');
+                       }
 
                        var hb; // keep button bar reference for adding close button
+                       var section_type;
+                       var section_id;
+                       var section_indices = {};
                        for (var i = 0; i < g.notes.length; i++) {
+                               var note = g.notes[i];
+
+                               if (g.section_titles) {
+                                       if (note.classname != section_type || note[g.section_id_names[note.classname]]() != section_id) {
+                                               section_type = note.classname;
+                                               if (!(section_type in section_indices)) {
+                                                       section_indices[section_type] = 0;
+                                               } else {
+                                                       section_indices[section_type]++;
+                                               }
+                                               var section_title = g.section_titles[section_type][section_indices[section_type]];
+                                               section_id = note[g.section_id_names[section_type]]();
+
+                                               // add the title to the window
+                                               var hbox = document.createElement('hbox');
+                                               np.appendChild(hbox);
+                                               var desc = document.createElement('description');
+                                               desc.appendChild(document.createTextNode(section_title));
+                                               hbox.appendChild(desc);
+                                       }
+                               }
 
                                /* template */
                                var node = $('note_template').cloneNode(true); np.appendChild(node); node.hidden = false;
-                               apply(node,'create_date',g.notes[i].create_date().toString().substr(0,10));
+                               apply(node,'create_date',note.create_date().toString().substr(0,10));
                                util.widgets.apply(node,'name','create_date',
                                        function(n) {
                                                n.setAttribute(
                                                        "tooltiptext",
                                                        $('catStrings').getString('staff.cat.copy_notes.widgets_apply.note_id') + " "
-                                                       + g.notes[i].id() + " " 
+                                                       + note.id() + " "
                                                        + $('catStrings').getString('staff.cat.copy_notes.widgets_apply.creator_id') + " "
-                                                       + g.notes[i].creator()
+                                                       + note.creator()
                                                );
                                        }
                                );
-                               apply(node,'title',g.notes[i].title());
+                               apply(node,'title',note.title());
                                apply(node,'pub',get_bool( g.notes[i].pub() ) ? $('catStrings').getString('staff.cat.copy_notes.widgets.public') : $('catStrings').getString('staff.cat.copy_notes.widgets.private'));
+                               apply(node,'alert',get_bool( g.notes[i].alert() ) ? '/xul/server/skin/media/images/bell.png' : '');
                                apply(node,'value',g.notes[i].value());
                                apply(node,'id',g.notes[i].id());
                                apply(node,'creator',g.notes[i].creator());
                                                                        $('commonStrings').getString('common.confirm')
                                                                ); 
                                                                if (r == 0) {
-                                                                       g.network.simple_request('FM_'+g.function_type+'_DELETE',[ses(),g.notes[index].id()]);
+                                                                       g.network.simple_request('FM_'+g.function_type_map[g.notes[index].classname]+'_DELETE',[ses(),g.notes[index].id()]);
+                                                                       g.notes.splice(index, 1);
                                                                        setTimeout(function() { 
                                                                                alert($('catStrings').getString('staff.cat.copy_notes.delete_note.success'));
                                                                                refresh(); },0
                                                                        );
+                                                                       if(!xulG.notes_updated) xulG.notes_updated = {};
+                                                                       xulG.notes_updated[g.notes[index].classname] = 1;
                                                                }
                                                        } }(i),
                                                        false
 
                function new_note(index) {
                        var public = false;
+                       var alert = false;
                        var title = '';
                        var value = '';
                        var edit_mode; // for clarity
                        if (typeof index != 'undefined') {
                                edit_mode = true;
                                public = get_bool(g.notes[index].pub());
+                               alert = get_bool(g.notes[index].alert());
                                title = xml_encode(g.notes[index].title());
                                value = xml_encode(g.notes[index].value());
                                label_text = $('serialStrings').getString('staff.serial.notes.edit_note.label');
                                        <grid flex="1"><columns><column/><column flex="1"/></columns> \
                                                <rows> \
                                                        <row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.public') + '"/><checkbox id="pub" name="fancy_data" checked="' + public + '"/></row> \
+                                                       <row><label value="' + fieldmapper.IDL.fmclasses[g.notes[index].classname].field_map.alert.label + '"/><checkbox id="alert" name="fancy_data" checked="' + alert + '"/></row> \
                                                        <row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.title') + '"/><textbox id="title" name="fancy_data" context="clipboard" value="' + title + '"/></row> \
                                                        <row><label value="' + $('catStrings').getString('staff.cat.copy_notes.new_note.note') + '"/><textbox multiline="true" id="note" name="fancy_data" context="clipboard" value="' + value + '"/></row> \
                                                        <row><spacer/><hbox> \
                                                                <button label="' + $('catStrings').getString('staff.cat.copy_notes.new_note.cancel.label') + '" name="fancy_cancel" accesskey="' + $('catStrings').getString('staff.cat.copy_notes.new_note.cancel.accesskey') + '"/> \
                                                                <button label="' + label_text + '" accesskey="' + button_accesskey + '" name="fancy_submit"/></hbox></row> \
                                                </rows></grid></groupbox>';
-                               //g.data.init({'via':'stash'});
-                               //g.data.temp_note_xml = xml; g.data.stash('temp_note_xml');
                                JSAN.use('util.window'); var win = new util.window();
                                var fancy_prompt_data = win.open(
                                        urls.XUL_FANCY_PROMPT,
-                                       //+ '?xml_in_stash=temp_note_xml'
-                                       //+ '&focus=' + window.escape('title')
-                                       //+ '&title=' + window.escape('Add Note'),
                                        'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
                                        { 'xml' : xml, 'focus' : 'title', 'title' : label_text }
                                );
-                               //g.data.init({'via':'stash'});
                                if (fancy_prompt_data.fancy_status == 'complete') {
-                                       //alert(js2JSON(g.data.fancy_prompt_data));
                                        var note;
                                        if (edit_mode) {
                                                note = g.notes[index];
                                        } else {
                                                note = new g.constructor();
                                                note.isnew(1);
+                                               note[g.object_type]( g.object_id );
                                        }
                                        note.title( fancy_prompt_data.title );
                                        note.value( fancy_prompt_data.note );
                                        note.pub( get_bool( fancy_prompt_data.pub ) ? get_db_true() : get_db_false() );
-                                       note[g.object_type]( g.object_id );
-                                       var r = g.network.simple_request('FM_'+g.function_type+'_UPDATE',[ ses(), note ]);
+                                       note.alert( get_bool( fancy_prompt_data.alert ) ? get_db_true() : get_db_false() );
+                                       var r = g.network.simple_request('FM_'+g.function_type_map[note.classname]+'_UPDATE',[ ses(), note ]);
                                        if (typeof r.ilsevent != 'undefined') throw(r);
+                                       // not every note type support pcrud, so we can't do this
+                                       // for now, if they pass in a pile of notes (g.notes mode),
+                                       // they simply won't be able to add notes
+                                       // One alternative would be to teach the UPDATE functions
+                                       // to send back the updated note objects
+                                       /*
+                                       if (!edit_mode) { // fetch new note and add to pile
+                                               note = g.network.request(
+                                                       'open-ils.pcrud',
+                                                       'open-ils.pcrud.retrieve.' + note.classname,
+                                                       [ ses(), r ]
+                                               );
+                                               g.notes.push(note);
+                                       }
+                                       */
+                                       if (!edit_mode) { // force re-fetch of notes
+                                               g.notes = undefined;
+                                       }
+                                       if(!xulG.notes_updated) xulG.notes_updated = {};
+                                       xulG.notes_updated[note.classname] = 1;
                                        setTimeout(function() {
                                                refresh();},0
                                        );
        <stack hidden="true" id="note_template" flex="1">
                <vbox flex="1" style="background-color: black; margin:3px"/>
                <vbox flex="1" style="background-color: #FFDE00; -moz-border-radius-topright: 35px; border: 2px groove ThreeDFace; margin:3px;" >
-                       <hbox>
+                       <hbox align="start">
                                <description name="title" style="font-weight: bold"/>
                                <spacer flex="1"/>
                                <description name="create_date" style="font-weight: bold"/>
                                <description name="pub" style="font-weight: bold"/>
+                               <image name="alert" src=""/>
                        </hbox>
                        <description style="white-space: pre-wrap;" name="value"/>
                </vbox>
diff --git a/Open-ILS/xul/staff_client/server/skin/media/images/bell.png b/Open-ILS/xul/staff_client/server/skin/media/images/bell.png
new file mode 100644 (file)
index 0000000..6a10c01
Binary files /dev/null and b/Open-ILS/xul/staff_client/server/skin/media/images/bell.png differ
diff --git a/Open-ILS/xul/staff_client/server/skin/media/images/bell_disabled.png b/Open-ILS/xul/staff_client/server/skin/media/images/bell_disabled.png
new file mode 100644 (file)
index 0000000..ff2a163
Binary files /dev/null and b/Open-ILS/xul/staff_client/server/skin/media/images/bell_disabled.png differ
diff --git a/Open-ILS/xul/staff_client/server/skin/media/images/licenses.txt b/Open-ILS/xul/staff_client/server/skin/media/images/licenses.txt
new file mode 100644 (file)
index 0000000..df3dbc5
--- /dev/null
@@ -0,0 +1,3 @@
+bell.png and bell_bw.png derived from:
+http://www.iconfinder.com/icondetails/1227/128/alarm_bell_icon
+GLPL