[open-ils-commits] r17040 - in branches/seials-integration/Open-ILS: src/perlmods/OpenILS/Application src/sql/Pg xul/staff_client/chrome/content/main xul/staff_client/server/serial (dbwells)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Jul 27 15:58:59 EDT 2010


Author: dbwells
Date: 2010-07-27 15:58:53 -0400 (Tue, 27 Jul 2010)
New Revision: 17040

Added:
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_unit.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.xul
Modified:
   branches/seials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm
   branches/seials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql
   branches/seials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.js
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.xul
   branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js
Log:
- 'NOT NULL' constraint for 'shadowed' column in serial.item
- Unit support menus, selection popup, and other interface elements
- Basic Item editor popup


Modified: branches/seials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm
===================================================================
--- branches/seials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm	2010-07-27 19:58:53 UTC (rev 17040)
@@ -395,10 +395,6 @@
 sub _update_sunit {
     my ($editor, $override, $sunit) = @_;
 
-#    my $evt;
-#    my $org = (ref $copy->circ_lib) ? $copy->circ_lib->id : $copy->circ_lib;
-#    return $evt if ( $evt = OpenILS::Application::Cat::AssetCommon->org_cannot_have_vols($editor, $org) );
-
     $logger->info("sunit-alter: retrieving sunit ".$sunit->id);
     my $orig_sunit = $editor->retrieve_serial_unit($sunit->id);
 
@@ -408,7 +404,60 @@
     return 0;
 }
 
+__PACKAGE__->register_method(
+	method	=> "retrieve_unit_list",
+    authoritative => 1,
+	api_name	=> "open-ils.serial.unit_list.retrieve"
+);
 
+sub retrieve_unit_list {
+
+	my( $self, $client, @sdist_ids ) = @_;
+
+	if(ref($sdist_ids[0])) { @sdist_ids = @{$sdist_ids[0]}; }
+
+	my $e = new_editor();
+
+    my $query = {
+        'select' => 
+            { 'sunit' => [ 'id', 'summary_contents', 'sort_key' ],
+              'sitem' => ['stream'],
+              'sstr' => ['distribution'],
+              'sdist' => [{'column' => 'label', 'alias' => 'sdist_label'}]
+            },
+        'from' =>
+            { 'sdist' =>
+                { 'sstr' =>
+                    { 'join' =>
+                        { 'sitem' =>
+                            { 'join' => { 'sunit' => {} } }
+                        }
+                    }
+                }
+            },
+        'distinct' => 'true',
+        'where' => { '+sdist' => {'id' => \@sdist_ids} },
+        'order_by' => [{'class' => 'sunit', 'field' => 'sort_key'}]
+    };
+
+    my $unit_list_entries = $e->json_query($query);
+    
+    my @entries;
+    foreach my $entry (@$unit_list_entries) {
+        my $value = {'sunit' => $entry->{id}, 'sstr' => $entry->{stream}, 'sdist' => $entry->{distribution}};
+        my $label = $entry->{summary_contents};
+        if (length($label) > 100) {
+            $label = substr($label, 0, 100) . '...'; # limited space in dropdown / menu
+        }
+        $label = "[$entry->{sdist_label}/$entry->{stream} #$entry->{id}] " . $label;
+        push (@entries, [$label, OpenSRF::Utils::JSON->perl2JSON($value)]);
+    }
+
+    return \@entries;
+}
+
+
+
 ##########################################################################
 # predict and receive methods
 #
@@ -706,6 +755,7 @@
             $sdist_by_stream_id{$stream_id} = $sdists->[0];
         } elsif ($unit_id == -2) { # create one unit for all '-2' items
             $unit_id = $new_unit_id;
+            $item->unit($unit_id);
         }
 
         $found_unit_ids{$unit_id} = 1;
@@ -818,7 +868,7 @@
     }
 
     $editor->commit;
-    return scalar @$items;
+    return {'num_items_received' => scalar @$items, 'new_unit_id' => $new_unit_id};
 }
 
 sub _build_unit {
@@ -829,7 +879,7 @@
     my $attr = $mode . '_unit_template';
     my $template = $editor->retrieve_asset_copy_template($sdist->$attr);
 
-    my @parts = qw( circ_lib status location loan_duration fine_level age_protect circulate deposit ref holdable deposit_amount price circ_modifier circ_as_type alert_message opac_visible floating mint_condition );
+    my @parts = qw( status location loan_duration fine_level age_protect circulate deposit ref holdable deposit_amount price circ_modifier circ_as_type alert_message opac_visible floating mint_condition );
 
     my $unit = new Fieldmapper::serial::unit;
     foreach my $part (@parts) {
@@ -837,9 +887,9 @@
         next if !defined($value);
         $unit->$part($value);
     }
-    if (!$template->circ_lib) {
-        $unit->circ_lib($sdist->holding_lib);
-    }
+
+    # ignore circ_lib in template, set to distribution holding_lib
+    $unit->circ_lib($sdist->holding_lib);
     $unit->creator($editor->requestor->id);
     $unit->editor($editor->requestor->id);
     $attr = $mode . '_call_number';
@@ -1223,7 +1273,6 @@
 	api_name	=> "open-ils.serial.subscription_tree.global.retrieve"
 );
 
-# user_session may be null/undef
 sub retrieve_sub_tree {
 
 	my( $self, $client, $user_session, $docid, @org_ids ) = @_;
@@ -1276,22 +1325,6 @@
 
 		#$dists = [ sort { $a->label cmp $b->label } @$dists  ];
 
-#		for my $dist (@$dists) {
-#			if( $c->status == OILS_COPY_STATUS_CHECKED_OUT ) {
-#				$c->circulations(
-#					$e->search_action_circulation(
-#						[
-#							{ target_copy => $c->id },
-#							{
-#								order_by => { circ => 'xact_start desc' },
-#								limit => 1
-#							}
-#						]
-#					)
-#				)
-#			}
-#		}
-
 		$sub->distributions($dists);
         
         # TODO: filter on !deleted?
@@ -1302,10 +1335,12 @@
 		#$issuances = [ sort { $a->label cmp $b->label } @$issuances  ];
 		$sub->issuances($issuances);
 
+        # TODO: filter on !deleted?
 		my $scaps = $e->search_serial_caption_and_pattern(
-			{ subscription => $sub->id }); # TODO: filter on !deleted?
+			[{ subscription => $sub->id }, { 'order_by' => {'scap' => 'id'} }]
+            );
 
-		$scaps = [ sort { $a->id cmp $b->id } @$scaps  ];
+		#$scaps = [ sort { $a->id cmp $b->id } @$scaps  ];
 		$sub->scaps($scaps);
 		push( @built_subs, $sub );
 	}

Modified: branches/seials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql
===================================================================
--- branches/seials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql	2010-07-27 19:58:53 UTC (rev 17040)
@@ -223,7 +223,7 @@
 	                        (
 	                            status IN ('Bindery', 'Bound', 'Claimed', 'Discarded', 'Expected', 'Not Held', 'Not Published', 'Received')
 	                        ) DEFAULT 'Expected',
-	shadowed        BOOL    DEFAULT FALSE -- ignore when generating summaries/labels
+	shadowed        BOOL    NOT NULL DEFAULT FALSE -- ignore when generating summaries/labels
 );
 
 CREATE TABLE serial.item_note (

Modified: branches/seials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js	2010-07-27 19:58:53 UTC (rev 17040)
@@ -426,6 +426,7 @@
     'XUL_SERIAL_ITEM_EDITOR' : '/xul/server/serial/item_editor.xul',
     'XUL_SERIAL_NOTES' : '/xul/server/serial/notes.xul',
     'XUL_SERIAL_SELECT_AOU' : '/xul/server/serial/select_aou.xul',
+    'XUL_SERIAL_SELECT_UNIT' : '/xul/server/serial/select_unit.xul',
     'XUL_SERIAL_SERCTRL_MAIN' : '/xul/server/serial/serctrl_main.xul',
     'XUL_SPINE_LABEL' : '/xul/server/cat/spine_labels.xul',
     'XUL_STAGED_PATRONS' : '/xul/server/patron/staged.xul',

Modified: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/editor_base.js	2010-07-27 19:58:53 UTC (rev 17040)
@@ -86,7 +86,7 @@
 
             var do_edit;
             if (typeof params.do_edit == 'undefined') {
-                do_edit = xul_params('do_edit',{'modal_xulG':true});
+                do_edit = xul_param('do_edit',{'modal_xulG':true});
             } else {
                 do_edit = params.do_edit;
             }
@@ -456,7 +456,7 @@
                 try {
                     if (block) return; block = true;
 
-                    function post_c(v) {
+                    function post_c(v, unchanged) {
                         try {
                             /* dbw2 not needed?
                             var t = input_cmd.match('apply_stat_cat') ? 'stat_cat' : ( input_cmd.match('apply_owning_lib') ? 'owning_lib' : 'attribute' );
@@ -473,7 +473,9 @@
                                 break;
                             }
                             obj.changed[ hbox.id ] = { 'type' : t, 'field' : f, 'value' : v }; */
-                            obj.changed[ hbox.id ] = true;
+                            if (!unchanged) {
+                                obj.changed[ hbox.id ] = true;
+                            }
                             block = false;
                             setTimeout(
                                 function() {
@@ -560,11 +562,14 @@
                 var xulG = {};
                 xulG[fm_type_plural] = obj[fm_type_plural];
                 update_modal_xulG(xulG);
-                window.close();
             } else {
                 obj.data['temp_' + fm_type_plural] = js2JSON( obj[fm_type_plural] );
                 obj.data.stash('temp_' + fm_type_plural);
             }
+
+            if (xul_param('in_modal',{'modal_xulG':true})) {
+                window.close();
+            }
         } catch(E) {
             obj.error.standard_unexpected_error_alert(fm_type + '_editor save',E);
         }

Modified: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.js	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.js	2010-07-27 19:58:53 UTC (rev 17040)
@@ -8,6 +8,9 @@
 	JSAN.use('util.error'); this.error = new util.error();
 	JSAN.use('util.network'); this.network = new util.network();
 	JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+
+    this.current_sunit_id = -1; //default to **AUTO**
+
 }
 
 serial.manage_items.prototype = {
@@ -18,11 +21,11 @@
 		var obj = this;
 
         try {
-            var holding_lib = $('serial_item_lib_menu').value;
-            robj = obj.network.request(
+            obj.holding_lib = $('serial_item_lib_menu').value;
+            var robj = obj.network.request(
                 'open-ils.pcrud',
                 'open-ils.pcrud.id_list.sdist',
-                [ ses(), {"holding_lib" : holding_lib, "+ssub":{"record_entry" : obj.docid}}, {"join":"ssub"} ]
+                [ ses(), {"holding_lib" : obj.holding_lib, "+ssub":{"record_entry" : obj.docid}}, {"join":"ssub"} ]
             );
             if (robj != null) {
                 if (typeof robj.ilsevent != 'undefined') throw(robj);
@@ -35,7 +38,7 @@
         }
     },
 
-    'build_lib_menu' : function () {
+    'build_menus' : function () {
 		var obj = this;
 
         // draw library drop-down
@@ -78,8 +81,8 @@
                 'command',
                 function(ev) {
                     if (document.getElementById('serial_item_refresh_button')) document.getElementById('serial_item_refresh_button').focus();
-                    JSAN.use('util.file'); var file = new util.file('manage_items_prefs.'+obj.data.server_unadorned);
-                    util.widgets.save_attributes(file, { 'serial_item_lib_menu' : [ 'value' ], 'serial_manage_items_mode' : [ 'selectedIndex' ], 'serial_manage_items_show_all' : [ 'checked' ] }); //FIXME: do load_attributes somewhere and check if selectedIndex does what we want here
+                    JSAN.use('util.file'); var file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
+                    util.widgets.save_attributes(file, { 'serial_item_lib_menu' : [ 'value' ], 'mode_receive' : [ 'selected' ], 'mode_bind' : [ 'selected' ], 'serial_manage_items_show_all' : [ 'checked' ] });
                     // get latest sdist id list based on library drowdown
                     obj.set_sdist_ids();
                     obj.refresh_list('main');
@@ -90,13 +93,26 @@
         } else {
             throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
         }
-        file = new util.file('manage_items_prefs.'+obj.data.server_unadorned);
+        file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
         util.widgets.load_attributes(file);
         ml.value = ml.getAttribute('value');
         if (! ml.value) {
             ml.value = org.id();
             ml.setAttribute('value',ml.value);
         }
+
+        // setup recent sunits list
+        var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
+        util.widgets.load_attributes(recent_sunits_file);
+        var recent_sunits_popup = $('serial_items_recent_sunits');
+        obj.sunit_entries = JSON2js(recent_sunits_popup.getAttribute('sunit_json'));
+        for (i = 0; i < obj.sunit_entries.length; i++) {
+            var sunit_info = obj.sunit_entries[i];
+            var new_menu_item = recent_sunits_popup.appendItem(sunit_info.label);
+            new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_info.id);
+            new_menu_item.setAttribute('sunit_id', sunit_info.id);
+            new_menu_item.setAttribute('command', 'cmd_set_sunit');
+        }
     },
 
 	'init' : function( params ) {
@@ -104,7 +120,8 @@
 
 		obj.docid = params['docid'];
 
-        obj.build_lib_menu();
+        obj.build_menus();
+        obj.set_sunit($('serial_items_current_sunit').getAttribute('sunit_id'), $('serial_items_current_sunit').getAttribute('sunit_label'), $('serial_items_current_sunit').getAttribute('sdist_id'), $('serial_items_current_sunit').getAttribute('sstr_id'));
         obj.set_sdist_ids();
 		obj.init_lists();
 
@@ -125,7 +142,7 @@
                                 new_item.issuance().subscription(1); //FIXME: hard-coded subscription
                                 new_item.isnew(1);
                                 new_item.issuance().isnew(1);
-                                spawn_item_editor( {'items' : [new_item], 'edit' : 1 } );
+                                spawn_sitem_editor( {'sitems' : [new_item], 'do_edit' : 1 } );
 
                                 obj.refresh_list('main');
 
@@ -148,7 +165,7 @@
                                         }
                                     );
 
-                                spawn_item_editor( { 'item_ids' : list, 'edit' : 1 } );
+                                spawn_sitem_editor( { 'sitem_ids' : list, 'do_edit' : 1 } );
 
                                 obj.refresh_list(obj.selected_list);
 
@@ -214,6 +231,28 @@
                             }
                         }
                     ],
+                    'cmd_set_sunit' : [
+                        ['command'],
+                        function(evt) {
+                            try {
+                                var target = evt.explicitOriginalTarget;
+                                var label = target.label;
+                                var sunit_id = target.getAttribute('sunit_id');
+                                var sdist_id = target.getAttribute('sdist_id');
+                                var sstr_id = target.getAttribute('sstr_id');
+                                obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
+                                obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
+                            } catch(E) {
+                                obj.error.standard_unexpected_error_alert('cmd_set_sunit failed!',E);
+                            }
+                        }
+                    ],
+                    'cmd_set_other_sunit' : [
+                        ['command'],
+                        function() {
+                            obj.set_other_sunit();
+                        }
+                    ],
                     'cmd_predict_items' : [
                         ['command'],
                         function() {
@@ -229,7 +268,7 @@
                                         obj.retrieve_ids,
                                         function (o) {
                                             var item = obj.list_sitem_map[o.sitem_id];
-                                            item.unit('-1'); //FIXME: hard-coded unit (-1 is AUTO)
+                                            item.unit(obj.current_sunit_id);
                                             return item;
                                         }
                                     );
@@ -241,7 +280,13 @@
                                         );
                                 if (typeof robj.ilsevent != 'undefined') throw(robj); //TODO: catch for override
 
-                                alert('Successfully received '+robj+' item(s)');
+                                alert('Successfully received '+robj.num_items_received+' item(s)');
+
+                                if (obj.current_sunit_id == -2) {
+                                    obj.current_sunit_id = robj.new_unit_id;
+                                }
+
+                                obj.rebuild_current_sunit(list[0].stream().distribution().label(), list[0].stream().distribution().id(), list[0].stream().id());
                                 obj.refresh_list('main');
                                 obj.refresh_list('workarea');
                                 
@@ -311,6 +356,122 @@
 		}
 	},
 
+	'rebuild_current_sunit' : function(sdist_label, sdist_id, sstr_id) {
+		var obj = this;
+		try {
+            var robj = obj.network.request(
+                'open-ils.pcrud',
+                'open-ils.pcrud.retrieve.sunit',
+                [ ses(),  obj.current_sunit_id]
+            );
+            if (!robj) return; // current sunit is NEW or AUTO
+
+            var label = '[' + sdist_label + '/' + sstr_id + ' #' + obj.current_sunit_id + '] ' + robj.summary_contents();
+            obj.set_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
+            obj.save_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
+		} catch(E) {
+			obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
+		}
+	},
+
+	'set_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
+		var obj = this;
+		try {
+            obj.current_sunit_id = sunit_id;
+            obj.current_sunit_sdist_id = sdist_id;
+            obj.current_sunit_sstr_id = sstr_id;
+            if (sunit_id < 0) {
+                $('serial_workarea_sunit_desc').firstChild.nodeValue = '**' + label + '**';
+            } else {
+                $('serial_workarea_sunit_desc').firstChild.nodeValue = label;
+                obj.add_sunit_to_menu(sunit_id, label, sdist_id, sstr_id);
+            }
+		} catch(E) {
+			obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
+		}
+	},
+
+	'save_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
+		var obj = this;
+		try {
+            $('serial_items_current_sunit').setAttribute('sunit_id', sunit_id);
+            $('serial_items_current_sunit').setAttribute('sunit_label', label);
+            if (sunit_id > 0) {
+                $('serial_items_current_sunit').setAttribute('sdist_id', sdist_id);
+                $('serial_items_current_sunit').setAttribute('sstr_id', sstr_id);
+            }
+            var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
+            util.widgets.save_attributes(recent_sunits_file, { 'serial_items_recent_sunits' : [ 'sunit_json' ], 'serial_items_current_sunit' : [ 'sunit_id', 'sunit_label', 'sdist_id', 'sstr_id' ] });
+		} catch(E) {
+			obj.error.standard_unexpected_error_alert('serial items save_sunit',E);
+		}
+	},
+
+	'set_other_sunit' : function() {
+		var obj = this;
+		try {
+            g.serial_items_sunit_select = '';
+            g.serial_items_sdist_ids = obj.sdist_ids;
+            JSAN.use('util.window'); var win = new util.window();
+            win.open(
+                xulG.url_prefix(urls.XUL_SERIAL_SELECT_UNIT),
+                'sel_serial_sunit_win_' + win.window_name_increment(),
+                'chrome,resizable,modal,centerscreen'
+            );
+            if (!g.serial_items_sunit_select) {
+                return;
+            }
+
+            var selection = g.serial_items_sunit_select;
+            var sunit_id = selection.sunit;
+            var sdist_id = selection.sdist;
+            var sstr_id = selection.sstr;
+            var label = selection.label;
+
+            obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
+            obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
+		} catch(E) {
+			obj.error.standard_unexpected_error_alert('serial items set_other_sunit',E);
+		}
+	},
+
+	'add_sunit_to_menu' : function(sunit_id, label, sdist_id, sstr_id) {
+		var obj = this;
+		try {
+            if (sunit_id > 0) {
+                // check if it is already in sunit_entries, remove it
+                for (i = 0; i < obj.sunit_entries.length; i++) {
+                    if (obj.sunit_entries[i].id == sunit_id) {
+                        obj.sunit_entries.splice(i,1);
+                        var menu_item = $('serial_items_recent_sunits_entry_'+sunit_id);
+                        menu_item.parentNode.removeChild(menu_item);
+                        i--;
+                    }
+                }
+                // add to front of array
+                obj.sunit_entries.unshift({"id" : sunit_id, "label" : label, "sdist_id" : sdist_id, "sstr_id" : sstr_id});
+                var recent_sunits_popup = $('serial_items_recent_sunits');
+                var new_menu_item = recent_sunits_popup.insertItemAt(0,label);
+                new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_id);
+                new_menu_item.setAttribute('sunit_id', sunit_id);
+                new_menu_item.setAttribute('sdist_id', sdist_id);
+                new_menu_item.setAttribute('sstr_id', sstr_id);
+                new_menu_item.setAttribute('command', 'cmd_set_sunit');
+
+                // pop off from sunit_entries if it already has 10 sunits
+                if (obj.sunit_entries.length > 10) {
+                    var sunit_info = obj.sunit_entries.pop();
+                    var menu_item = $('serial_items_recent_sunits_entry_'+sunit_info.id);
+                    menu_item.parentNode.removeChild(menu_item);
+                }
+
+                recent_sunits_popup.setAttribute('sunit_json', js2JSON(obj.sunit_entries));
+            }
+		} catch(E) {
+			obj.error.standard_unexpected_error_alert('serial items add_sunit_to_menu',E);
+		}
+	},
+
 	'init_lists' : function() {
 		var obj = this;
 
@@ -320,20 +481,21 @@
         function retrieve_row(params) {
 			try { 
 				var row = params.row;
-                obj.network.simple_request( //FIXME: pcrud fleshing won't work!!
-                    'FM_SITEM_RETRIEVE',
-                    //[ ses(), row.my.sitem_id, {"flesh":1, "flesh_fields":{"sitem": ["creator","editor","distribution","shelving_unit"]}}],
-                    [ ses(), row.my.sitem_id, {"flesh":2,"flesh_fields":{"sitem":["creator","editor","issuance","stream","unit","notes"], "sunit":["call_number"], "sstr":["distribution"]}}], // TODO: we really need note count only, not the actual notes, is there a smart way to do that?
+                obj.network.simple_request(
+                    'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative',
+                    [[row.my.sitem_id]],
+                    //[ ses(), row.my.sitem_id, {"flesh":2,"flesh_fields":{"sitem":["creator","editor","issuance","stream","unit","notes"], "sunit":["call_number"], "sstr":["distribution"]}}],
                     function(req) {
                         try {
                             var robj = req.getResultObject();
                             if (typeof robj.ilsevent != 'undefined') throw(robj);
                             if (typeof robj.ilsevent == 'null') throw('null result');
-                            obj.list_sitem_map[robj.id()] = robj;
-                            row.my.sitem = robj;
+                            var sitem = robj[0];
+                            obj.list_sitem_map[sitem.id()] = sitem;
+                            row.my.sitem = sitem;
                             //params.row_node.setAttribute( 'retrieve_id', js2JSON({'copy_id':copy_id,'circ_id':row.my.circ.id(),'barcode':row.my.acp.barcode(),'doc_id': ( row.my.record ? row.my.record.id() : null ) }) );
-                            params.row_node.setAttribute( 'retrieve_id', js2JSON({'sitem_id':robj.id()}) );
-                            dump('dumping... ' + js2JSON(obj.list_sitem_map[robj.id()]));
+                            params.row_node.setAttribute( 'retrieve_id', js2JSON({'sitem_id':sitem.id()}) );
+                            dump('dumping... ' + js2JSON(obj.list_sitem_map[sitem.id()]));
                             if (typeof params.on_retrieve == 'function') {
                                 params.on_retrieve(row);
                             }
@@ -378,7 +540,11 @@
 				}
 			}
 		);
-        obj.lists.main.sitem_retrieve_params = {'date_received' : null };
+        if (document.getElementById('serial_manage_items_show_all').checked) {
+            obj.lists.main.sitem_retrieve_params = {};
+        } else {
+            obj.lists.main.sitem_retrieve_params = {'date_received' : null };
+        }
         obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
 
         obj.lists.workarea = new util.list('workarea_tree');
@@ -455,6 +621,7 @@
         }
 
 		list.clear();
+
         for (i = 0; i < robj.length; i++) {
             list.append( { 'row' : { 'my' : { 'sitem_id' : robj[i] } }, 'to_bottom' : true, 'no_auto_select' : true } );
         }
@@ -664,12 +831,12 @@
     return c;
 };
 
-spawn_item_editor = function(params) {
+spawn_sitem_editor = function(params) {
     try {
-        if (!params.item_ids && !params.items) return;
-        if (params.item_ids && params.item_ids.length == 0) return;
-        if (params.items && params.items.length == 0) return;
-        if (params.item_ids) params.item_ids = js2JSON(params.item_ids); // legacy
+        if (!params.sitem_ids && !params.sitems) return;
+        if (params.sitem_ids && params.sitem_ids.length == 0) return;
+        if (params.sitems && params.sitems.length == 0) return;
+        if (params.sitem_ids) params.sitem_ids = js2JSON(params.sitem_ids); // legacy
         if (!params.caller_handles_update) params.handle_update = 1; // legacy
 
         var obj = {};
@@ -677,30 +844,31 @@
         JSAN.use('util.error'); obj.error = new util.error();
 
         var title = '';
-        if (params.item_ids && params.item_ids.length > 1 && params.edit == 1)
+        if (params.sitem_ids && params.sitem_ids.length > 1 && params.do_edit == 1)
             title = 'Batch Edit Items';
-        else /* if(params.copies && params.copies.length > 1 && params.edit == 1)
+        else /* if(params.sitems && params.sitems.length > 1 && params.do_edit == 1)
             title = 'Batch View Items';
-        else if(params.item_ids && params.item_ids.length == 1) */
+        else if(params.sitem_ids && params.sitem_ids.length == 1) */
             title = 'Edit Item';/*
         else
             title = 'View Item';*/
 
         JSAN.use('util.window'); var win = new util.window();
+        params.in_modal = true;
         var my_xulG = win.open(
             (urls.XUL_SERIAL_ITEM_EDITOR),
             title,
             'chrome,modal,resizable',
             params
         );
-        if (my_xulG.items && params.edit) {
-            return my_xulG.items;
+        if (my_xulG.sitems && params.do_edit) {
+            return my_xulG.sitems;
         } else {
             return [];
         }
     } catch(E) {
         JSAN.use('util.error'); var error = new util.error();
-        error.standard_unexpected_error_alert('error in spawn_item_editor',E);
+        error.standard_unexpected_error_alert('error in spawn_sitem_editor',E);
     }
 }
 

Modified: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.xul	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_items.xul	2010-07-27 19:58:53 UTC (rev 17040)
@@ -83,24 +83,22 @@
         <tree id="item_tree" flex="2" enableColumnDrag="true" context="serial_manage_items_popup"/>
         <splitter state="open" collapse="after" resizebefore="closest" resizeafter="farthest"/>
         <hbox align="center">
-            <label style="font-weight: bold" value="Workarea"/>
+            <label style="font-weight: bold" value="Showing: "/>
             <label id="serial_workarea_type_label" value="Recently Received"/>
             <spacer flex="1"/>
             <button label="Receive/Move Selected &#8595;" command="cmd_receive_items"/>
-            <description value="into"/>
-            <description id="serial_workarea_unit_desc" value="[**AUTO**]"/>
+        </hbox>
+        <hbox align="center">
+            <label style="font-weight: bold" value="Current Working Unit: "/>
+            <description flex="1" id="serial_workarea_sunit_desc">**Auto per Item**</description>
+            <spacer flex="1"/>
             <menubar>
-                <menu label="Set Current Unit">
+                <menu label="Set Current Unit" id="serial_items_current_sunit" sunit_id="-1" sunit_label="Auto per Item" sdist_id="" sstr_id="">
                     <menupopup>
-                        <menuitem command="cmd_broken" label="New Unit"/>
-                        <menuitem command="cmd_broken" label="Auto per Item"/>
-                        <menu label="Recent">
-                            <menupopup>
-                                <menuitem command="cmd_broken" label="V.1"/>
-                                <menuitem command="cmd_broken" label="V.2"/>
-                            </menupopup>
-                        </menu>
-                        <menuitem command="cmd_broken" label="Other..."/>
+                        <menuitem command="cmd_set_sunit" label="New Unit" sunit_id="-2" sdist_id="" sstr_id=""/>
+                        <menuitem command="cmd_set_sunit" label="Auto per Item" sunit_id="-1" sdist_id="" sstr_id=""/>
+                        <menu label="Recent" id="serial_items_recent_sunits" sunit_json='[]'/>
+                        <menuitem command="cmd_set_other_sunit" label="Other..."/>
                     </menupopup>
                 </menu>
                 <button command="cmd_broken" label="Edit Current Unit..."/>

Modified: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js	2010-07-27 17:27:01 UTC (rev 17039)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/manage_subs.js	2010-07-27 19:58:53 UTC (rev 17040)
@@ -1147,7 +1147,7 @@
         var id = obj.focused_node_retrieve_id.split('_')[1];
 
         if (sel_lists[row_type]) { // the type focused is in the selection (usually the case)
-            obj['on_click_' + row_type](sel_lists[row_type],twisty);
+            if (obj['on_click_' + row_type]) obj['on_click_' + row_type](sel_lists[row_type],twisty);
         }
     },
 

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_unit.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_unit.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/select_unit.xul	2010-07-27 19:58:53 UTC (rev 17040)
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Select Serial Unit Dialog -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/cat.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+	<!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="select_serial_unit_win" title="Select Serial Unit"
+	onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }" oils_persist="height width"
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+	<!-- BEHAVIOR -->
+	<script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script>
+	<scripts id="openils_util_scripts"/>
+
+	<script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+	<script>
+	<![CDATA[
+		function $(id) { return document.getElementById(id); }
+
+		function my_init() {
+			try {
+				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
+				JSAN.errorLevel = "die"; // none, warn, or die
+				JSAN.addRepository('/xul/server/');
+				JSAN.use('util.error'); g.error = new util.error();
+				g.error.sdump('D_TRACE','my_init() for serial/select_unit.xul');
+
+                JSAN.use('util.widgets');
+
+                var ml;
+				JSAN.use('util.network'); g.network = new util.network();
+                var robj = g.network.request(
+                    'open-ils.serial',
+                    'open-ils.serial.unit_list.retrieve',
+                    opener.g.serial_items_sdist_ids
+                );
+                if (typeof robj.ilsevent != 'undefined') throw(robj);
+                ml = util.widgets.make_menulist(robj);
+                ml.setAttribute('id','unit_menu');
+                document.getElementById('x_unit_menu').appendChild(ml);
+            } catch(E) {
+                //TODO: better error
+                g.error.standard_unexpected_error_alert('', E);
+            }
+        }
+
+        g.select_unit = function() {
+            var selection = JSON2js($('unit_menu').value);
+            selection.label = $('unit_menu').selectedItem.label;
+            opener.g.serial_items_sunit_select = selection;
+            window.close();
+        }
+
+	]]>
+	</script>
+	
+	<messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+
+	<vbox flex="1" style="overflow: auto">
+	<groupbox flex="1">
+<!--TODO: label strings -->
+		<caption label="Select a Serial Unit"/>
+		<description id="desc">Please select a Serial Unit</description>
+        <hbox id="x_unit_menu"/>
+		<hbox>
+			<button label="Select"
+				accesskey="s" oncommand="g.select_unit()"/>
+			<button label="&staff.cat.record_buckets_quick.cancel.label;"
+				accesskey="&staff.cat.record_buckets_quick.cancel.accesskey;" oncommand="window.close()"/>
+		</hbox>
+		<hbox>
+		</hbox>
+	</groupbox>
+	</vbox>
+
+</window>
+

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.js
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.js	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.js	2010-07-27 19:58:53 UTC (rev 17040)
@@ -0,0 +1,186 @@
+dump('entering serial/sitem_editor.js\n');
+// vim:noet:sw=4:ts=4:
+
+JSAN.addRepository('/xul/server/');
+JSAN.use('serial.editor_base');
+
+if (typeof serial == 'undefined') serial = {};
+serial.sitem_editor = function (params) {
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        JSAN.use('util.error'); this.error = new util.error();
+        JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
+        JSAN.use('util.network'); this.network = new util.network();
+    } catch(E) {
+        dump('serial/sitem_editor: ' + E + '\n');
+    }
+
+    /* This keeps track of what fields have been edited for styling purposes */
+    this.changed = {};
+
+    /* This holds the original values for prepopulating the field editors */
+    this.editor_values = {};
+};
+
+serial.sitem_editor.prototype = {
+    // we could do this with non-standard '__proto__' property instead
+    'editor_base_init' : serial.editor_base.editor_base_init,
+    'editor_base_apply' : serial.editor_base.editor_base_apply,
+    'editor_base_save' : serial.editor_base.editor_base_save,
+
+    'fm_type' : 'sitem',
+    'fm_type_plural' : 'sitems',
+    'can_have_notes' : true,
+
+    'init' : function (params) {
+        var obj = this;
+
+        params.retrieve_function = 'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative';
+
+        obj.editor_base_init(params);
+
+        /* Do it */
+        obj.summarize( obj.sitems );
+        obj.render();
+    },
+
+    /******************************************************************************************************/
+    /* Restore backup copies */
+
+    'reset' :  serial.editor_base.editor_base_reset,
+
+    /******************************************************************************************************/
+    /* Apply a value to a specific field on all the copies being edited */
+
+    'apply' : function(field,value) {
+        var obj = this;
+        JSAN.use('util.date');
+        if (field == 'date_expected') {
+            if (value == '') {
+                alert("Date Expected cannot be unset.");
+                return false;
+            } else if (!util.date.check('YYYY-MM-DD',value)) {
+                alert("Invalid Date");
+                return false;
+            }
+        } else if (field == 'date_received') { // manually unset not allowed
+            if (value == '') {
+                alert("Date Received cannot be manually unset; use 'Reset to Expected' instead.");
+                return false;
+            } else if (!util.date.check('YYYY-MM-DD',value)) {
+                alert("Invalid Date");
+                return false;
+            }
+        }
+        obj.editor_base_apply(field, value);
+        return true;
+    },
+
+    /******************************************************************************************************/
+
+    'init_panes' : function () {
+        var obj = this;
+        obj.panes_and_field_names = {
+
+        /* These get shown in the left panel */
+        'sitem_editor_left_pane' :
+        [
+            [
+                'ID',
+                { 
+                    render: '"#" + fm.id();', 
+
+                }
+            ],
+            [
+                'Status',
+                { 
+                    render: 'fm.status();',
+                    value_key: 'label'
+                }
+            ]
+        ],
+        /* These get shown in the middle panel */
+        'sitem_editor_middle_pane' :
+        [
+            [
+                'Distribution',
+                {
+                    render: 'fm.stream().distribution().label() == null ? "" : fm.stream().distribution().label();',
+
+                }
+            ],
+            [
+                'Shelving Unit ID',
+                {
+                    render: 'fm.unit() == null ? "" : "#" + fm.unit().id();',
+                }
+            ],
+        ],
+
+        /* These get shown in the right panel */
+        'sitem_editor_right_pane' :
+        [
+            [
+                'Date Expected',
+                {
+                    render: 'fm.date_expected() == null ? "" : util.date.formatted_date( fm.date_expected(), "%F");',
+                    input: 'c = function(v){ var applied = obj.apply("date_expected",v); if (typeof post_c == "function") post_c(v, !applied);}; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.date_expected); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+                    value_key: 'date_expected'
+                }
+            ],
+            [
+                'Date Received',
+                {
+                    render: 'fm.date_received() == null ? "" : util.date.formatted_date( fm.date_received(), "%F");',
+                    input: 'if (obj.editor_values.date_received) { c = function(v){ var applied = obj.apply("date_received",v); if (typeof post_c == "function") post_c(v, !applied);}; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.date_received); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false); } else { alert("Cannot edit Date Received for unreceived items."); block = false; }',
+                    value_key: 'date_received'
+                }
+            ],
+        ],
+
+        };
+    },
+
+    /******************************************************************************************************/
+    /* This loops through all our fieldnames and all the copies, tallying up counts for the different values */
+
+    'summarize' :  serial.editor_base.editor_base_summarize,
+
+    /******************************************************************************************************/
+    /* Display the summarized data and inputs for editing */
+
+    'render' :  serial.editor_base.editor_base_render,
+
+    /******************************************************************************************************/
+    /* This actually draws the change button and input widget for a given field */
+    'render_input' : serial.editor_base.editor_base_render_input,
+
+    /******************************************************************************************************/
+    /* save the items */
+
+    'save' : function() {
+        var obj = this;
+        obj.editor_base_save('open-ils.serial.item.fleshed.batch.update');
+    },
+
+    /******************************************************************************************************/
+    /* spawn notes interface */
+
+    'notes' : function() {
+        var obj = this;
+        JSAN.use('util.window'); var win = new util.window();
+        win.open(
+            urls.XUL_SERIAL_NOTES, 
+            //+ '?copy_id=' + window.escape(obj.sitems[0].id()),
+            'Item Notes','chrome,resizable,modal',
+            { 'object_id' : obj.sitems[0].id(), 'function_type' : 'SIN', 'object_type' : 'item', 'constructor' : sin }
+        );
+    },
+
+    /******************************************************************************************************/
+    'save_attributes' : serial.editor_base.editor_base_save_attributes
+
+};
+
+dump('exiting serial/sitem.js\n');

Added: branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.xul
===================================================================
--- branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.xul	                        (rev 0)
+++ branches/seials-integration/Open-ILS/xul/staff_client/server/serial/sitem_editor.xul	2010-07-27 19:58:53 UTC (rev 17040)
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<!-- Application: Evergreen Staff Client -->
+<!-- Screen: Serial Item Editor -->
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- STYLESHEETS -->
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://open_ils_staff_client/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- LOCALIZATION -->
+<!DOCTYPE window PUBLIC "" ""[
+	<!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+
+<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+<!-- OVERLAYS -->
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+
+<window id="serial_item_editor_win" 
+	onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }"
+	width="800" height="390" oils_persist="width height"
+	title="Item Editor"
+	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+	<!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
+	<!-- BEHAVIOR -->
+    <script type="text/javascript">
+		var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};
+	</script>
+    <scripts id="openils_util_scripts"/>
+
+	<script type="text/javascript" src="/xul/server/main/JSAN.js"/>
+	<script type="text/javascript" src="sitem_editor.js"/>
+    <script>
+        <![CDATA[
+            function my_init() {
+                try {
+                    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                    if (typeof JSAN == 'undefined') { 
+                        throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+                    }
+                    JSAN.errorLevel = "die"; // none, warn, or die
+                    JSAN.addRepository('/xul/server/');
+                    JSAN.use('util.error'); g.error = new util.error();
+                    g.error.sdump('D_TRACE','my_init() for serial/sitem_editor.xul');
+                    JSAN.use('serial.sitem_editor'); g.sitem_editor = new serial.sitem_editor();
+
+                    g.sitem_editor.init({"do_edit" : true, "handle_update" : true});
+
+                } catch(E) {
+                    var err_msg = document.getElementById("commonStrings").getFormattedString('common.exception', ['serial/sitem_editor.xul', E]);
+                    try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
+                    alert(err_msg);
+                }
+            }
+
+        ]]>
+    </script>
+
+	<messagecatalog id="catStrings" src="/xul/server/locale/<!--#echo var='locale'-->/cat.properties" />
+	<messagecatalog id="serialStrings" src="/xul/server/locale/<!--#echo var='locale'-->/serial.properties" />
+
+    <vbox id="brief_display_box"/>
+
+	<groupbox flex="1" class="my_overflow">
+		<hbox flex="1" style="overflow: auto">
+			<vbox flex="1">
+				<label value="Item" style="font-weight: bold; font-size: large"/>
+				<vbox id="sitem_editor_left_pane" flex="1"/>
+			</vbox>
+			<splitter><grippy /></splitter>
+			<vbox flex="1">
+				<label value=" " style="font-weight: bold; font-size: large"/>
+				<vbox id="sitem_editor_middle_pane" flex="1"/>
+			</vbox>
+			<splitter><grippy /></splitter>
+			<vbox flex="1">
+				<button style="font-weight: bold; font-size: normal" label="Item Dates" accesskey="1" oncommand="document.getElementById('sitem_editor_right_pane').firstChild.firstChild.focus();"/>
+				<vbox id="sitem_editor_right_pane" flex="1"/>
+			</vbox>
+		</hbox>
+
+		<hbox id="nav">
+			<spacer flex="1"/>
+			<button id="sitem_notes" label="&staff.serial.sitem_editor.notes;" accesskey="&staff.serial.sitem_editor.notes.accesskey;" oncommand="g.sitem_editor.notes();"/>
+			<button id="sitem_save" label="&staff.serial.sitem_editor.modify;" hidden="true" accesskey="&staff.serial.sitem_editor.modify.accesskey;" oncommand="g.sitem_editor.save();"/>
+			<button id="sitem_cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>
+		</hbox>
+
+		<spacer/>
+	</groupbox>
+
+</window>
+



More information about the open-ils-commits mailing list