<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>
<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>
<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>
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
);
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
);
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
);
--- /dev/null
+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;
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?
false
);
+ obj.set_alert_notes_button();
+
JSAN.use('util.controller'); obj.controller = new util.controller();
obj.controller.init(
{
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() {
],
'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(); } ]
}
}
);
);
},
- '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
obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');*/
obj.retrieve_ids = list;
+ obj.set_alert_notes_button();
},
'process_unit_selection' : function(menuitem) {
}
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) {
<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;"/>
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>
--- /dev/null
+bell.png and bell_bw.png derived from:
+http://www.iconfinder.com/icondetails/1227/128/alarm_bell_icon
+GLPL