merging admin interface from the dojo-admin branch
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 11 Apr 2008 03:45:49 +0000 (03:45 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 11 Apr 2008 03:45:49 +0000 (03:45 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@9309 dcc99617-32d9-48b4-a31d-7c20da2025e4

13 files changed:
Open-ILS/src/Makefile
Open-ILS/src/extras/autogen.sh
Open-ILS/web/conify/global/actor/org_unit.html [new file with mode: 0644]
Open-ILS/web/conify/global/actor/org_unit.js [new file with mode: 0644]
Open-ILS/web/conify/global/actor/org_unit_type.html [new file with mode: 0644]
Open-ILS/web/conify/global/actor/org_unit_type.js [new file with mode: 0644]
Open-ILS/web/conify/global/admin.html [new file with mode: 0644]
Open-ILS/web/conify/global/config/copy_status.html [new file with mode: 0644]
Open-ILS/web/conify/global/config/copy_status.js [new file with mode: 0644]
Open-ILS/web/conify/global/permission/grp_tree.html [new file with mode: 0644]
Open-ILS/web/conify/global/permission/grp_tree.js [new file with mode: 0644]
Open-ILS/web/conify/global/permission/perm_list.html [new file with mode: 0644]
Open-ILS/web/conify/global/permission/perm_list.js [new file with mode: 0644]

index 335f05a..5abe169 100644 (file)
@@ -72,6 +72,9 @@ webcore-install:
        mkdir -p $(WEBDIR)/opac/extras/xsl/
        cp -r ../web/* $(WEBDIR)
        cp $(OPENSRF_LIBS)/javascript/* $(WEBDIR)/opac/common/js/
+       # dojo-ified opensrf libs
+       cp $(OPENSRF_LIBS)/javascript/opensrf*js $(WEBDIR)/js/opensrf/
+       cp $(OPENSRF_LIBS)/javascript/OpenSRF.js $(WEBDIR)/js/
        ln -sf $(WEBDIR)/opac/skin/default/xml/index.xml $(WEBDIR)/opac/skin/default/xml/mresult.xml
        ln -sf $(WEBDIR)/opac/skin/default/xml/index.xml $(WEBDIR)/opac/skin/default/xml/rresult.xml
        ln -sf $(WEBDIR)/opac/skin/default/xml/index.xml $(WEBDIR)/opac/skin/default/xml/rdetail.xml
index 58f4530..73e5bdb 100755 (executable)
@@ -70,6 +70,7 @@ done
 [ -z "$CONFIG" ] && usage;
 
 JSDIR="/openils/var/web/opac/common/js/";
+FMDOJODIR="/openils/var/web/js/dojo/fieldmapper/";
 SLIMPACDIR="/openils/var/web/opac/extras/slimpac/";
 
 echo "Updating fieldmapper";
@@ -83,9 +84,11 @@ perl org_tree_js.pl "$CONFIG" > "$JSDIR/OrgTree.js";
 
 echo "Updating OrgTree HTML";
 perl org_tree_html_options.pl "$CONFIG" "$SLIMPACDIR/lib_list.inc";
+cp "$JSDIR/OrgTree.js" "$FMDOJODIR/"
 
 echo "Updating Search Groups";
 perl org_lasso_js.pl "$CONFIG" > "$JSDIR/OrgLasso.js";
+cp "$JSDIR/OrgLasso.js" "$FMDOJODIR/"
 
 if [ "$PROXIMITY" ]
 then
diff --git a/Open-ILS/web/conify/global/actor/org_unit.html b/Open-ILS/web/conify/global/actor/org_unit.html
new file mode 100644 (file)
index 0000000..b250faa
--- /dev/null
@@ -0,0 +1,811 @@
+<!--
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+       <head>
+               <title>Confiy :: Global :: Actor :: Org Units</title>
+
+               <style type="text/css">
+                       @import url("/js/dojo/dojo/resources/dojo.css");
+                       @import url("/js/dojo/dijit/themes/tundra/tundra.css");
+                       @import url("/js/dojo/dojox/widget/Toaster/Toaster.css");
+               </style>
+
+               <style>
+                       html, body
+                       {
+                               height: 100%;
+                               width: 100%;
+                               margin: 0px 0px 0px 0px;
+                               padding: 0px 0px 0px 0px;
+                               overflow: hidden;
+                       }
+
+                       th
+                       {
+                               text-align: right;
+                               font-weight: bold;
+                               padding-left: 20px;
+                               padding-right: 5px;
+                       }
+               </style>
+
+               <!-- The OpenSRF API writ JS -->
+               <script language='javascript' src='/opac/common/js/utils.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/Cookies.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/CGI.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/JSON_v1.js' type='text/javascript'></script>
+
+               <!-- Fieldmapper objects -->
+               <script language='javascript' src='/opac/common/js/fmall.js' type='text/javascript'></script>
+
+               <!-- Dojo goodness -->
+               <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+               <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
+
+               <script type="text/javascript" src="org_unit.js"></script>
+
+       </head>
+
+       <body class="tundra" id='pagebody'>
+
+               <div dojoType="dijit.layout.SplitContainer" orientation="horizontal" style="height: 100%">
+
+                       <div dojoType="dijit.layout.ContentPane" sizeShare="100">
+                               <script type="dojo/method">
+
+                                       var ou_list_data = { label : 'shortname', identifier : 'id' };
+                                       window.dirtyStore = [];
+               
+                                       pCRUD.request({
+                                               method : 'open-ils.permacrud.search.aou.atomic',
+                                               timeout : 15,
+                                               params : [ ses, { id : { "!=" : null } }, { order_by : { aou : 'shortname' } } ],
+                                               onerror : function (r) { throw 'Problem fetching org units';},
+                                               oncomplete : function (r) {
+                                                       window._ou_list = r.recv().content();
+                                                       window._ou_data = aou.toStoreData( window._ou_list );
+                                                       window.ou_list_store = new dojo.data.ItemFileWriteStore({ data : window._ou_data });
+
+                                                       window.ou_list_store.onSet = function (item, attr, o, n) {
+                                                               if (attr == 'ischanged') return;
+                                                               if (n == o) return;
+                                                               this.setValue( item, 'ischanged', 1);
+                                                       };
+
+                                                       dojo.addOnUnload( function (event) {
+
+                                                               ou_list_store.fetch({
+                                                                       query : { ischanged : 1 },
+                                                                       queryOptions : { deep : true },
+                                                                       onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
+                                                                       scope : ou_list_store
+                                                               });
+
+                                                               if (dirtyStore.length > 0) {
+                                                                       var confirmation = confirm(
+                                                                               'There are unsaved modified Organizational Units!  '+
+                                                                               'OK to save these changes, Cancel to abandon them.'
+                                                                       );
+
+                                                                       if (confirmation) {
+                                                                               for (var i in window.dirtyStore) {
+                                                                                       window.current_ou = window.dirtyStore[i];
+                                                                                       save_org(true);
+                                                                               }
+                                                                       }
+                                                               }
+
+                                                       });
+                                               }
+                                       }).send();
+
+                    pCRUD.request({
+                        method : 'open-ils.permacrud.search.aout.atomic',
+                        timeout : 10,
+                        params : [ ses, { id : { "!=" : null } }, { order_by : { aout : 'depth' } } ],
+                        onerror : function (r) { status_update('Problem fetching types') },
+                        oncomplete : function (r) {
+                            window._ou_type_list = r.recv().content();
+                            window._ou_type_data = aout.toStoreData( window._ou_type_list );
+                            window.ou_type_store = new dojo.data.ItemFileReadStore({ data : window._ou_type_data });
+                        }
+                    }).send();
+
+                                       highlighter.ou_tree = {};
+                                       highlighter.editor_pane = {};
+                                       highlighter.hoo_pane = {};
+                                       highlighter.addresses_pane = {};
+
+                                       highlighter.ou_tree.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'ou_tree', duration : 500 } );
+                                       highlighter.ou_tree.red = dojox.fx.highlight( { color : '#FF2018', node : 'ou_tree', duration : 500 } );
+
+                                       highlighter.editor_pane.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'editor_pane', duration : 500 } );
+                                       highlighter.editor_pane.red = dojox.fx.highlight( { color : '#FF2018', node : 'editor_pane', duration : 500 } );
+
+                                       highlighter.hoo_pane.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'hoo_pane', duration : 500 } );
+                                       highlighter.hoo_pane.red = dojox.fx.highlight( { color : '#FF2018', node : 'hoo_pane', duration : 500 } );
+
+                                       highlighter.addresses_pane.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'addresses_pane', duration : 500 } );
+                                       highlighter.addresses_pane.red = dojox.fx.highlight( { color : '#FF2018', node : 'addresses_pane', duration : 500 } );
+                               </script>
+                               <div
+                                 id="ou_tree"
+                                 label="Organizational Units"
+                                 query="{'_top':'true'}"
+                                 dojoType="dijit.Tree"
+                                 store="ou_list_store"
+                                 minSize="200"
+                                 jsId="ou_tree"
+                               >
+
+                                       <script type="dojo/method" event="onClick" args="item,node">
+
+                                               right_pane_toggler.show();
+
+                                               current_ou = item;
+
+                                               highlighter.editor_pane.green.play();
+                                               status_update( 'Now editing ' + this.store.getValue( item, 'name' ) );
+
+                                               new_kid_button.disabled = false;
+                                               save_ou_button.disabled = false;
+                                               delete_ou_button.disabled = false;
+
+                                               dojo.byId('current_ou_name').innerHTML = this.store.getValue( current_ou, 'name' );
+
+                                               var main_settings_fields = [ 'name', 'shortname', 'email', 'phone', 'ou_type' ];
+                                               for ( var i in main_settings_fields ) {
+                                                       var field = main_settings_fields[i];
+                                                       var value = this.store.getValue( current_ou, field );
+
+                                                       if (!value) {
+                                                               window["editor_pane_" + field].setValue( '' ); // unset the value
+                                                               window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
+                                                       } else window["editor_pane_" + field].setValue( value );
+                                               }
+
+                                               if ( this.store.getValue( current_ou, '_trueRoot' ) == 'true' ) {
+                                                       editor_pane_parent_ou.disabled = true;
+                                                       editor_pane_parent_ou.setValue(null);
+                                                       editor_pane_parent_ou.setDisplayedValue('');
+                                                       editor_pane_parent_ou.validate(false);
+                                               } else {
+                                                       editor_pane_parent_ou.disabled = false;
+                                                       editor_pane_parent_ou.validate(true);
+                                                       editor_pane_parent_ou.setValue( this.store.getValue( current_ou, 'parent_ou' ) );
+                                               }
+
+                                               editor_pane_opac_visible.setChecked( this.store.getValue( current_ou, 'opac_visible' ) == 't' ? true : false );
+
+                                               hoo_load();
+                                               addr_load();
+
+                                       </script>
+
+                                       <script type="dojo/method" event="getLabel" args="item,pI">
+                                               var label = this.store.getValue(item,'shortname') + ' : ' + this.store.getValue(item,'name');
+                                               if (this.store.getValue(item,'ischanged') == 1) label = '* ' + label;
+                                               return label;
+                                       </script>
+
+                               </div>
+                       </div>
+
+                       <div jsId="right_pane" id="right_pane" dojoType="dijit.layout.ContentPane"  sizeShare="200">
+                               <script type="dojo/method">
+                                       window.right_pane_toggler = new dojo.fx.Toggler({ node: 'right_pane'});
+                                       window.right_pane_toggler.hide();
+                               </script>
+
+                               <div id="right_tabpane" dojoType="dijit.layout.TabContainer">
+       
+                                       <div id="editor_pane" dojoType="dijit.layout.ContentPane" title="Main Settings">
+
+                                               <table class="tundra" style="margin:10px;">
+                                                       <tr>
+                                                               <th>Org Unit Name</th>
+                                                               <td>
+                                                                       <span id="editor_pane_name" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_name" regExp=".+" required="true">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_ou) ou_list_store.setValue( current_ou, "name", this.getValue() );
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Org Unit Policy Code</th>
+                                                               <td>
+                                                                       <span id="editor_pane_shortname" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_shortname" uppercase="true" regExp=".+" required="true">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_ou) ou_list_store.setValue( current_ou, "shortname", this.getValue() );
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Main Email Address</th>
+                                                               <td>
+                                                                       <span id="editor_pane_email" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_email" regExp="^\w+\@\w+(?:\.\w+)+$">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_ou) ou_list_store.setValue( current_ou, "email", this.getValue() );
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Main Phone Number</th>
+                                                               <td>
+                                                                       <span id="editor_pane_phone" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_phone" regExp="^(?:(?:\d{1}[ -\.])?\(?\d{3}\)?[ -\.]{1})?\d{3}[ -\.]{1}\d{4}(| \S+.*)$">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_ou) ou_list_store.setValue( current_ou, "phone", this.getValue() );
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Org Unit Type</th>
+                                                               <td>
+                                                                       <div
+                                                                         id="editor_pane_ou_type"
+                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                         jsId="editor_pane_ou_type"
+                                                                         store="ou_type_store"
+                                                                         searchAttr="name"
+                                                                         ignoreCase="true"
+                                                                         required="true"
+                                                                       >
+                                                                               <script type="dojo/method" event="onChange">
+                                                                                       if (current_ou) ou_list_store.setValue( current_ou, "ou_type", this.getValue() );
+                                                                               </script>
+                                                                       </div>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Parent Org Unit</th>
+                                                               <td>
+                                                                       <div
+                                                                         id="editor_pane_parent_ou"
+                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                         jsId="editor_pane_parent_ou"
+                                                                         store="ou_list_store"
+                                                                         searchAttr="shortname"
+                                                                         ignoreCase="true"
+                                                                         required="true"
+                                                                       >
+                                                                               <script type="dojo/method" event="onChange">
+                                                                                       if (current_ou && this.getValue()) this.store.setValue( current_ou, "parent_ou", this.getValue() );
+                                                                                       if ( this.store.getValue( current_ou, '_trueRoot' ) == 'true' ) this.required = false;
+                                                                                       else this.required = true;
+                                                                               </script>
+                                                                       </div>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>OPAC Visible</th>
+                                                               <td>
+                                                                       <input
+                                                                         id="editor_pane_opac_visible"
+                                                                         jsId="editor_pane_opac_visible"
+                                                                         type="checkbox"
+                                                                         dojoType="dijit.form.CheckBox"
+                                                                         onChange='if (current_ou) ou_list_store.setValue( current_ou, "opac_visible", this.checked ? "t" : "f" );'
+                                                                       />
+                                                               </td>
+                                                       </tr>
+                                               </table>
+       
+                                               <div dojoType="dijit.layout.ContentPane" orientation="horizontal" style="margin-bottom: 20px;">
+       
+                                                       <button jsId="save_ou_button" dojoType="dijit.form.Button" label="Save" onClick="save_org()">
+                                                               <script type="dojo/connect" event="startup">
+                                                                       this.disabled = true;
+                                                               </script>
+                                                       </button>
+       
+                                                       <button jsId="delete_ou_button" dojoType="dijit.form.Button" label="Delete">
+                                                               <script type="dojo/connect" event="startup">
+                                                                       this.disabled = true;
+                                                               </script>
+                                                               <script type="dojo/connect" event="onClick">
+       
+                                                                       var old_name = ou_list_store.getValue( current_ou, 'name' );
+
+                                                                       if (ou_list_store.getValue( current_ou, '_trueRoot' ) == 'true') {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Cannot delete' + ou_list_store.getValue( current_ou, 'name' ) + ', you need at least one.' );
+                                                                               return false;
+                                                                       }
+
+                                                                       if ( current_ou.children ) {
+                                                                               var kids = current_ou.children;
+                                                                               if (!dojo.isArray(kids)) kids = [kids];
+       
+                                                                               var existing_kids = dojo.filter(
+                                                                                       kids,
+                                                                                       function(kid){ return kid.isdeleted[0] != 1 }
+                                                                               );
+                                                                               if ( existing_kids.length > 0) {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Cannot delete' + ou_list_store.getValue( current_ou, 'name' ) + ', ' + existing_kids.length + ' subordinates still exist.' );
+                                                                                       return;
+                                                                               }
+                                                                       }
+       
+                                                                       if ( confirm('Are you sure you want to delete ' + current_ou.name + '?')) {
+                                                                               ou_list_store.setValue( current_ou, 'isdeleted', 1 );
+       
+                                                                               var modified_ou = new aou().fromStoreItem( current_ou );
+                                                                               modified_ou.isdeleted( 1 );
+       
+                                                                               pCRUD.request({
+                                                                                       method : 'open-ils.permacrud.delete.aou',
+                                                                                       timeout : 10,
+                                                                                       params : [ ses, modified_ou ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.editor_pane.red.play();
+                                                                                               status_update( 'Problem deleting ' + old_name );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+       
+                                                                                                       ou_list_store.fetch({
+                                                                                                               query : { id : ou_list_store.getValue( current_ou, 'id' ) },
+                                                                                                               queryOptions : { deep : true },
+                                                                                                               onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
+                                                                                                               scope : ou_list_store
+                                                                                                       });
+       
+                                                                                                       current_ou = null;
+       
+                                                                                                       new_kid_button.disabled = true;
+                                                                                                       save_ou_button.disabled = true;
+                                                                                                       delete_ou_button.disabled = true;
+                       
+                                                                                                       var main_settings_fields = [ 'name', 'shortname', 'email', 'phone', 'ou_type', 'parent_ou' ];
+                                                                                                       for ( var i in main_settings_fields ) {
+                                                                                                               var field = main_settings_fields[i];
+                                                                                                               window["editor_pane_" + field].setValue( '' ); // unset the value
+                                                                                                               window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
+                                                                                                       }
+                       
+                                                                                                       highlighter.editor_pane.green.play();
+                                                                                                       status_update( old_name + ' deleted' );
+                                                                                               } else {
+                                                                                                       highlighter.editor_pane.red.play();
+                                                                                                       status_update( 'Problem deleting ' + old_name );
+                                                                                               }
+                                                                                       }
+                                                                               }).send();
+       
+                                                                       }
+       
+                                                               </script>
+                                                       </button>
+       
+                                               </div>
+       
+                                               <button jsId="new_kid_button" dojoType="dijit.form.Button" label="New Child">
+                                                       <script type="dojo/connect" event="startup">
+                                                               this.disabled = true;
+                                                       </script>
+                                                       <script type="dojo/connect" event="onClick">
+       
+                                                               var new_fm_obj = new aou().fromHash({
+                                                                       isnew                   : 1,
+                                                                       name                    : 'New Branch',
+                                                                       opac_visible    : 'f',
+                                                                       shortname               : ou_list_store.getValue( current_ou, 'shortname' ) + '-NEW' + virgin_ou_id--,
+                                                                       parent_ou               : ou_list_store.getValue( current_ou, 'id' ),
+                                                                       ou_type                 : ou_list_store.getValue( current_ou, 'ou_type' )
+                                                               });
+       
+                                                               var new_obj;
+       
+                                                               pCRUD.request({
+                                                                       method : 'open-ils.permacrud.create.aou',
+                                                                       timeout : 10,
+                                                                       params : [ ses, new_fm_obj ],
+                                                                       onerror : function (r) {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Problem creating child Org Unit' );
+                                                                       },
+                                                                       oncomplete : function (r) {
+                                                                               var res = r.recv();
+                                                                               if ( res && res.content() ) {
+                                                                                       ou_list_store.newItem(
+                                                                                               res.content().toHash(),
+                                                                                               { parent : current_ou, attribute : 'children' }
+                                                                                       );
+                                                                               } else {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Problem creating child Org Unit' );
+                                                                               }
+                                                                       },
+                                                               }).send();
+       
+                                                               highlighter.editor_pane.green.play();
+                                                               highlighter.ou_tree.green.play();
+                                                               status_update( 'New child Organizational Unit created for ' + ou_list_store.getValue( current_ou, 'name' ) );
+       
+                                                       </script>
+                                               </button>
+       
+                                       </div>
+
+                                       <div id="hoo_pane" dojoType="dijit.layout.ContentPane" title="Hours of Operation">
+                                               <table class="tundra" style="margin:10px;">
+                                                       <tr><th/><th>Open time</th><th>Close time</th></tr>
+                                                       <tr><th>Monday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_0_open" onChange="current_ou_hoo.dow_0_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_0_close" onChange="current_ou_hoo.dow_0_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_0_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_0_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                                       <tr><th>Tuesday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_1_open" onChange="current_ou_hoo.dow_1_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_1_close" onChange="current_ou_hoo.dow_1_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_1_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_1_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                                       <tr><th>Wednesday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_2_open" onChange="current_ou_hoo.dow_2_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_2_close" onChange="current_ou_hoo.dow_2_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_2_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_2_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                                       <tr><th>Thursday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_3_open" onChange="current_ou_hoo.dow_3_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_3_close" onChange="current_ou_hoo.dow_3_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_3_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_3_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                                       <tr><th>Friday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_4_open" onChange="current_ou_hoo.dow_4_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_4_close" onChange="current_ou_hoo.dow_4_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_4_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_4_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                                       <tr><th>Saturday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_5_open" onChange="current_ou_hoo.dow_5_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_5_close" onChange="current_ou_hoo.dow_5_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_5_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_5_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                                       <tr><th>Sunday</th>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_6_open" onChange="current_ou_hoo.dow_6_open( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.TimeTextBox" style="width:8em;" jsId="dow_6_close" onChange="current_ou_hoo.dow_6_close( this.getDisplayedValue() );"/></td>
+                                                               <td><span dojoType="dijit.form.Button" label="Closed" onClick="dow_6_open.setValue( new Date('Tue Mar 25 2008 00:00:00') ); dow_6_close.setValue( new Date('Tue Mar 25 2008 00:00:00') );"/></td>
+                                                       </tr>
+                                               </table>
+       
+                                               <button jsId="save_hoo_button" dojoType="dijit.form.Button" label="Save">
+                                                       <script type="dojo/connect" event="onClick">
+       
+                                                               var method_name = 'open-ils.permacrud.update.aouhoo';
+                                                               if (current_ou_hoo.isnew() == 1) method_name = 'open-ils.permacrud.create.aouhoo';
+       
+                                                               pCRUD.request({
+                                                                       method : method_name,
+                                                                       params : [ ses, current_ou_hoo ],
+                                                                       onerror : function (r) {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Problem saving Hours of Operation data for ' + ou_list_store.getValue( current_ou, 'name' ));
+                                                                       },
+                                                                       oncomplete : function (r) {
+                                                                               var res = r.recv();
+                                                                               if ( res && res.content() ) {
+                                                                                       current_ou_hoo.isnew(0);
+                                                                                       highlighter.editor_pane.green.play();
+                                                                                       status_update( 'Hours of Operation updated for ' + ou_list_store.getValue( current_ou, 'name' ) );
+                                                                               } else {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Problem saving Hours of Operation data for ' + ou_list_store.getValue( current_ou, 'name' ));
+                                                                               }
+                                                                       },
+                                                               }).send();
+       
+                                                       </script>
+                                               </button>
+       
+                                       </div>
+       
+                                       <div id="addresses_pane" dojoType="dijit.layout.ContentPane" title="Addresses">
+                                               
+                                               <div id="billing_address_pane" dojoType="dijit.layout.TabContainer" style="margin-top:10px">
+       
+                                                       <script type="dojo/method">
+                                                               window.current_billing_address = null;
+                                                               window.current_mailing_address = null;
+                                                               window.current_holds_address = null;
+                                                               window.current_ill_address = null;
+                                                       </script>
+       
+                                                       <div id="billing_address" dojoType="dijit.layout.ContentPane" title="Physical Address">
+                                                               <table class="tundra" style="margin:10px;">
+                                                                       <tr>
+                                                                               <th>Type</th><td colspan="3"><span jsId="billing_addr_type" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_billing_address.address_type( this.getValue() )"/></td>
+                                                                               <th>Valid</th><td>
+                                                                                       <input
+                                                                                         type="checkbox"
+                                                                                         jsId="billing_addr_valid"
+                                                                                         dojoType="dijit.form.CheckBox"
+                                                                                         value='t'
+                                                                                         onChange='if (current_billing_address) current_billing_address.valid( this.checked ? "t" : "f" );'
+                                                                                       />
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 1</th><td colspan="5"><span jsId="billing_addr_street1" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_billing_address.street1( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 2</th><td colspan="5"><span jsId="billing_addr_street2" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_billing_address.street2( this.getValue() )"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>City</th><td><span jsId="billing_addr_city" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_billing_address.city( this.getValue() )" required="true"/></td>
+                                                                               <th>State</th><td><span jsId="billing_addr_state" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="2" maxSize="2" uppercase="true" onChange="current_billing_address.state( this.getValue() )" required="true"/></td>
+                                                                               <th>Zip</th><td><span jsId="billing_addr_post_code" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="10" maxSize="10" regExp="^\d{5}(?:-\d{4})?$" uppercase="true" onChange="current_billing_address.post_code( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Country</th><td colspan="2"><span jsId="billing_addr_country" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_billing_address.country( this.getValue() )" required="true"/></td>
+                                                                               <th>County</th><td colspan="2"><span jsId="billing_addr_county" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_billing_address.county( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                               </table>
+       
+                                                               <button jsId="save_billing_address" dojoType="dijit.form.Button" label="Save">
+                                                                       <script type="dojo/connect" event="startup">
+                                                                               this.disabled = true;
+                                                                       </script>
+                                                                       <script type="dojo/connect" event="onClick">
+       
+                                                                               var method_name = 'open-ils.permacrud.update.aoa';
+                                                                               if (current_billing_address.isnew() == 1) method_name = 'open-ils.permacrud.create.aoa';
+       
+                                                                               pCRUD.request({
+                                                                                       method : method_name,
+                                                                                       params : [ ses, current_billing_address ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.addresses_pane.red.play();
+                                                                                               status_update( 'Problem saving Physical Address data for ' + ou_list_store.getValue( current_ou, 'name' ) );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+                                                                                                       if (current_billing_address.isnew() == 1) {
+                                                                                                               current_billing_address = res.content();
+                                                                                                               ou_list_store.setValue( current_ou, 'billing_address', current_billing_address.id() );
+                                                                                                               save_org();
+                                                                                                       }
+                                                                                                       current_billing_address.isnew(0);
+                                                                                                       highlighter.addresses_pane.green.play();
+                                                                                                       status_update( 'Changes to the Physical Address of ' + ou_list_store.getValue( current_ou, 'name' ) + ' saved' );
+                                                                                               } else {
+                                                                                                       highlighter.addresses_pane.red.play();
+                                                                                                       status_update( 'Problem saving Physical Address data for ' + ou_list_store.getValue( current_ou, 'name' ) );
+                                                                                               }
+                                                                                       },
+                                                                               }).send();
+       
+                                                                       </script>
+                                                               </button>
+                                                       </div>
+
+                                                       <div id="holds_address" dojoType="dijit.layout.ContentPane" title="Holds Address">
+                                                               <table class="tundra" style="margin:10px;">
+                                                                       <tr>
+                                                                               <th>Type</th><td colspan="3"><span jsId="holds_addr_type" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_holds_address.address_type( this.getValue() )"/></td>
+                                                                               <th>Valid</th><td>
+                                                                                       <input
+                                                                                         type="checkbox"
+                                                                                         jsId="holds_addr_valid"
+                                                                                         dojoType="dijit.form.CheckBox"
+                                                                                         value='t'
+                                                                                         onChange='if (current_holds_address) current_holds_address.valid( this.checked ? "t" : "f" );'
+                                                                                       />
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 1</th><td colspan="5"><span jsId="holds_addr_street1" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_holds_address.street1( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 2</th><td colspan="5"><span jsId="holds_addr_street2" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_holds_address.street2( this.getValue() )"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>City</th><td><span jsId="holds_addr_city" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_holds_address.city( this.getValue() )" required="true"/></td>
+                                                                               <th>State</th><td><span jsId="holds_addr_state" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="2" maxSize="2" uppercase="true" onChange="current_holds_address.state( this.getValue() )" required="true"/></td>
+                                                                               <th>Zip</th><td><span jsId="holds_addr_post_code" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="10" maxSize="10" regExp="^\d{5}(?:-\d{4})?$" uppercase="true" onChange="current_holds_address.post_code( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Country</th><td colspan="2"><span jsId="holds_addr_country" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_holds_address.country( this.getValue() )" required="true"/></td>
+                                                                               <th>County</th><td colspan="2"><span jsId="holds_addr_county" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_holds_address.county( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                               </table>
+       
+                                                               <button jsId="save_holds_address" dojoType="dijit.form.Button" label="Save">
+                                                                       <script type="dojo/connect" event="startup">
+                                                                               this.disabled = true;
+                                                                       </script>
+                                                                       <script type="dojo/connect" event="onClick">
+       
+                                                                               var method_name = 'open-ils.permacrud.update.aoa';
+                                                                               if (current_holds_address.isnew() == 1) method_name = 'open-ils.permacrud.create.aoa';
+       
+                                                                               pCRUD.request({
+                                                                                       method : method_name,
+                                                                                       params : [ ses, current_holds_address ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.addresses_pane.red.play();
+                                                                                               throw 'Problem saving Holds Address data for ' + ou_list_store.getValue( current_ou, 'name' );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+                                                                                                       if (current_holds_address.isnew() == 1) {
+                                                                                                               current_holds_address = res.content();
+                                                                                                               ou_list_store.setValue( current_ou, 'holds_address', current_holds_address.id() );
+                                                                                                               save_org();
+                                                                                                       }
+                                                                                                       current_holds_address.isnew(0);
+                                                                                                       highlighter.addresses_pane.green.play();
+                                                                                                       status_update( 'Changes to the Holds Address of ' + ou_list_store.getValue( current_ou, 'name' ) + ' saved' );
+                                                                                               } else {
+                                                                                                       highlighter.addresses_pane.red.play();
+                                                                                                       throw 'Problem saving Holds Address data for ' + ou_list_store.getValue( current_ou, 'name' );
+                                                                                               }
+                                                                                       },
+                                                                               }).send();
+       
+                                                                       </script>
+                                                               </button>
+                                                       </div>
+
+                                                       <div id="mailing_address" dojoType="dijit.layout.ContentPane" title="Mailing Address">
+                                                               <table class="tundra" style="margin:10px;">
+                                                                       <tr>
+                                                                               <th>Type</th><td colspan="3"><span jsId="mailing_addr_type" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_mailing_address.address_type( this.getValue() )"/></td>
+                                                                               <th>Valid</th><td>
+                                                                                       <input
+                                                                                         type="checkbox"
+                                                                                         jsId="mailing_addr_valid"
+                                                                                         dojoType="dijit.form.CheckBox"
+                                                                                         onChange='if (current_mailing_address) current_mailing_address.valid( this.checked ? "t" : "f" );'
+                                                                                       />
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 1</th><td colspan="5"><span jsId="mailing_addr_street1" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_mailing_address.street1( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 2</th><td colspan="5"><span jsId="mailing_addr_street2" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_mailing_address.street2( this.getValue() )"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>City</th><td><span jsId="mailing_addr_city" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_mailing_address.city( this.getValue() )" required="true"/></td>
+                                                                               <th>State</th><td><span jsId="mailing_addr_state" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="2" maxSize="2" uppercase="true" onChange="current_mailing_address.state( this.getValue() )" required="true"/></td>
+                                                                               <th>Zip</th><td><span jsId="mailing_addr_post_code" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="10" maxSize="10" regExp="^\d{5}(?:-\d{4})?$" uppercase="true" onChange="current_mailing_address.post_code( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Country</th><td colspan="2"><span jsId="mailing_addr_country" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_mailing_address.country( this.getValue() )" required="true"/></td>
+                                                                               <th>County</th><td colspan="2"><span jsId="mailing_addr_county" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_mailing_address.county( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                               </table>
+       
+                                                               <button jsId="save_mailing_address" dojoType="dijit.form.Button" label="Save">
+                                                                       <script type="dojo/connect" event="startup">
+                                                                               this.disabled = true;
+                                                                       </script>
+                                                                       <script type="dojo/connect" event="onClick">
+       
+                                                                               var method_name = 'open-ils.permacrud.update.aoa';
+                                                                               if (current_mailing_address.isnew() == 1) method_name = 'open-ils.permacrud.create.aoa';
+       
+                                                                               pCRUD.request({
+                                                                                       method : method_name,
+                                                                                       params : [ ses, current_mailing_address ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.addresses_pane.red.play();
+                                                                                               throw 'Problem saving Mailing Address data for ' + ou_list_store.getValue( current_ou, 'name' );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+                                                                                                       if (current_mailing_address.isnew() == 1) {
+                                                                                                               current_mailing_address = res.content();
+                                                                                                               ou_list_store.setValue( current_ou, 'mailing_address', current_mailing_address.id() );
+                                                                                                               save_org();
+                                                                                                       }
+                                                                                                       current_mailing_address.isnew(0);
+                                                                                                       highlighter.addresses_pane.green.play();
+                                                                                                       status_update( 'Changes to the Mailing Address of ' + ou_list_store.getValue( current_ou, 'name' ) + ' saved' );
+                                                                                               } else {
+                                                                                                       highlighter.addresses_pane.red.play();
+                                                                                                       throw 'Problem saving Mailing Address data for ' + ou_list_store.getValue( current_ou, 'name' );
+                                                                                               }
+                                                                                       },
+                                                                               }).send();
+       
+                                                                       </script>
+                                                               </button>
+                                                       </div>
+
+                                                       <div id="ill_address" dojoType="dijit.layout.ContentPane" title="ILL Address">
+                                                               <table class="tundra" style="margin:10px;">
+                                                                       <tr>
+                                                                               <th>Type</th><td colspan="3"><span jsId="ill_addr_type" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_ill_address.address_type( this.getValue() )"/></td>
+                                                                               <th>Valid</th><td>
+                                                                                       <input
+                                                                                         type="checkbox"
+                                                                                         jsId="ill_addr_valid"
+                                                                                         dojoType="dijit.form.CheckBox"
+                                                                                         onChange='if (current_ill_address) current_ill_address.valid( this.checked ? "t" : "f" );'
+                                                                                       />
+                                                                               </td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 1</th><td colspan="5"><span jsId="ill_addr_street1" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_ill_address.street1( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Street 2</th><td colspan="5"><span jsId="ill_addr_street2" style="width:100%;" dojoType="dijit.form.TextBox" onChange="current_ill_address.street2( this.getValue() )"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>City</th><td><span jsId="ill_addr_city" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_ill_address.city( this.getValue() )" required="true"/></td>
+                                                                               <th>State</th><td><span jsId="ill_addr_state" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="2" maxSize="2" uppercase="true" onChange="current_ill_address.state( this.getValue() )" required="true"/></td>
+                                                                               <th>Zip</th><td><span jsId="ill_addr_post_code" style="width:100%;" dojoType="dijit.form.ValidationTextBox" size="10" maxSize="10" regExp="^\d{5}(?:-\d{4})?$" uppercase="true" onChange="current_ill_address.post_code( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                                       <tr>
+                                                                               <th>Country</th><td colspan="2"><span jsId="ill_addr_country" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_ill_address.country( this.getValue() )" required="true"/></td>
+                                                                               <th>County</th><td colspan="2"><span jsId="ill_addr_county" style="width:100%;" dojoType="dijit.form.ValidationTextBox" onChange="current_ill_address.county( this.getValue() )" required="true"/></td>
+                                                                       </tr>
+                                                               </table>
+       
+                                                               <button jsId="save_ill_address" dojoType="dijit.form.Button" label="Save">
+                                                                       <script type="dojo/connect" event="startup">
+                                                                               this.disabled = true;
+                                                                       </script>
+                                                                       <script type="dojo/connect" event="onClick">
+       
+                                                                               var method_name = 'open-ils.permacrud.update.aoa';
+                                                                               if (current_ill_address.isnew() == 1) method_name = 'open-ils.permacrud.create.aoa';
+       
+                                                                               pCRUD.request({
+                                                                                       method : method_name,
+                                                                                       params : [ ses, current_ill_address ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.addresses_pane.red.play();
+                                                                                               throw 'Problem saving Physical Address data for ' + ou_list_store.getValue( current_ou, 'name' );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+                                                                                                       if (current_ill_address.isnew() == 1) {
+                                                                                                               current_ill_address = res.content();
+                                                                                                               ou_list_store.setValue( current_ou, 'ill_address', current_ill_address.id() );
+                                                                                                               save_org();
+                                                                                                       }
+                                                                                                       current_ill_address.isnew(0);
+                                                                                                       highlighter.addresses_pane.green.play();
+                                                                                                       status_update( 'Changes to the ILL Address of ' + ou_list_store.getValue( current_ou, 'name' ) + ' saved' );
+                                                                                               } else {
+                                                                                                       highlighter.addresses_pane.red.play();
+                                                                                                       throw 'Problem saving Physical Address data for ' + ou_list_store.getValue( current_ou, 'name' );
+                                                                                               }
+                                                                                       },
+                                                                               }).send();
+       
+                                                                       </script>
+                                                               </button>
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+
+               <div id="status_bar"><span style="font-weight: bold; margin: 5px; margin-right: 10px;">Now editing:</span><span id="current_ou_name"></span></div>
+       </body>
+</html>
diff --git a/Open-ILS/web/conify/global/actor/org_unit.js b/Open-ILS/web/conify/global/actor/org_unit.js
new file mode 100644 (file)
index 0000000..fe5c257
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+# ---------------------------------------------------------------------------
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# ---------------------------------------------------------------------------
+*/
+
+dojo.require('fieldmapper.dojoData');
+dojo.require('dojo.parser');
+dojo.require('dojo.data.ItemFileWriteStore');
+dojo.require('dojo.date.stamp');
+dojo.require('dijit.form.TextBox');
+dojo.require('dijit.form.TimeTextBox');
+dojo.require('dijit.form.ValidationTextBox');
+dojo.require('dijit.form.CheckBox');
+dojo.require('dijit.form.FilteringSelect');
+dojo.require('dijit.Tree');
+dojo.require('dijit.layout.ContentPane');
+dojo.require('dijit.layout.TabContainer');
+dojo.require('dijit.layout.LayoutContainer');
+dojo.require('dijit.layout.SplitContainer');
+dojo.require('dojox.widget.Toaster');
+dojo.require('dojox.fx');
+
+// some handy globals
+var cgi = new CGI();
+var cookieManager = new HTTP.Cookies();
+var ses = cookieManager.read('ses') || cgi.param('ses');
+var pCRUD = new OpenSRF.ClientSession('open-ils.permacrud');
+
+var current_ou, current_ou_hoo;
+var virgin_ou_id = -1;
+
+//var ou_type_store = new dojo.data.ItemFileWriteStore({ data : aout.toStoreData( globalOrgTypes ) });
+
+var highlighter = {};
+
+function status_update (markup) {
+       if (parent !== window && parent.status_update) parent.status_update( markup );
+}
+
+function save_org () {
+       var modified_ou = new aou().fromStoreItem( current_ou );
+       modified_ou.ischanged( 1 );
+
+       new_kid_button.disabled = false;
+       save_ou_button.disabled = false;
+       delete_ou_button.disabled = false;
+
+       pCRUD.request({
+               method : 'open-ils.permacrud.update.aou',
+               timeout : 10,
+               params : [ ses, modified_ou ],
+               onerror : function (r) {
+                       highlighter.editor_pane.red.play();
+                       status_update( 'Problem saving data for ' + ou_list_store.getValue( current_ou, 'name' ) );
+               },
+               oncomplete : function (r) {
+                       var res = r.recv();
+                       if ( res && res.content() ) {
+                               ou_list_store.setValue( current_ou, 'ischanged', 0 );
+                               highlighter.editor_pane.green.play();
+                               status_update( 'Saved changes to ' + ou_list_store.getValue( current_ou, 'name' ) );
+                       } else {
+                               highlighter.editor_pane.red.play();
+                               status_update( 'Problem saving data for ' + ou_list_store.getValue( current_ou, 'name' ) );
+                       }
+               },
+       }).send();
+}
+       
+function hoo_load () {
+       // empty result not coming through ...
+       current_ou_hoo = new aouhoo().fromHash({id:ou_list_store.getValue( current_ou, 'id' )});
+       current_ou_hoo.isnew(1);
+
+       pCRUD.request({
+               method : 'open-ils.permacrud.retrieve.aouhoo',
+               params : [ ses, ou_list_store.getValue( current_ou, 'id' ) ],
+               onerror : function (r) { throw 'Problem fetching hours of operation for ' + ou_list_store.getValue( current_ou, 'name' );},
+               oncomplete : function (r) {
+                       current_ou_hoo = null;
+
+                       var res = r.recv();
+                       if (res) {
+                               if (res.content()) current_ou_hoo = res.content();
+                       }
+
+                       if (!current_ou_hoo) {
+                               current_ou_hoo = new aouhoo().fromHash({id:ou_list_store.getValue( current_ou, 'id' )});
+                               current_ou_hoo.isnew(1);
+                               for (var i = 0; i < 7; i++) {
+                                       current_ou_hoo['dow_' + i + '_open']('09:00:00');
+                                       current_ou_hoo['dow_' + i + '_close']('17:00:00');
+                               }
+                       }
+
+                       for (var i = 0; i < 7; i++) {
+                               window['dow_' + i + '_open'].setValue(
+                                       dojo.date.stamp.fromISOString( 'T' + current_ou_hoo['dow_' + i + '_open']() )
+                               );
+                               window['dow_' + i + '_close'].setValue(
+                                       dojo.date.stamp.fromISOString( 'T' + current_ou_hoo['dow_' + i + '_close']() )
+                               );
+                       }
+
+                       highlighter.hoo_pane.green.play();
+               }
+       }).send();
+
+}
+
+function addr_load () {
+       // empty result not coming through ...
+
+       save_ill_address.disabled = false;
+       save_holds_address.disabled = false;
+       save_mailing_address.disabled = false;
+       save_billing_address.disabled = false;
+
+       if (ou_list_store.getValue( current_ou, 'billing_address' )) {
+               pCRUD.request({
+                       method : 'open-ils.permacrud.retrieve.aoa',
+                       params : [ ses, ou_list_store.getValue( current_ou, 'billing_address' ) ],
+                       onerror : function (r) { throw 'Problem fetching Physical Address for ' + ou_list_store.getValue( current_ou, 'name' );},
+                       oncomplete : function (r) {
+                               current_billing_address = null;
+
+                               var res = r.recv();
+                               if (res) {
+                                       if (res.content()) current_billing_address = res.content();
+                               }
+
+                               if (!current_billing_address) {
+                                       current_billing_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+                                       current_billing_address.isnew(1);
+                               }
+
+                               set_addr_inputs('billing');
+                               highlighter.addresses_pane.green.play();
+                       }
+               }).send();
+       } else {
+               current_billing_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+               current_billing_address.isnew(1);
+               set_addr_inputs('billing');
+       }
+
+       if (ou_list_store.getValue( current_ou, 'mailing_address' )) {
+               pCRUD.request({
+                       method : 'open-ils.permacrud.retrieve.aoa',
+                       params : [ ses, ou_list_store.getValue( current_ou, 'mailing_address' ) ],
+                       onerror : function (r) { throw 'Problem fetching Physical Address for ' + ou_list_store.getValue( current_ou, 'name' );},
+                       oncomplete : function (r) {
+                               current_mailing_address = null;
+
+                               var res = r.recv();
+                               if (res) {
+                                       if (res.content()) current_mailing_address = res.content();
+                               }
+
+                               if (!current_mailing_address) {
+                                       current_mailing_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+                                       current_mailing_address.isnew(1);
+                               }
+
+                               set_addr_inputs('mailing');
+                               highlighter.addresses_pane.green.play();
+                       }
+               }).send();
+       } else {
+               current_mailing_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+               current_mailing_address.isnew(1);
+               set_addr_inputs('mailing');
+       }
+
+       if (ou_list_store.getValue( current_ou, 'holds_address' )) {
+               pCRUD.request({
+                       method : 'open-ils.permacrud.retrieve.aoa',
+                       params : [ ses, ou_list_store.getValue( current_ou, 'holds_address' ) ],
+                       onerror : function (r) { throw 'Problem fetching Physical Address for ' + ou_list_store.getValue( current_ou, 'name' );},
+                       oncomplete : function (r) {
+                               current_holds_address = null;
+
+                               var res = r.recv();
+                               if (res) {
+                                       if (res.content()) current_holds_address = res.content();
+                               }
+
+                               if (!current_holds_address) {
+                                       current_holds_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+                                       current_holds_address.isnew(1);
+                               }
+
+                               set_addr_inputs('holds');
+                               highlighter.addresses_pane.green.play();
+                       }
+               }).send();
+       } else {
+               current_holds_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+               current_holds_address.isnew(1);
+               set_addr_inputs('holds');
+       }
+
+       if (ou_list_store.getValue( current_ou, 'ill_address' )) {
+               pCRUD.request({
+                       method : 'open-ils.permacrud.retrieve.aoa',
+                       params : [ ses, ou_list_store.getValue( current_ou, 'ill_address' ) ],
+                       onerror : function (r) { throw 'Problem fetching Physical Address for ' + ou_list_store.getValue( current_ou, 'name' );},
+                       oncomplete : function (r) {
+                               current_ill_address = null;
+
+                               var res = r.recv();
+                               if (res) {
+                                       if (res.content()) current_ill_address = res.content();
+                               }
+
+                               if (!current_ill_address) {
+                                       current_ill_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+                                       current_ill_address.isnew(1);
+                               }
+
+                               set_addr_inputs('ill');
+                               highlighter.addresses_pane.green.play();
+                       }
+               }).send();
+       } else {
+               current_ill_address = new aoa().fromHash({org_unit:ou_list_store.getValue( current_ou, 'id' )});
+               current_ill_address.isnew(1);
+               set_addr_inputs('ill');
+       }
+
+}
+
+function set_addr_inputs (type) {
+       window[type + '_addr_valid'].setChecked( window['current_' + type + '_address'].valid() == 't' ? true : false );
+       window[type + '_addr_type'].setValue( window['current_' + type + '_address'].address_type() || '' );
+       window[type + '_addr_street1'].setValue( window['current_' + type + '_address'].street1() || '' );
+       window[type + '_addr_street2'].setValue( window['current_' + type + '_address'].street2() || '' );
+       window[type + '_addr_city'].setValue( window['current_' + type + '_address'].city() || '' );
+       window[type + '_addr_county'].setValue( window['current_' + type + '_address'].county() || '' );
+       window[type + '_addr_country'].setValue( window['current_' + type + '_address'].country() || '' );
+       window[type + '_addr_state'].setValue( window['current_' + type + '_address'].state() || '' );
+       window[type + '_addr_post_code'].setValue( window['current_' + type + '_address'].post_code() || '' );
+}
+
diff --git a/Open-ILS/web/conify/global/actor/org_unit_type.html b/Open-ILS/web/conify/global/actor/org_unit_type.html
new file mode 100644 (file)
index 0000000..0818da7
--- /dev/null
@@ -0,0 +1,412 @@
+<!--
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+       <head>
+               <title>Confiy :: Global :: Actor :: Org Unit Types</title>
+
+               <style type="text/css">
+                       @import url("/js/dojo/dojo/resources/dojo.css");
+                       @import url("/js/dojo/dijit/themes/tundra/tundra.css");
+                       @import url("/js/dojo/dojox/widget/Toaster/Toaster.css");
+               </style>
+
+               <style>
+                       html, body
+                       {
+                               height: 100%;
+                               width: 100%;
+                               margin: 0px 0px 0px 0px;
+                               padding: 0px 0px 0px 0px;
+                               overflow: hidden;
+                       }
+
+                       th
+                       {
+                               text-align: right;
+                               font-weight: bold;
+                               padding-left: 20px;
+                               padding-right: 5px;
+                       }
+               </style>
+
+               <!-- The OpenSRF API writ JS -->
+               <script language='javascript' src='/opac/common/js/utils.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/Cookies.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/CGI.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/JSON_v1.js' type='text/javascript'></script>
+
+               <!-- Fieldmapper objects -->
+               <script language='javascript' src='/opac/common/js/fmall.js' type='text/javascript'></script>
+
+               <!-- Dojo goodness -->
+               <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+               <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
+
+               <script type="text/javascript" src="org_unit_type.js"></script>
+
+       </head>
+
+       <body class="tundra" id='pagebody'>
+
+               <div dojoType="dijit.layout.SplitContainer" orientation="horizontal" style="height: 100%">
+
+                       <div dojoType="dijit.layout.ContentPane" sizeShare="100">
+                               <script type="dojo/method">
+                                       window.dirtyStore = [];
+
+                    pCRUD.request({
+                        method : 'open-ils.permacrud.search.aout.atomic',
+                        timeout : 10,
+                        params : [ ses, { id : { "!=" : null } }, { order_by : { aout : 'name' } } ],
+                        onerror : function (r) { status_update('Problem fetching types') },
+                        oncomplete : function (r) {
+                            ou_type_store = new dojo.data.ItemFileWriteStore({ data : aout.toStoreData( r.recv().content() ) });
+                            ou_type_store.onSet = function (item, attr, o, n) {
+                                if (attr == 'ischanged') return;
+                                if (n == o) return;
+                                this.setValue( item, 'ischanged', 1);
+                            };
+                            dojo.addOnUnload( function (event) {
+
+                                ou_type_store.fetch({
+                                    query : { ischanged : 1 },
+                                    queryOptions : { deep : true },
+                                    onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
+                                    scope : ou_type_store
+                                });
+
+                                if (dirtyStore.length > 0) {
+                                    var confirmation = confirm(
+                                        'There are unsaved modified Organization Types!  '+
+                                        'OK to save these changes, Cancel to abandon them.'
+                                    );
+
+                                    if (confirmation) {
+                                        for (var i in window.dirtyStore) {
+                                            window.current_type = window.dirtyStore[i];
+                                            save_type(true);
+                                        }
+                                    }
+                                }
+
+                            });
+                        }
+                    }).send();
+
+                               </script>
+                               <div
+                                 id="type_tree"
+                                 label="Organization Types"
+                                 query="{'_top':'true'}"
+                                 dojoType="dijit.Tree"
+                                 store="ou_type_store"
+                                 minSize="200"
+                                 jsId="type_tree"
+                               >
+
+                                       <script type="dojo/method" event="onClick" args="item,node">
+
+                                               right_pane_toggler.show();
+                                               current_type = item;
+
+                                               highlighter.editor_pane.green.play();
+                                               status_update( 'Now editing ' + this.store.getValue( item, 'name' ) );
+
+                                               new_kid_button.disabled = false;
+                                               save_out_button.disabled = false;
+                                               delete_out_button.disabled = false;
+
+                                               var main_settings_fields = [ 'name', 'opac_label'];
+                                               for ( var i in main_settings_fields ) {
+                                                       var field = main_settings_fields[i];
+                                                       var value = this.store.getValue( current_type, field );
+
+                                                       if (!value) {
+                                                               window["editor_pane_" + field].setValue( '' ); // unset the value
+                                                               window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
+                                                       } else window["editor_pane_" + field].setValue( value );
+                                               }
+
+                                               if ( this.store.getValue( current_type, '_trueRoot' ) == 'true' ) {
+                                                       editor_pane_parent.disabled = true;
+                                                       editor_pane_parent.setValue(null);
+                                                       editor_pane_parent.setDisplayedValue('');
+                                                       editor_pane_parent.validate(false);
+                                               } else {
+                                                       editor_pane_parent.disabled = false;
+                                                       editor_pane_parent.validate(true);
+                                                       editor_pane_parent.setValue( this.store.getValue( current_type, 'parent' ) );
+                                               }
+
+                                               editor_pane_can_have_vols.setChecked( this.store.getValue( current_type, 'can_have_vols' ) == 't' ? true : false );
+                                               editor_pane_can_have_users.setChecked( this.store.getValue( current_type, 'can_have_users' ) == 't' ? true : false );
+
+                                       </script>
+
+                                       <script type="dojo/method" event="getLabel" args="item,pI">
+                                               var label = this.store.getValue(item,'name');
+                                               if (this.store.getValue(item,'ischanged') == 1) label = '* ' + label;
+                                               return label;
+                                       </script>
+
+                               </div>
+                       </div>
+
+                       <div id="right_pane" dojoType="dijit.layout.ContentPane"  sizeShare="200">
+                               <script type="dojo/method">
+                                       window.right_pane_toggler = new dojo.fx.Toggler({ node: 'right_pane'});
+                                       window.right_pane_toggler.hide();
+                               </script>
+
+                                       <div id="editor_pane" dojoType="dijit.layout.ContentPane">
+                                               <script type="dojo/method">
+                                                       highlighter.type_tree = {};
+                                                       highlighter.editor_pane = {};
+                                                       highlighter.type_tree.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'type_tree', duration : 500 } );
+                                                       highlighter.type_tree.red = dojox.fx.highlight( { color : '#FF2018', node : 'type_tree', duration : 500 } );
+                                                       highlighter.editor_pane.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'editor_pane', duration : 500 } );
+                                                       highlighter.editor_pane.red = dojox.fx.highlight( { color : '#FF2018', node : 'editor_pane', duration : 500 } );
+                                               </script>
+       
+                                               <table class="tundra" style="margin:10px;">
+                                                       <tr>
+                                                               <th>Type Name</th>
+                                                               <td>
+                                                                       <span id="editor_pane_name" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_name" regExp=".+" required="true">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_type) {
+                                                                                               ou_type_store.setValue( current_type, "name", this.getValue() );
+                                                                                       }
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>OPAC Label</th>
+                                                               <td>
+                                                                       <span id="editor_pane_opac_label" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_opac_label" regExp=".+" required="true">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_type) {
+                                                                                               ou_type_store.setValue( current_type, "opac_label", this.getValue() );
+                                                                                       }
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Parent Type</th>
+                                                               <td>
+                                                                       <div
+                                                                         id="editor_pane_parent"
+                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                         jsId="editor_pane_parent"
+                                                                         store="ou_type_store"
+                                                                         searchAttr="name"
+                                                                         ignoreCase="true"
+                                                                         required="true"
+                                                                       >
+                                                                               <script type="dojo/method" event="onChange" args=>
+                                                                                       if (current_type && this.getValue()) {
+                                                                                               if ( this.store.getValue( current_type, 'parent' ) == this.getValue() ) return;
+
+                                                                                               this.store.setValue( current_type, "parent", this.getValue() );
+                                                                                               this.store.fetch({
+                                                                                                       query : { "parent" : this.getValue() },
+                                                                                                       onItem: function (parent_item) {
+                                                                                                               this.setValue( current_type, 'depth', 1 + parseInt(this.getValue( parent_item, 'depth' ) ));
+                                                                                                       },
+                                                                                                       scope : ou_type_store
+                                                                                               });
+                                                                                       }
+                                                                               </script>
+                                                                       </div>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Can have Volumes/Copies</th>
+                                                               <td>
+                                                                       <input
+                                                                         id="editor_pane_can_have_vols"
+                                                                         jsId="editor_pane_can_have_vols"
+                                                                         type="checkbox"
+                                                                         dojoType="dijit.form.CheckBox"
+                                                                         onChange='if (current_type) ou_type_store.setValue( current_type, "can_have_vols", this.checked ? "t" : "f" );'
+                                                                       />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Can have Users</th>
+                                                               <td>
+                                                                       <input
+                                                                         id="editor_pane_can_have_users"
+                                                                         jsId="editor_pane_can_have_users"
+                                                                         type="checkbox"
+                                                                         dojoType="dijit.form.CheckBox"
+                                                                         onChange='if (current_type) ou_type_store.setValue( current_type, "can_have_users", this.checked ? "t" : "f" );'
+                                                                       />
+                                                               </td>
+                                                       </tr>
+                                               </table>
+       
+                                               <div dojoType="dijit.layout.ContentPane" orientation="horizontal" style="margin-bottom: 20px;">
+       
+                                                       <button jsId="save_out_button" dojoType="dijit.form.Button" label="Save" onClick="save_type()">
+                                                               <script type="dojo/connect" event="startup">
+                                                                       this.disabled = true;
+                                                               </script>
+                                                       </button>
+       
+                                                       <button jsId="delete_out_button" dojoType="dijit.form.Button" label="Delete">
+                                                               <script type="dojo/connect" event="startup">
+                                                                       this.disabled = true;
+                                                               </script>
+                                                               <script type="dojo/connect" event="onClick">
+       
+                                                                       if (ou_type_store.getValue( current_type, '_trueRoot' ) == 'true') {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Cannot delete' + ou_type_store.getValue( current_type, 'name' ) + ', you need at least one.' );
+                                                                               return false;
+                                                                       }
+
+                                                                       if ( current_type.children ) {
+                                                                               var kids = current_type.children;
+                                                                               if (!dojo.isArray(kids)) kids = [kids];
+       
+                                                                               var existing_kids = dojo.filter(
+                                                                                       kids,
+                                                                                       function(kid){ return kid.isdeleted[0] != 1 }
+                                                                               );
+                                                                               if ( existing_kids.length > 0) {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Cannot delete' + ou_type_store.getValue( current_type, 'name' ) + ', ' + existing_kids.length + ' subordinates still exist.' );
+                                                                                       return;
+                                                                               }
+                                                                       }
+       
+                                                                       if ( confirm('Are you sure you want to delete ' + current_type.name + '?')) {
+                                                                               ou_type_store.setValue( current_type, 'isdeleted', 1 );
+       
+                                                                               var modified_aout = new aout().fromStoreItem( current_type );
+                                                                               modified_aout.isdeleted( 1 );
+       
+                                                                               pCRUD.request({
+                                                                                       method : 'open-ils.permacrud.delete.aout',
+                                                                                       timeout : 10,
+                                                                                       params : [ ses, modified_aout ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.editor_pane.red.play();
+                                                                                               status_update( 'Problem deleting ' + ou_type_store.getValue( current_type, 'name' ) );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+       
+                                                                                                       var old_name = ou_type_store.getValue( current_type, 'name' );
+
+                                                                                                       ou_type_store.fetch({
+                                                                                                               query : { id : ou_type_store.getValue( current_type, 'id' ) },
+                                                                                                               queryOptions : { deep : true },
+                                                                                                               onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
+                                                                                                               scope : ou_type_store
+                                                                                                       });
+       
+                                                                                                       current_type = null;
+       
+                                                                                                       new_kid_button.disabled = true;
+                                                                                                       save_out_button.disabled = true;
+                                                                                                       delete_out_button.disabled = true;
+                       
+                                                                                                       var main_settings_fields = [ 'name', 'opac_label' ];
+                                                                                                       for ( var i in main_settings_fields ) {
+                                                                                                               var field = main_settings_fields[i];
+                                                                                                               window["editor_pane_" + field].setValue( '' ); // unset the value
+                                                                                                               window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
+                                                                                                       }
+
+                                                                                                       window["editor_pane_can_have_vols"].setChecked( false ); // unset the value
+                                                                                                       window["editor_pane_can_have_users"].setChecked( false ); // unset the value
+                       
+                                                                                                       highlighter.editor_pane.green.play();
+                                                                                                       status_update( old_name + ' deleted' );
+                                                                                               } else {
+                                                                                                       highlighter.editor_pane.red.play();
+                                                                                                       status_update( 'Problem deleting ' + old_name );
+                                                                                               }
+                                                                                       }
+                                                                               }).send();
+       
+                                                                       }
+       
+                                                               </script>
+                                                       </button>
+       
+                                               </div>
+       
+                                               <button jsId="new_kid_button" dojoType="dijit.form.Button" label="New Child">
+                                                       <script type="dojo/connect" event="startup">
+                                                               this.disabled = true;
+                                                       </script>
+                                                       <script type="dojo/connect" event="onClick">
+       
+                                                               var new_fm_obj = new aout().fromHash({
+                                                                       isnew                   : 1,
+                                                                       name                    : 'New Type',
+                                                                       can_have_vols   : 'f',
+                                                                       can_have_users  : 'f',
+                                                                       depth                   : 1 + parseInt(ou_type_store.getValue( current_type, 'depth' )),
+                                                                       opac_label              : ou_type_store.getValue( current_type, 'opac_label' ) + ' child' + virgin_out_id--,
+                                                                       parent                  : ou_type_store.getValue( current_type, 'id' )
+                                                               });
+       
+                                                               var err = false;
+                                                               pCRUD.request({
+                                                                       method : 'open-ils.permacrud.create.aout',
+                                                                       timeout : 10,
+                                                                       params : [ ses, new_fm_obj ],
+                                                                       onerror : function (r) {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Problem calling method to create child Org Type' );
+                                                                               err = true;
+                                                                       },
+                                                                       oncomplete : function (r) {
+                                                                               var res = r.recv();
+                                                                               if ( res && res.content() ) {
+                                                                                       ou_type_store.newItem(
+                                                                                               res.content().toHash(),
+                                                                                               { parent : current_type, attribute : 'children' }
+                                                                                       );
+                                                                               } else {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Problem creating child Org Type' );
+                                                                                       err = true;
+                                                                               }
+                                                                       },
+                                                               }).send();
+       
+                                                               if (!err) {
+                                                                       highlighter.editor_pane.green.play();
+                                                                       highlighter.type_tree.green.play();
+                                                                       status_update( 'New child Organization Type created for ' + ou_type_store.getValue( current_type, 'name' ) );
+                                                               }
+       
+                                                       </script>
+                                               </button>
+       
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+       </body>
+</html>
diff --git a/Open-ILS/web/conify/global/actor/org_unit_type.js b/Open-ILS/web/conify/global/actor/org_unit_type.js
new file mode 100644 (file)
index 0000000..e297c72
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+# ---------------------------------------------------------------------------
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# ---------------------------------------------------------------------------
+*/
+
+dojo.require('fieldmapper.dojoData');
+dojo.require('dojo.parser');
+dojo.require('dojo.data.ItemFileWriteStore');
+dojo.require('dojo.date.stamp');
+dojo.require('dijit.form.NumberSpinner');
+dojo.require('dijit.form.TextBox');
+dojo.require('dijit.form.TimeTextBox');
+dojo.require('dijit.form.ValidationTextBox');
+dojo.require('dijit.form.CheckBox');
+dojo.require('dijit.form.FilteringSelect');
+dojo.require('dijit.Tree');
+dojo.require('dijit.layout.ContentPane');
+dojo.require('dijit.layout.TabContainer');
+dojo.require('dijit.layout.LayoutContainer');
+dojo.require('dijit.layout.SplitContainer');
+dojo.require('dojox.widget.Toaster');
+dojo.require('dojox.fx');
+
+// some handy globals
+var cgi = new CGI();
+var cookieManager = new HTTP.Cookies();
+var ses = cookieManager.read('ses') || cgi.param('ses');
+var pCRUD = new OpenSRF.ClientSession('open-ils.permacrud');
+
+var current_type;
+var virgin_out_id = -1;
+
+var highlighter = {};
+
+function status_update (markup) {
+       if (parent !== window && parent.status_update) parent.status_update( markup );
+}
+
+function save_type () {
+
+       var modified_aout = new aout().fromStoreItem( current_type );
+       modified_aout.ischanged( 1 );
+
+       new_kid_button.disabled = false;
+       save_out_button.disabled = false;
+       delete_out_button.disabled = false;
+
+       pCRUD.request({
+               method : 'open-ils.permacrud.update.aout',
+               timeout : 10,
+               params : [ ses, modified_aout ],
+               onerror : function (r) {
+                       highlighter.editor_pane.red.play();
+                       status_update( 'Problem saving data for ' + ou_type_store.getValue( current_type, 'name' ) );
+               },
+               oncomplete : function (r) {
+                       var res = r.recv();
+                       if ( res && res.content() ) {
+                               ou_type_store.setValue( current_type, 'ischanged', 0 );
+                               highlighter.editor_pane.green.play();
+                               status_update( 'Saved changes to ' + ou_type_store.getValue( current_type, 'name' ) );
+                       } else {
+                               highlighter.editor_pane.red.play();
+                               status_update( 'Problem saving data for ' + ou_type_store.getValue( current_type, 'name' ) );
+                       }
+               },
+       }).send();
+}
+
diff --git a/Open-ILS/web/conify/global/admin.html b/Open-ILS/web/conify/global/admin.html
new file mode 100644 (file)
index 0000000..8a4ff3f
--- /dev/null
@@ -0,0 +1,77 @@
+<!--
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+       <head>
+               <title>Conify :: Global :: Admin</title>
+
+        <style type="text/css">
+            @import url("/js/dojo/dojo/resources/dojo.css");
+            @import url("/js/dojo/dijit/themes/tundra/tundra.css");
+            @import url("/js/dojo/dojox/widget/Toaster/Toaster.css");
+        </style>
+
+        <style>
+            html, body
+            {
+                height: 100%;
+                width: 100%;
+                margin: 0px 0px 0px 0px;
+                padding: 0px 0px 0px 0px;
+                overflow: hidden;
+            }
+        </style>
+
+        <!-- Dojo goodness -->
+        <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+        <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
+
+        <script type="text/javascript">
+            dojo.require('dojo.parser');
+            dojo.require('dijit.form.Button');
+            dojo.require('dijit.layout.ContentPane');
+            dojo.require('dijit.layout.LayoutContainer');
+
+            function status_update (markup) {
+                dojo.byId('status_text').innerHTML = markup;
+            }
+
+        </script>
+
+       </head>
+       <body class="tundra" id='pagebody'>
+               <div dojoType="dijit.layout.LayoutContainer" style="height: 100%; width: 100%; margin: 0; padding: 0; border: 0;">
+                       <div id="top_pane" jsId="top_pane" dojoType="dijit.layout.ContentPane" layoutAlign="top" orientation="horizontal" style="margin: 4px; width: 100%; text-align: middle;" title="Controls">
+                               <img src="/opac/images/small_logo.jpg"/>
+                               <span style="font-size: large; padding-left: 20px;"> Configure your ILS </span>
+                       </div>
+                       <div id="left_pane" jsId="left_pane" dojoType="dijit.layout.ContentPane" layoutAlign="left" orientation="vertical" style="height: 90%; margin: 4px;" label="Controls">
+                               <ul style="margin-left: -10px;">
+                                       <li><a href="" onclick="dojo.byId('action_iframe').src = 'actor/org_unit_type.html'; return false;">Organization Types</a></li>
+                                       <li><a href="" onclick="dojo.byId('action_iframe').src = 'actor/org_unit.html'; return false;">Organizational Units</a></li>
+                                       <li><a href="" onclick="dojo.byId('action_iframe').src = 'permission/grp_tree.html'; return false;">Permission Groups</a></li>
+                                       <li><a href="" onclick="dojo.byId('action_iframe').src = 'permission/perm_list.html'; return false;">Permissions</a></li>
+                                       <li><a href="" onclick="dojo.byId('action_iframe').src = 'config/copy_status.html'; return false;">Copy Statuses</a></li>
+                               </ul>
+                       </div>
+                       <div id="content_pane" jsId="content_pane" dojoType="dijit.layout.ContentPane" layoutAlign="client" style="margin: 2px; border-top: 2px solid grey; border-bottom: 2px solid grey; border-left: 2px solid grey;">
+                               <iframe id="action_iframe" marginwidth="0" marginheight="0" style="border:0; height: 100%; width: 100%;"></iframe>
+                       </div>
+                       <div id="bottom_pane" jsId="bottom_pane" dojoType="dijit.layout.ContentPane" layoutAlign="bottom" orientation="horizontal" style="margin: 4px; height: 5%; width: 100%" title="Controls">
+                               <span id="status_text"/>
+                       </div>
+               </div>
+       </body>
+</html>
+
diff --git a/Open-ILS/web/conify/global/config/copy_status.html b/Open-ILS/web/conify/global/config/copy_status.html
new file mode 100644 (file)
index 0000000..90e3b2f
--- /dev/null
@@ -0,0 +1,275 @@
+<!--
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+       <head>
+               <title>Confiy :: Global :: Config :: Copy Status</title>
+
+               <style type="text/css">
+                       @import url("/js/dojo/dojox/grid/_grid/tundraGrid.css");
+                       @import url("/js/dojo/dojo/resources/dojo.css");
+                       @import url("/js/dojo/dijit/themes/tundra/tundra.css");
+                       @import url("/js/dojo/dojox/widget/Toaster/Toaster.css");
+               </style>
+
+               <style>
+                       html, body {
+                               height: 100%;
+                               width: 100%;
+                               margin: 0px 0px 0px 0px;
+                               padding: 0px 0px 0px 0px;
+                               overflow: hidden;
+                       }
+
+                       #status_grid {
+                               border: 0px;
+                               width: 100%;
+                               height: 100%;
+                       }
+
+                       #grid_container {
+                               width: 100%;
+                               height: 100%;
+                       }
+               </style>
+
+               <!-- The OpenSRF API writ JS -->
+               <script language='javascript' src='/opac/common/js/utils.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/Cookies.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/CGI.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/JSON_v1.js' type='text/javascript'></script>
+
+               <!-- Fieldmapper objects -->
+               <script language='javascript' src='/opac/common/js/fmall.js' type='text/javascript'></script>
+
+               <!-- Dojo goodness -->
+               <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+               <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
+
+               <script type="text/javascript" src="copy_status.js"></script>
+
+       </head>
+
+       <body class="tundra" id='pagebody'>
+
+               <div dojoType="dijit.layout.LayoutContainer" id="grid_container" jsId="grid_container" orientation="vertical">
+                       <script type="dojo/method">
+                               window.highlighter= {};
+                               window.highlighter.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'grid_container', duration : 500 } );
+                               window.highlighter.red = dojox.fx.highlight( { color : '#FF2018', node : 'grid_container', duration : 500 } );
+
+                               window.dirtyStore = [];
+
+                pCRUD.request({
+                    method : 'open-ils.permacrud.search.ccs.atomic',
+                    timeout : 10,
+                    params : [ ses, { id : { "!=" : null } }, { order_by : { ccs : 'name' } } ],
+                    onerror : function (r) { status_update('Problem fetching statuses') },
+                    oncomplete : function (r) {
+
+                        window._status_list = r.recv().content();
+                        window._status_data = ccs.toStoreData( window._status_list, 'name' );
+                        window.status_store = new dojo.data.ItemFileWriteStore({ data : window._status_data });
+
+                           window.status_store.onSet = function (item, attr, o, n) {
+                            if (attr == 'ischanged') return;
+                            if (n == o) return;
+                            this.setValue( item, 'ischanged', 1);
+
+                            if (attr == 'holdable' && typeof n != 'string')
+                                this.setValue(item, 'holdable', n ? 't' : 'f');
+
+                        };
+
+                        dojo.addOnUnload( function (event) {
+
+                            status_store.fetch({
+                                query : { ischanged : 1 },
+                                onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
+                                scope : status_store
+                            });
+
+                            if (dirtyStore.length > 0) {
+                                var confirmation = confirm(
+                                    'There are unsaved modified Statuses!  '+
+                                    'OK to save these changes, Cancel to abandon them.'
+                                );
+
+                                if (confirmation) {
+                                    for (var i in window.dirtyStore) {
+                                        window.current_status = window.dirtyStore[i];
+                                        save_status(true);
+                                    }
+                                }
+                            }
+
+                        });
+                    }
+                }).send();
+
+                       </script>
+
+                       <div dojoType="dijit.layout.LayoutContainer" orientation="horizontal" style="margin-top: 5px;" layoutAlign="top">
+                               <span>New Status:</span>
+                               <div dojoType="dijit.form.TextBox" id="new_status_code" jsId="new_status_name" label="New Status Name"></div>
+                               <button dojoType="dijit.form.Button" id="save_new_status_code" jsId="save_new_status_name" label="Add"> 
+                                       <script type="dojo/connect" event="onClick">
+
+                                               var new_name = new_status_name.getValue();
+                                               if (!new_name) return;
+
+                       var new_fm_obj = new ccs().fromHash({
+                               isnew           : 1,
+                           name            : new_name
+                           });
+    
+                       var err = false;
+                           pCRUD.request({
+                           method : 'open-ils.permacrud.create.ccs',
+                               timeout : 10,
+                           params : [ ses, new_fm_obj ],
+                               onerror : function (r) {
+                               highlighter.red.play();
+                                   status_update( 'Problem calling method to create new Status' );
+                               err = true;
+                               },
+                               oncomplete : function (r) {
+                               var res = r.recv();
+                                   if ( res && res.content() ) {
+                                   var new_item_hash = res.content().toHash();
+                                   status_store.newItem( new_item_hash );
+                                                                       status_update( 'New ' + new_item_hash.name + ' status created' );
+                                                                       status_grid.model.sort(-2);
+                                                                       highlighter.green.play();
+                               } else {
+                                       highlighter.red.play();
+                                   status_update( 'Problem creating new Status' );
+                                       err = true;
+                               }
+                               }
+                       }).send();
+    
+                       </script>
+                               </button>
+                       </div>
+
+                       <div dojoType="dijit.layout.ContentPane" style="width:100%; height:100%;" layoutAlign="client">
+                               <div dojoType="dojox.grid.data.DojoData" id="status_data_model"jsId="status_data_model" store="status_store" query="{ 'id' : '*' }"></div>
+                               <div id="status_grid" dojoType="dojox.Grid" jsId="status_grid">
+                                       <script type="dojo/connect" event="startup">
+                                               var g = this;
+                                               var status_grid_layout = [
+                                                       {       cells : [
+                                                                       [
+                                                                               { name : "ID",
+                                                                                 field : "id",
+                                                                               },
+                                                                               { name : "Name",
+                                                                                 field : "name",
+                                                                                 width : "auto",
+                                                                                 editor : dojox.grid.editors.Dijit
+                                                                               },
+                                                                               { name : "Holdable",
+                                                                                 field : "holdable",
+                                                                                 editor : dojox.grid.editors.bool,
+                                          get : function (row) {
+                                               var r = window.status_data_model.getRow(row);
+                                                                                       if (r) {
+                                                       var h = r.holdable;
+                                                           if (h == 't' || h === true) return true;
+                                                               return false;
+                                                                                       }
+                                          }
+                                                                               }
+                                                                       ]
+                                                               ]
+                                                       }
+                                               ];
+
+                                               this.setStructure(status_grid_layout);
+                                               this.setModel(window.status_data_model);
+                                       </script>
+                               </div>
+                       </div>
+
+                       <div dojoType="dijit.layout.ContentPane" orientation="horizontal" style="margin-bottom: 5px;" layoutAlign="bottom">
+               
+                               <button jsId="save_ccs_button" dojoType="dijit.form.Button" label="Save Changes" onClick="save_them_all()"></button>
+               
+                               <button jsId="delete_ccs_button" dojoType="dijit.form.Button" label="Delete Selected">
+                                       <script type="dojo/connect" event="onClick">
+
+                                               var selected_rows = status_grid.selection.getSelected();
+               
+                                               var selected_items = [];
+                                               for (var i in selected_rows) {
+                                                       selected_items.push(
+                                                               status_grid.model.getRow( selected_rows[i] ).__dojo_data_item
+                                                       );
+                                               }
+
+                                               status_grid.selection.clear();
+
+                                               for (var i in selected_items) {
+                                                       current_status = selected_items[i];
+
+                                                       if ( confirm('Are you sure you want to delete ' + status_store.getValue( current_status, 'name' ) + '?')) {
+
+                                                               status_store.setValue( current_status, 'isdeleted', 1 );
+                       
+                                                               var modified_ccs = new ccs().fromStoreItem( current_status );
+                                                               modified_ccs.isdeleted( 1 );
+                       
+                                                               pCRUD.request({
+                                                                       method : 'open-ils.permacrud.delete.ccs',
+                                                                       timeout : 10,
+                                                                       params : [ ses, modified_ccs ],
+                                                                       onerror : function (r) {
+                                                                               highlighter.red.play();
+                                                                               status_update( 'Problem deleting ' + status_store.getValue( current_status, 'name' ) );
+                                                                       },
+                                                                       oncomplete : function (r) {
+                                                                               var res = r.recv();
+                                                                               if ( res && res.content() ) {
+                       
+                                                                                       var old_name = status_store.getValue( current_status, 'name' );
+               
+                                                                                       status_store.fetch({
+                                                                                               query : { id : status_store.getValue( current_status, 'id' ) },
+                                                                                               onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
+                                                                                               scope : status_store
+                                                                                       });
+                       
+                                                                                       current_status = null;
+                       
+                                                                                       highlighter.green.play();
+                                                                                       status_update( old_name + ' deleted' );
+                                                                               } else {
+                                                                                       highlighter.red.play();
+                                                                                       status_update( 'Problem deleting ' + old_name );
+                                                                               }
+                                                                       }
+                                                               }).send();
+               
+                                                       }
+                                               }
+       
+                                       </script>
+                               </button>
+       
+                       </div>
+               </div>
+       
+       </body>
+</html>
diff --git a/Open-ILS/web/conify/global/config/copy_status.js b/Open-ILS/web/conify/global/config/copy_status.js
new file mode 100644 (file)
index 0000000..9fffc7a
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+# ---------------------------------------------------------------------------
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# ---------------------------------------------------------------------------
+*/
+
+dojo.require('fieldmapper.dojoData');
+dojo.require('dojo.parser');
+dojo.require('dojo.string');
+dojo.require('dojo.data.ItemFileWriteStore');
+dojo.require('dijit.form.TextBox');
+dojo.require('dijit.form.ValidationTextBox');
+dojo.require('dijit.form.Textarea');
+dojo.require('dijit.layout.ContentPane');
+dojo.require('dijit.layout.LayoutContainer');
+dojo.require('dijit.layout.BorderContainer');
+dojo.require('dojox.widget.Toaster');
+dojo.require('dojox.fx');
+dojo.require('dojox.grid.Grid');
+dojo.require('dojox.grid._data.model');
+dojo.require("dojox.grid.editors");
+
+// some handy globals
+var cgi = new CGI();
+var cookieManager = new HTTP.Cookies();
+var ses = cookieManager.read('ses') || cgi.param('ses');
+var pCRUD = new OpenSRF.ClientSession('open-ils.permacrud');
+
+var current_status;
+var virgin_out_id = -1;
+
+var highlighter = {};
+
+function status_update (markup) {
+       if (parent !== window && parent.status_update) parent.status_update( markup );
+}
+
+function save_status () {
+
+       var modified_ccs = new ccs().fromStoreItem( current_status );
+       modified_ccs.ischanged( 1 );
+
+       pCRUD.request({
+               method : 'open-ils.permacrud.update.ccs',
+               timeout : 10,
+               params : [ ses, modified_ccs ],
+               onerror : function (r) {
+                       highlighter.red.play();
+                       status_update( 'Problem saving ' + status_store.getValue( current_status, 'name' ) );
+               },
+               oncomplete : function (r) {
+                       var res = r.recv();
+                       if ( res && res.content() ) {
+                               status_store.setValue( current_status, 'ischanged', 0 );
+                               highlighter.green.play();
+                               status_update( 'Saved changes to ' + status_store.getValue( current_status, 'name' ) );
+                       } else {
+                               highlighter.red.play();
+                               status_update( 'Problem saving ' + status_store.getValue( current_status, 'name' ) );
+                       }
+               },
+       }).send();
+}
+
+function save_them_all (event) {
+
+       status_store.fetch({
+               query : { ischanged : 1 },
+               onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
+               scope : status_store
+       });
+
+       var confirmation = true;
+
+
+       if (event && dirtyStore.length > 0) {
+               confirmation = confirm(
+                       'There are unsaved modified Statuses!  '+
+                       'OK to save these changes, Cancel to abandon them.'
+               );
+       }
+
+       if (confirmation) {
+               for (var i in window.dirtyStore) {
+                       window.current_status = window.dirtyStore[i];
+                       save_status(true);
+               }
+
+               window.dirtyStore = [];
+       }
+}
+
+dojo.addOnUnload( save_them_all );
+
diff --git a/Open-ILS/web/conify/global/permission/grp_tree.html b/Open-ILS/web/conify/global/permission/grp_tree.html
new file mode 100644 (file)
index 0000000..f8ea5ca
--- /dev/null
@@ -0,0 +1,739 @@
+<!--
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+-->
+<html xmlns="http://www.w2.org/1999/xhtml">
+       <head>
+               <title>Confiy :: Global :: Permission :: Group Tree</title>
+
+               <style type="text/css">
+                       @import url("/js/dojo/dojox/grid/_grid/tundraGrid.css");
+                       @import url("/js/dojo/dojo/resources/dojo.css");
+                       @import url("/js/dojo/dijit/themes/tundra/tundra.css");
+                       @import url("/js/dojo/dojox/widget/Toaster/Toaster.css");
+               </style>
+
+               <style>
+                       html, body
+                       {
+                               height: 100%;
+                               width: 100%;
+                               margin: 0px 0px 0px 0px;
+                               padding: 0px 0px 0px 0px;
+                               overflow: hidden;
+                       }
+
+                       th
+                       {
+                               text-align: right;
+                               font-weight: bold;
+                               padding-left: 20px;
+                               padding-right: 5px;
+                       }
+
+            #perm_grid {
+                border: 0px;
+                width: 100%;
+                height: 100%;
+            }
+
+            #grid_container {
+                width: 75%;
+                height: 100%;
+            }
+
+               </style>
+
+               <!-- The OpenSRF API writ JS -->
+               <script language='javascript' src='/opac/common/js/utils.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/Cookies.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/CGI.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/JSON_v1.js' type='text/javascript'></script>
+
+               <!-- Fieldmapper objects XXX need to dojo-ize this -->
+               <script language='javascript' src='/opac/common/js/fmall.js' type='text/javascript'></script>
+
+               <!-- Dojo goodness -->
+               <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+               <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
+
+               <script type="text/javascript" src="grp_tree.js"></script>
+
+       </head>
+
+       <body class="tundra" id='pagebody'>
+
+               <div dojoType="dijit.layout.SplitContainer" orientation="horizontal" style="height: 100%">
+
+                       <div dojoType="dijit.layout.ContentPane" sizeShare="100">
+                               <script type="dojo/method">
+                                       window.dirtyStore = [];
+
+                    server.pCRUD.request({
+                        method : 'open-ils.permacrud.search.pgt.atomic',
+                        timeout : 10,
+                        params : [ ses, { id : { "!=" : null } }, { order_by : { pgt : 'name' } } ],
+                        onerror : function (r) { status_update('Problem fetching groups') },
+                        oncomplete : function (r) {
+                            window._group_list = r.recv().content();
+                            window._group_data = pgt.toStoreData( window._group_list );
+                            window.group_store = new dojo.data.ItemFileWriteStore({ data : window._group_data });
+                            window.group_store.onSet = function (item, attr, o, n) {
+                                if (attr == 'ischanged') return;
+                                if (n == o) return;
+                                this.setValue( item, 'ischanged', 1);
+                            };
+                            dojo.addOnUnload( function (event) {
+
+                                window.group_store.fetch({
+                                    query : { ischanged : 1 },
+                                    queryOptions : { deep : true },
+                                    onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
+                                    scope : window.group_store
+                                });
+
+                                if (dirtyStore.length > 0) {
+                                    var confirmation = confirm(
+                                        'There are unsaved modified Groups!  '+
+                                        'OK to save these changes, Cancel to abandon them.'
+                                    );
+
+                                    if (confirmation) {
+                                        for (var i in window.dirtyStore) {
+                                            window.current_group = window.dirtyStore[i];
+                                            save_group(true);
+                                        }
+                                    }
+                                }
+
+                            });
+                        }
+                    }).send();
+
+                    server.actor.request({
+                        method : 'open-ils.actor.org_types.retrieve',
+                        timeout : 10,
+                        onerror : function (r) { status_update('Problem fetching types') },
+                        oncomplete : function (r) {
+                            window._ou_type_list = r.recv().content();
+                            window._ou_type_data = aout.toStoreData( window._ou_type_list );
+                            window.ou_type_store = new dojo.data.ItemFileReadStore({ data : window._ou_type_data });
+                        }
+                    }).send();
+
+                    server.actor.request({
+                        method : 'open-ils.actor.permissions.retrieve',
+                        timeout : 10,
+                        onerror : function (r) { status_update('Problem fetching perms') },
+                        oncomplete : function (r) {
+    
+                            window._perm_list = r.recv().content();
+
+                            window._perm_data = ppl.toStoreData( window._perm_list, 'code' );
+                            window._perm_name_data = ppl.toStoreData( window._perm_list, 'code', { identifier : 'code' } );
+
+                            window.perm_store = new dojo.data.ItemFileWriteStore({ data : window._perm_data });
+                            window.perm_name_store = new dojo.data.ItemFileWriteStore({ data : window._perm_name_data });
+    
+   
+                        }
+                    }).send();
+
+                    server.pCRUD.request({
+                        method : 'open-ils.permacrud.search.pgpm.atomic',
+                        timeout : 10,
+                        params : [ ses, { id : { "!=" : null } } ],
+                        onerror : function (r) { status_update('Problem fetching perm maps') },
+                        oncomplete : function (r) {
+                            window._perm_map_list = r.recv().content();
+                            window._perm_map_data = pgpm.toStoreData( window._perm_map_list, 'id' );
+                            window.perm_map_store = new dojo.data.ItemFileWriteStore({ data : window._perm_map_data });
+
+                                                       window.perm_map_store.onSet = function (item, attr, o, n) {
+                                                               if (attr == 'ischanged') return;
+                                                               if (n == o) return;
+
+                                                               this.setValue( item, 'ischanged', 1);
+
+                                                               if (attr == 'grantable' && typeof n != 'string')
+                                                                       this.setValue(item, 'grantable', n ? 't' : 'f');
+                                                       }
+
+                            dojo.addOnUnload( function (event) { save_them_all(); });
+                        }
+                    }).send();
+
+                               </script>
+                               <div
+                                 id="group_tree"
+                                 label="Permission Groups"
+                                 query="{'_top':'true'}"
+                                 dojoType="dijit.Tree"
+                                 store="group_store"
+                                 minSize="200"
+                                 jsId="group_tree"
+                               >
+
+                                       <script type="dojo/method" event="onClick" args="item,node">
+
+                                               right_pane_toggler.show();
+
+                                               current_group = item;
+
+                                               perm_map_model.query = { grp : current_group ? current_group.id[0] : -1 };
+                                               perm_map_model.refresh();
+                                               perm_grid.refresh();
+
+                                               highlighter.editor_pane.green.play();
+                                               status_update( 'Now editing ' + this.store.getValue( item, 'name' ) );
+
+                                               new_kid_button.disabled = false;
+                                               save_group_button.disabled = false;
+                                               delete_group_button.disabled = false;
+
+                                               var main_settings_fields = [ 'name', 'perm_interval', 'description'];
+                                               for ( var i in main_settings_fields ) {
+                                                       var field = main_settings_fields[i];
+                                                       var value = this.store.getValue( current_group, field );
+
+                                                       if (!value) {
+                                                               window["editor_pane_" + field].setValue( '' ); // unset the value
+                                                               if (field != 'description') window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
+                                                       } else window["editor_pane_" + field].setValue( value );
+                                               }
+
+                                               if ( this.store.getValue( current_group, '_trueRoot' ) == 'true' ) {
+                                                       editor_pane_parent.disabled = true;
+                                                       editor_pane_parent.setValue(null);
+                                                       editor_pane_parent.setDisplayedValue('');
+                                                       editor_pane_parent.validate(false);
+                                               } else {
+                                                       editor_pane_parent.disabled = false;
+                                                       editor_pane_parent.validate(true);
+                                                       editor_pane_parent.setValue( this.store.getValue( current_group, 'parent' ) );
+                                               }
+
+                                               editor_pane_application_perm.setValue( this.store.getValue( current_group, 'application_perm' ) );
+
+                                               editor_pane_usergroup.setChecked( this.store.getValue( current_group, 'usergroup' ) == 't' ? true : false );
+
+                                       </script>
+
+                                       <script type="dojo/method" event="getLabel" args="item,pI">
+                                               var label = this.store.getValue(item,'name');
+                                               if (this.store.getValue(item,'ischanged') == 1) label = '* ' + label;
+                                               return label;
+                                       </script>
+
+                               </div>
+                       </div>
+
+                       <div id="right_pane" dojoType="dijit.layout.ContentPane"  sizeShare="300">
+                               <script type="dojo/method">
+                                       window.right_pane_toggler = new dojo.fx.Toggler({ node: 'right_pane'});
+                                       window.right_pane_toggler.hide();
+                               </script>
+
+                               <div dojoType="dijit.layout.TabContainer">
+                                       <div id="editor_pane" dojoType="dijit.layout.ContentPane" title="Group Configuration">
+                                               <script type="dojo/method">
+                                                       highlighter.group_tree = {};
+                                                       highlighter.editor_pane = {};
+                                                       highlighter.group_tree.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'group_tree', duration : 500 } );
+                                                       highlighter.group_tree.red = dojox.fx.highlight( { color : '#FF2018', node : 'group_tree', duration : 500 } );
+                                                       highlighter.editor_pane.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'editor_pane', duration : 500 } );
+                                                       highlighter.editor_pane.red = dojox.fx.highlight( { color : '#FF2018', node : 'editor_pane', duration : 500 } );
+                                               </script>
+       
+                                               <table class="tundra" style="margin:10px;">
+                                                       <tr>
+                                                               <th>Group Name</th>
+                                                               <td>
+                                                                       <span id="editor_pane_name" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_name" regExp=".+" required="true">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_group) {
+                                                                                               group_store.setValue( current_group, "name", this.getValue() );
+                                                                                       }
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Description</th>
+                                                               <td>
+                                                                       <textarea
+                                                                         id="editor_pane_description"
+                                                                         dojoType="dijit.form.Textarea"
+                                                                         jsId="editor_pane_description"
+                                                                         onChange="if (current_group) group_store.setValue( current_group, "description", this.getValue() );"
+                                                                       ></textarea>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Permission Interval</th>
+                                                               <td>
+                                                                       <span id="editor_pane_perm_interval" dojoType="dijit.form.ValidationTextBox" jsId="editor_pane_perm_interval" regExp="^\d+ (?:y.*|mo.*|d.*)$" required="true">
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_group) {
+                                                                                               group_store.setValue( current_group, "perm_interval", this.getValue() );
+                                                                                       }
+                                                                               </script>
+                                                                       </span>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Editing Permission</th>
+                                                               <td>
+                                                                       <div
+                                                                         id="editor_pane_application_perm"
+                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                         store="perm_name_store"
+                                                                         searchAttr="code"
+                                                                         jsId="editor_pane_application_perm"
+                                                                       >
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_group && this.getValue()) {
+                                                                                               group_store.setValue( current_group, "application_perm", this.getValue() );
+                                                                                       }
+                                                                               </script>
+                                                                       </div>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>Parent Group</th>
+                                                               <td>
+                                                                       <div
+                                                                         id="editor_pane_parent"
+                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                         jsId="editor_pane_parent"
+                                                                         store="group_store"
+                                                                         searchAttr="name"
+                                                                         ignoreCase="true"
+                                                                         required="true"
+                                                                       >
+                                                                               <script type="dojo/connect" event="onChange">
+                                                                                       if (current_group && this.getValue()) {
+                                                                                               this.store.setValue( current_group, "parent", this.getValue() );
+                                                                                       }
+                                                                               </script>
+                                                                       </div>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <th>User Group</th>
+                                                               <td>
+                                                                       <input
+                                                                         id="editor_pane_usergroup"
+                                                                         jsId="editor_pane_usergroup"
+                                                                         type="checkbox"
+                                                                         dojoType="dijit.form.CheckBox"
+                                                                         onChange='if (current_group) group_store.setValue( current_group, "usergroup", this.checked ? "t" : "f" );'
+                                                                       />
+                                                               </td>
+                                                       </tr>
+                                               </table>
+       
+                                               <div dojoType="dijit.layout.ContentPane" orientation="horizontal" style="margin-bottom: 20px;">
+       
+                                                       <button jsId="save_group_button" dojoType="dijit.form.Button" label="Save" onClick="save_group()">
+                                                               <script type="dojo/connect" event="startup">
+                                                                       this.disabled = true;
+                                                               </script>
+                                                       </button>
+       
+                                                       <button jsId="delete_group_button" dojoType="dijit.form.Button" label="Delete">
+                                                               <script type="dojo/connect" event="startup">
+                                                                       this.disabled = true;
+                                                               </script>
+                                                               <script type="dojo/connect" event="onClick">
+       
+                                                                       if (group_store.getValue( current_group, '_trueRoot' ) == 'true') {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Cannot delete' + group_store.getValue( current_group, 'name' ) + ', you need at least one.' );
+                                                                               return false;
+                                                                       }
+
+                                                                       if ( current_group.children ) {
+                                                                               var kids = current_group.children;
+                                                                               if (!dojo.isArray(kids)) kids = [kids];
+       
+                                                                               var existing_kids = dojo.filter(
+                                                                                       kids,
+                                                                                       function(kid){ return kid.isdeleted[0] != 1 }
+                                                                               );
+                                                                               if ( existing_kids.length > 0) {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Cannot delete' + group_store.getValue( current_group, 'name' ) + ', ' + existing_kids.length + ' subordinates still exist.' );
+                                                                                       return;
+                                                                               }
+                                                                       }
+       
+                                                                       if ( confirm('Are you sure you want to delete ' + current_group.name + '?')) {
+                                                                               group_store.setValue( current_group, 'isdeleted', 1 );
+       
+                                                                               var modified_pgt = new pgt().fromStoreItem( current_group );
+                                                                               modified_pgt.isdeleted( 1 );
+       
+                                                                               server.pCRUD.request({
+                                                                                       method : 'open-ils.permacrud.delete.pgt',
+                                                                                       timeout : 10,
+                                                                                       params : [ ses, modified_pgt ],
+                                                                                       onerror : function (r) {
+                                                                                               highlighter.editor_pane.red.play();
+                                                                                               status_update( 'Problem deleting ' + group_store.getValue( current_group, 'name' ) );
+                                                                                       },
+                                                                                       oncomplete : function (r) {
+                                                                                               var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+       
+                                                                                                       var old_name = group_store.getValue( current_group, 'name' );
+
+                                                                                                       group_store.fetch({
+                                                                                                               query : { id : group_store.getValue( current_group, 'id' ) },
+                                                                                                               queryOptions : { deep : true },
+                                                                                                               onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
+                                                                                                               scope : group_store
+                                                                                                       });
+       
+                                                                                                       current_group = null;
+       
+                                                                                                       new_kid_button.disabled = true;
+                                                                                                       save_group_button.disabled = true;
+                                                                                                       delete_group_button.disabled = true;
+                       
+                                                                                                       var main_settings_fields = [ 'name', 'perm_interval', 'description' ];
+                                                                                                       for ( var i in main_settings_fields ) {
+                                                                                                               var field = main_settings_fields[i];
+                                                                                                               window["editor_pane_" + field].setValue( '' ); // unset the value
+                                                                                                               window["editor_pane_" + field].setDisplayedValue( '' ); // unset the value
+                                                                                                       }
+
+                                                                                                       window["editor_pane_usergroup"].setChecked( false ); // unset the value
+                       
+                                                                                                       highlighter.editor_pane.green.play();
+                                                                                                       status_update( old_name + ' deleted' );
+                                                                                               } else {
+                                                                                                       highlighter.editor_pane.red.play();
+                                                                                                       status_update( 'Problem deleting ' + old_name );
+                                                                                               }
+                                                                                       }
+                                                                               }).send();
+       
+                                                                       }
+       
+                                                               </script>
+                                                       </button>
+       
+                                               </div>
+       
+                                               <button jsId="new_kid_button" dojoType="dijit.form.Button" label="New Child">
+                                                       <script type="dojo/connect" event="startup">
+                                                               this.disabled = true;
+                                                       </script>
+                                                       <script type="dojo/connect" event="onClick">
+       
+                                                               var new_fm_obj = new pgt().fromHash({
+                                                                       isnew                   : 1,
+                                                                       name                    : 'New Group',
+                                                                       usergroup               : 'f',
+                                                                       parent                  : group_store.getValue( current_group, 'id' )
+                                                               });
+       
+                                                               var err = false;
+                                                               server.pCRUD.request({
+                                                                       method : 'open-ils.permacrud.create.pgt',
+                                                                       timeout : 10,
+                                                                       params : [ ses, new_fm_obj ],
+                                                                       onerror : function (r) {
+                                                                               highlighter.editor_pane.red.play();
+                                                                               status_update( 'Problem calling method to create child Group' );
+                                                                               err = true;
+                                                                       },
+                                                                       oncomplete : function (r) {
+                                                                               var res = r.recv();
+                                                                               if ( res && res.content() ) {
+                                                                                       group_store.newItem(
+                                                                                               res.content().toHash(),
+                                                                                               { parent : current_group, attribute : 'children' }
+                                                                                       );
+                                                                               } else {
+                                                                                       highlighter.editor_pane.red.play();
+                                                                                       status_update( 'Problem creating child Group' );
+                                                                                       err = true;
+                                                                               }
+                                                                       },
+                                                               }).send();
+       
+                                                               if (!err) {
+                                                                       highlighter.editor_pane.green.play();
+                                                                       highlighter.group_tree.green.play();
+                                                                       status_update( 'New child Group created for ' + group_store.getValue( current_group, 'name' ) );
+                                                               }
+       
+                                                       </script>
+                                               </button>
+       
+                                       </div>
+
+                                       <div id="perm_pane" dojoType="dijit.layout.ContentPane" title="Group Permissions">
+                                               <script type="dojo/connect" event="onShow">
+                                                       perm_map_model.query = { grp : current_group ? current_group.id[0] : -1 };
+                                                       perm_map_model.refresh();
+                                                       perm_grid.refresh();
+                                               </script>
+                                               <div dojoType="dijit.layout.LayoutContainer" orientation="horizontal" style="width:100%; height:100%;">
+                                                       <div id="grid_container" dojoType="dijit.layout.ContentPane" sizeShare="1" layoutAlign="left">
+                                                               <div dojoType="dojox.grid.data.DojoData" id="perm_map_model"jsId="perm_map_model" store="perm_map_store"></div>
+       
+                                                               <div id="perm_grid" dojoType="dojox.Grid" model="perm_map_model" jsId="perm_grid">
+                                                                       <script type="dojo/connect" event="startup">
+       
+                                                                               function get_item_part(model_field, item_search_field, item_part, model, store, datum, row) {
+                                                                                       var formatter = true;
+       
+                                                                                       if (!row && row != '0') {
+                                                                                               row = datum;
+                                                                                               formatter = false;
+                                                                                       }
+       
+                                                                                       if(!model.getRow(row)) return null;
+                                                                                       var value = null;
+       
+                                                                                       if(!formatter) { //this.editor && (this.editor.alwaysOn || (this.grid.edit.info.rowIndex==row && this.grid.edit.info.cell==this))) {
+                                                                                               return model.getRow(row)[model_field];
+                                                                                       }
+       
+                                                                                       var q = {};
+                                                                                       q[item_search_field] = model.getRow(row)[model_field];
+       
+                                                                                       store.fetch({
+                                                                                               query : q,
+                                                                                               onItem : function (item) { value = store.getValue( item, item_part ) }
+                                                                                       });
+
+                                                                                       return value;
+                                                                               }
+       
+                                                   window.current_perm_grid_layout = [
+                                                       {   cells : [
+                                                                   [
+                                                                           {   name : "Code",
+                                                                                                                       field: "perm",
+                                                                                                                       formatter : dojo.partial(get_item_part, "perm", "id", "code", perm_map_model, perm_store),
+                                                                                                                       width : "auto"
+                                                                                                               },
+                                                                                               {       name : "Depth",
+                                                                                                                       field : "depth",
+                                                                                                                       formatter : dojo.partial(get_item_part, "depth", "depth", "name", perm_map_model, ou_type_store),
+                                                                                                                       editor : dojox.grid.editors.select,
+                                                                                                                       options : dojo.map( _ou_type_list, function (x) { return x.name() } ),
+                                                                                                                       values : dojo.map( _ou_type_list, function (x) { return x.depth() } )
+                                                                                                               }, 
+                                                                   {   name : "Grantable",
+                                                                                                                       field : "grantable",
+                                                                                                                       editor : dojox.grid.editors.bool,
+                                                                                                                       get : function (row) {
+                                                                                                                               var gr = get_item_part("id", "id", "grantable", perm_map_model, perm_map_model.store, row, row);
+                                                                                                                               if (gr == 't' || gr === true) return true;
+                                                                                                                               return false;
+                                                                                                                       },
+                                                                                                               }
+                                                                                               ]
+                                                                                               ]
+                                                       }
+                                                   ];
+
+                                                                               perm_grid.setStructure(window.current_perm_grid_layout);
+       
+                                                                       </script>
+                                                               </div>
+                                                       </div>
+
+                                                       <div id="new_perm_container" dojoType="dijit.layout.ContentPane" sizeShare="1" layoutAlign="client">
+
+                                                               <div dojoType="dijit.form.DropDownButton" id="new_popup" jsId="new_popup">
+                                                                       <span>New Mapping</span>
+                                                                       <div  dojoType="dijit.TooltipDialog"> 
+                                                                               <table class="tundra">
+                                                                                       <tr>
+                                                                                               <td>Permission:</td>
+                                                                                               <td>
+                                                                                                       <div
+                                                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                                                         Id="new_perm_select"
+                                                                                                         jsId="new_perm_select"
+                                                                                                         store="perm_store"
+                                                                                                         searchAttr="code"
+                                                                                                         ignoreCase="true"
+                                                                                                         required="true"></div>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                                       <tr>
+                                                                                               <td>Depth:</td>
+                                                                                               <td>
+                                                                                                       <div
+                                                                                                         dojoType="dijit.form.FilteringSelect"
+                                                                                                         Id="new_depth_select"
+                                                                                                         jsId="new_depth_select"
+                                                                                                         store="ou_type_store"
+                                                                                                         searchAttr="name"
+                                                                                                         ignoreCase="true"
+                                                                                                         required="true"></div>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                                       <tr>
+                                                                                               <td>Grantable:</td>
+                                                                                               <td>
+                                                                                                       <input
+                                                                                                         type="checkbox"
+                                                                                                         dojoType="dijit.form.CheckBox"
+                                                                                                         Id="new_grant_checkbox"
+                                                                                                         jsId="new_grant_checkbox"
+                                                                                                         value="t"></input>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                               </table>
+
+                                                                               <button dojoType="dijit.form.Button" jsId="new_mapping_add" label="Add Mapping">
+                                                                   <script type="dojo/connect" event="onClick">
+                                               
+                                                                       var new_perm = new_perm_select.getValue();
+                                                                       if (!new_perm) return;
+               
+                                                                       var new_type_id = new_depth_select.getValue();
+                                                                       if (!new_type_id) return;
+               
+                                                                                               var new_type;
+                                                               window.ou_type_store.fetch({
+                                                               query : { id : new_type_id },
+                                                               onItem : function (item, req) { try { new_type = item } catch (e) { /* meh */ } },
+                                                               });
+               
+                                                                       var new_depth = ou_type_store.getValue( new_type, 'depth')
+                                                                       var new_grant = new_grant_checkbox.getValue();
+                                               
+                                                                       var new_fm_obj = new pgpm().fromHash({
+                                                                           isnew       : 1,
+                                                                           perm        : new_perm,
+                                                                           depth       : new_depth,
+                                                                                                       grp                     : group_store.getValue( current_group, 'id' ),
+                                                                                                       grantable       : new_grant ? 't' : 'f'
+                                                                       });
+                                                   
+                                                                       var err = false;
+                                                                       server.pCRUD.request({
+                                                                           method : 'open-ils.permacrud.create.pgpm',
+                                                                           timeout : 10,
+                                                                           params : [ ses, new_fm_obj ],
+                                                                           onerror : function (r) {
+                                                                               highlighter.group_tree.red.play();
+                                                                               status_update( 'Problem calling method to create new Permission Map' );
+                                                                               err = true;
+                                                                           },
+                                                                           oncomplete : function (r) {
+               
+                                                                               var res = r.recv();
+                                                                               if ( res && res.content() ) {
+                                                                                   var new_item_hash = res.content().toHash();
+                                                                                   perm_map_store.newItem( new_item_hash );
+                                                                                   status_update( 'New permission map created' );
+                                                                                   highlighter.group_tree.green.play();
+               
+                                                                                           perm_map_model.query = { grp : current_group ? current_group.id[0] : -1 };
+                                                                                   perm_grid.model.sort(-1);
+                                                                                           perm_map_model.refresh();
+                                                                                           perm_grid.refresh();
+               
+                                                                               } else {
+                                                                                   highlighter.group_tree.red.play();
+                                                                                   status_update( 'Problem creating new Permission Map' );
+                                                                                   err = true;
+                                                                               }
+                                                                           }
+                                                                       }).send();
+
+                                                                                               new_popup._closeDropDown();
+                   
+                                                                   </script>
+               
+                                                                               </button>
+                                                                       </div>
+                                                               </div>
+
+                                                               <button jsId="save_pgpm_button" dojoType="dijit.form.Button" label="Save Changes" onClick="save_them_all()"></button><br/>
+
+                                               <button jsId="delete_pgpm_button" dojoType="dijit.form.Button" label="Remove Selected">
+                                                       <script type="dojo/connect" event="onClick">
+                                       
+                                                       var selected_rows = perm_grid.selection.getSelected();
+                                       
+                                                       var selected_items = [];
+                                                       for (var i in selected_rows) {
+                                                           selected_items.push(
+                                                               perm_grid.model.getRow( selected_rows[i] ).__dojo_data_item
+                                                           );
+                                                       }
+                       
+                                                       perm_grid.selection.clear();
+                               
+                                                           for (var i in selected_items) {
+                                                                   window.current_perm_map = selected_items[i];
+                       
+                                                                       perm_map_store.setValue( window.current_perm_map, 'isdeleted', 1 );
+                                                       
+                                                                           var modified_pgpm = new pgpm().fromStoreItem( window.current_perm_map );
+                                                                               modified_pgpm.isdeleted( 1 );
+                                   
+                                                       server.pCRUD.request({
+                                                           method : 'open-ils.permacrud.delete.pgpm',
+                                                           timeout : 10,
+                                                               params : [ ses, modified_pgpm ],
+                                                                   onerror : function (r) {
+                                                                                                       highlighter.editor_pane.red.play();
+                                                                               status_update( 'Problem deleting permission mapping ' + perm_map_store.getValue( window.current_perm_map, 'id' ) );
+                                                                               },
+                                                                                   oncomplete : function (r) {
+                                                                                           var res = r.recv();
+                                                                                               if ( res && res.content() ) {
+                                               
+                                                                                   perm_map_store.fetch({
+                                                                                           query : { id : perm_map_store.getValue( window.current_perm_map, 'id' ) },
+                                                                                               onItem : function (item, req) { try { if (this.isItem( item )) this.deleteItem( item ); } catch (e) { /* meh */ } },
+                                                                                                   scope : perm_map_store
+                                                                                                   });
+                           
+                                                                                                       window.current_perm_map = null;
+                                               
+                                                                                                               highlighter.editor_pane.green.play();
+                                                                                       status_update( 'Permission mapping deleted' );
+                                                                                       } else {
+                                                                                                               highlighter.editor_pane.red.play();
+                                                                                                   status_update( 'Problem deleting permission mapping ' + perm_map_store.getValue( window.current_perm_map, 'id' ));
+                                                                                                   }
+                                                           }
+                                                       }).send();
+                                       
+                                                       }
+                                   
+                                                       </script>
+                                                       </button>
+       
+                                                       </div>
+                                               </div>
+                                       </div>
+                               </div>
+                       </div>
+               </div>
+       </body>
+</html>
diff --git a/Open-ILS/web/conify/global/permission/grp_tree.js b/Open-ILS/web/conify/global/permission/grp_tree.js
new file mode 100644 (file)
index 0000000..05d3dbd
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+# ---------------------------------------------------------------------------
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# ---------------------------------------------------------------------------
+*/
+
+dojo.require('fieldmapper.dojoData');
+dojo.require('dojo.parser');
+dojo.require('dojo.data.ItemFileWriteStore');
+dojo.require('dojo.date.stamp');
+dojo.require('dijit.form.NumberSpinner');
+dojo.require('dijit.form.TextBox');
+dojo.require('dijit.form.TimeTextBox');
+dojo.require('dijit.form.ValidationTextBox');
+dojo.require('dijit.form.CheckBox');
+dojo.require('dijit.form.FilteringSelect');
+dojo.require('dijit.form.Textarea');
+dojo.require('dijit.form.Button');
+dojo.require('dijit.Dialog');
+dojo.require('dijit.Tree');
+dojo.require('dijit.layout.ContentPane');
+dojo.require('dijit.layout.TabContainer');
+dojo.require('dijit.layout.LayoutContainer');
+dojo.require('dijit.layout.SplitContainer');
+dojo.require('dojox.widget.Toaster');
+dojo.require('dojox.fx');
+dojo.require('dojox.grid.Grid');
+dojo.require('dojox.grid._data.model');
+dojo.require("dojox.grid.editors");
+
+// some handy globals
+var cgi = new CGI();
+var cookieManager = new HTTP.Cookies();
+var ses = cookieManager.read('ses') || cgi.param('ses');
+var server = {};
+server.pCRUD = new OpenSRF.ClientSession('open-ils.permacrud');
+server.actor = new OpenSRF.ClientSession('open-ils.actor');
+
+var current_group;
+var virgin_out_id = -1;
+
+var highlighter = {};
+
+function status_update (markup) {
+       if (parent !== window && parent.status_update) parent.status_update( markup );
+}
+
+function save_group () {
+
+       var modified_pgt = new pgt().fromStoreItem( current_group );
+       modified_pgt.ischanged( 1 );
+
+       new_kid_button.disabled = false;
+       save_out_button.disabled = false;
+       delete_out_button.disabled = false;
+
+       server.pCRUD.request({
+               method : 'open-ils.permacrud.update.pgt',
+               timeout : 10,
+               params : [ ses, modified_pgt ],
+               onerror : function (r) {
+                       highlighter.editor_pane.red.play();
+                       status_update( 'Problem saving data for ' + group_store.getValue( current_group, 'name' ) );
+               },
+               oncomplete : function (r) {
+                       var res = r.recv();
+                       if ( res && res.content() ) {
+                               group_store.setValue( current_group, 'ischanged', 0 );
+                               highlighter.editor_pane.green.play();
+                               status_update( 'Saved changes to ' + group_store.getValue( current_group, 'name' ) );
+                       } else {
+                               highlighter.editor_pane.red.play();
+                               status_update( 'Problem saving data for ' + group_store.getValue( current_group, 'name' ) );
+                       }
+               },
+       }).send();
+}
+
+function save_perm_map (storeItem) {
+
+       var modified_pgpm = new pgpm().fromStoreItem( storeItem );
+       modified_pgpm.ischanged( 1 );
+
+       server.pCRUD.request({
+               method : 'open-ils.permacrud.update.pgpm',
+               timeout : 10,
+               params : [ ses, modified_pgpm ],
+               onerror : function (r) {
+                       highlighter.editor_pane.red.play();
+                       status_update( 'Problem saving permission data for ' + group_store.getValue( current_group, 'name' ) );
+               },
+               oncomplete : function (r) {
+                       var res = r.recv();
+                       if ( res && res.content() ) {
+                               perm_map_store.setValue( storeItem, 'ischanged', 0 );
+                               highlighter.editor_pane.green.play();
+                               status_update( 'Saved permission changes to ' + group_store.getValue( current_group, 'name' ) );
+                       } else {
+                               highlighter.editor_pane.red.play();
+                               status_update( 'Problem saving permission data for ' + group_store.getValue( current_group, 'name' ) );
+                       }
+               },
+       }).send();
+}
+
+function save_them_all (event) {
+
+       var dirtyMaps = [];
+
+    perm_map_store.fetch({
+        query : { ischanged : 1 },
+        onItem : function (item, req) { try { if (this.isItem( item )) dirtyMaps.push( item ); } catch (e) { /* meh */ } },
+        scope : perm_map_store
+    });
+
+    var confirmation = true;
+
+
+    if (event && dirtyMaps.length > 0) {
+        confirmation = confirm(
+            'There are unsaved modified Permission Maps!  '+
+            'OK to save these changes, Cancel to abandon them.'
+        );
+    }
+
+    if (confirmation) {
+        for (var i in dirtyMaps) {
+            save_perm_map(dirtyMaps[i]);
+        }
+    }
+}
+
+dojo.addOnUnload( save_them_all );
+
diff --git a/Open-ILS/web/conify/global/permission/perm_list.html b/Open-ILS/web/conify/global/permission/perm_list.html
new file mode 100644 (file)
index 0000000..4fc1a05
--- /dev/null
@@ -0,0 +1,252 @@
+<!--
+# Copyright (C) 2008  Georgia Public Library Service / Equinox Software, Inc
+# Mike Rylander <miker@esilibrary.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+       <head>
+               <title>Confiy :: Global :: Permission :: Permission List</title>
+
+               <style type="text/css">
+                       @import url("/js/dojo/dojox/grid/_grid/tundraGrid.css");
+                       @import url("/js/dojo/dojo/resources/dojo.css");
+                       @import url("/js/dojo/dijit/themes/tundra/tundra.css");
+                       @import url("/js/dojo/dojox/widget/Toaster/Toaster.css");
+               </style>
+
+               <style>
+                       html, body {
+                               height: 100%;
+                               width: 100%;
+                               margin: 0px 0px 0px 0px;
+                               padding: 0px 0px 0px 0px;
+                               overflow: hidden;
+                       }
+
+                       #perm_grid {
+                               border: 0px;
+                               width: 100%;
+                               height: 100%;
+                       }
+
+                       #grid_container {
+                               width: 100%;
+                               height: 100%;
+                       }
+               </style>
+
+               <!-- The OpenSRF API writ JS -->
+               <script language='javascript' src='/opac/common/js/utils.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/Cookies.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/CGI.js' type='text/javascript'></script>
+               <script language='javascript' src='/opac/common/js/JSON_v1.js' type='text/javascript'></script>
+
+               <!-- Fieldmapper objects -->
+               <script language='javascript' src='/opac/common/js/fmall.js' type='text/javascript'></script>
+
+               <!-- Dojo goodness -->
+               <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+               <script type="text/javascript" src="/js/dojo/dijit/dijit.js"></script>
+
+               <script type="text/javascript" src="perm_list.js"></script>
+
+       </head>
+
+       <body class="tundra" id='pagebody'>
+
+               <div dojoType="dijit.layout.LayoutContainer" id="grid_container" jsId="grid_container" orientation="vertical">
+                       <script type="dojo/method">
+                               window.highlighter= {};
+                               window.highlighter.green = dojox.fx.highlight( { color : '#B4FFB4', node : 'grid_container', duration : 500 } );
+                               window.highlighter.red = dojox.fx.highlight( { color : '#FF2018', node : 'grid_container', duration : 500 } );
+
+                               window.dirtyStore = [];
+
+                pCRUD.request({
+                    method : 'open-ils.permacrud.search.ppl.atomic',
+                    timeout : 10,
+                    params : [ ses, { id : { "!=" : null } }, { order_by : { ppl : 'code' } } ],
+                    onerror : function (r) { status_update('Problem fetching perms') },
+                    oncomplete : function (r) {
+
+                        window._perm_list = r.recv().content();
+                        window._perm_data = ppl.toStoreData( window._perm_list, 'code' );
+                        window.perm_store = new dojo.data.ItemFileWriteStore({ data : window._perm_data });
+
+                           perm_store.onSet = function (item, attr, o, n) {
+                            if (attr == 'ischanged') return;
+                            if (n == o) return;
+                            this.setValue( item, 'ischanged', 1);
+                        };
+
+                                               window.perm_grid_layout = [
+                                                       {       cells : [
+                                                                       [
+                                                                               { name : "Code",        field : "code",        width : "300px", editor : dojox.grid.editors.Dijit },
+                                                                               { name : "Description", field : "description", width : "auto",  editor : dojox.grid.editors.Editor }
+                                                                       ]
+                                                               ]
+                                                       }
+                                               ];
+
+                        dojo.addOnUnload( function (event) {
+
+                            perm_store.fetch({
+                                query : { ischanged : 1 },
+                                onItem : function (item, req) { try { if (this.isItem( item )) window.dirtyStore.push( item ); } catch (e) { /* meh */ } },
+                                scope : perm_store
+                            });
+
+                            if (dirtyStore.length > 0) {
+                                var confirmation = confirm(
+                                    'There are unsaved modified Permissions!  '+
+                                    'OK to save these changes, Cancel to abandon them.'
+                                );
+
+                                if (confirmation) {
+                                    for (var i in window.dirtyStore) {
+                                        window.current_perm = window.dirtyStore[i];
+                                        save_perm(true);
+                                    }
+                                }
+                            }
+
+                        });
+                    }
+                }).send();
+
+                       </script>
+
+                       <div dojoType="dijit.layout.LayoutContainer" orientation="horizontal" style="margin-top: 5px;" layoutAlign="top">
+                               <span>New Permission:</span>
+                               <div dojoType="dijit.form.TextBox" id="new_perm_code" jsId="new_perm_code" label="New Code"></div>
+                               <button dojoType="dijit.form.Button" id="save_new_perm_code" jsId="save_new_perm_code" label="Add"> 
+                                       <script type="dojo/connect" event="onClick">
+
+                                               var new_code = new_perm_code.getValue();
+                                               if (!new_code) return;
+
+                       var new_fm_obj = new ppl().fromHash({
+                               isnew           : 1,
+                           code            : new_code
+                           });
+    
+                       var err = false;
+                           pCRUD.request({
+                           method : 'open-ils.permacrud.create.ppl',
+                               timeout : 10,
+                           params : [ ses, new_fm_obj ],
+                               onerror : function (r) {
+                               highlighter.red.play();
+                                   status_update( 'Problem calling method to create new Permission' );
+                               err = true;
+                               },
+                               oncomplete : function (r) {
+                               var res = r.recv();
+                                   if ( res && res.content() ) {
+                                   var new_item_hash = res.content().toHash();
+                                   perm_store.newItem( new_item_hash );
+                                                                       status_update( 'New ' + new_item_hash.code + ' permission created' );
+                                                                       perm_grid.model.sort(-1);
+                                                                       highlighter.green.play();
+                               } else {
+                                       highlighter.red.play();
+                                   status_update( 'Problem creating new Permission' );
+                                       err = true;
+                               }
+                               }
+                       }).send();
+    
+             &n