Z39.50 attributes management interface
authorBill Erickson <berick@esilibrary.com>
Tue, 19 Jun 2012 14:23:22 +0000 (10:23 -0400)
committerDan Scott <dan@coffeecode.net>
Wed, 11 Jul 2012 22:15:38 +0000 (18:15 -0400)
From the release notes:

There is a new interface for managing Z39.50 attributes on a Z39.50
source.  The interface is linked from each source name in the Z39.50
Source administrative interface.

Cloning
~~~~~~

In addition to attribute creation, deletion, and editing, it's also
possible to clone a set of attributes from one source into another.
When cloning, any attributes present in the cloned source that are
not present in the destination source are copied into the destination
source.

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Dan Scott <dan@coffeecode.net>

Open-ILS/examples/fm_IDL.xml
Open-ILS/src/templates/conify/global/config/z3950_source.tt2
Open-ILS/web/js/ui/default/conify/global/config/z3950_source.js
docs/RELEASE_NOTES_NEXT/z3950-attr-admin-ui.txt [new file with mode: 0644]

index 88b1b71..6d0ad62 100644 (file)
@@ -857,7 +857,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
         </permacrud>
     </class>
 
-    <class id="cza" controller="open-ils.cstore" oils_obj:fieldmapper="config::z3950_attr" oils_persist:tablename="config.z3950_attr" reporter:label="Z39.50 Attribute">
+    <class id="cza" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::z3950_attr" oils_persist:tablename="config.z3950_attr" reporter:label="Z39.50 Attribute">
         <fields oils_persist:primary="id" oils_persist:sequence="config.z3950_attr_id_seq">
             <field reporter:label="Z39.50 Attribute ID" name="id" reporter:datatype="id"/>
             <field reporter:label="Z39.50 Source" name="source" reporter:datatype="link"/>
@@ -870,6 +870,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
         <links>
             <link field="source" reltype="has_a" key="name" map="" class="czs"/>
         </links>
+        <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+            <actions>
+                <create permission="ADMIN_Z3950_SOURCE" global_required="true"/>
+                <retrieve/>
+                <update permission="ADMIN_Z3950_SOURCE" global_required="true"/>
+                <delete permission="ADMIN_Z3950_SOURCE" global_required="true"/>
+            </actions>
+        </permacrud>
     </class>
 
        <class id="ateo" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="action_trigger::event_output" oils_persist:tablename="action_trigger.event_output" reporter:label="Event Output">
index cf32681..271dca8 100644 (file)
@@ -4,6 +4,54 @@
 
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
 
+[%  source_code = ctx.page_args.0; 
+    IF source_code %]
+
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>[% l('Z39.50 Attributes for [_1]', source_code) | html %]</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='zaGrid.showCreateDialog()'>[% l('New') %]</button>
+            <button dojoType='dijit.form.Button' onClick='zaGrid.deleteSelected()'>[% l('Delete Selected') %]</button>
+            <button dojoType='dijit.form.Button' onClick='showAttrCloneDialog()'>[% l('Clone Attributes From Source') %]</button>
+        </div>
+    </div>
+    <div>
+        <button onClick="location.href = location.href.replace(/\/[^\/]+$/, '')">[% l('Return to Sources') %]</button>
+    </div>
+    <br/>
+
+    <table
+        id="zaGrid"
+        jsid="zaGrid"
+        dojoType="openils.widget.FlattenerGrid"
+        columnPersistKey='"conify.config.z3950_attr"'
+        autoHeight="true"
+        editOnEnter="true"
+        editStyle="pane"
+        showLoadFilter="true"
+        fmClass="'cza'"
+        defaultSort="['code']"
+        query="{'source': ['[% source_code %]']}">
+        <thead>
+            <tr>
+                <th field="source" fpath="source" ffilter="true"/>
+                <th field="name" fpath="name" ffilter="true"/>
+                <th field="label" fpath="label" ffilter="true"/>
+                <th field="code" fpath="code" ffilter="true"/>
+                <th field="format" fpath="format" ffilter="true"/>
+                <th field="truncation" fpath="truncation" ffilter="true"/>
+            </tr>
+        </thead>
+    </table>
+
+    <div jsId="attrCloneDialog" dojoType="dijit.Dialog">
+        <span>[% l('Select a source to clone') %]</span>
+        <span><div id='attr-clone-source'></div></span>
+        <span><button onClick='cloneFromSource()'>[% l('Apply') %]</button></span>
+    </div>
+
+[% ELSE %]
+
     <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
         <div>Z39.50 Servers</div>
         <div>
             defaultCellWidth='"auto"'
             fmClass='czs'
             editOnEnter='true'>
+        <thead>
+            <th field='name' formatter='formatSourceName'/>
+        </thead>
     </table>
-</div>
 
 [% END %]
 
+</div>
+
+<script>var sourceCode = '[% source_code %]';</script>
+
+[% END %]
 
index ff2de10..23998e5 100644 (file)
@@ -2,13 +2,76 @@ dojo.require('dojox.grid.DataGrid');
 dojo.require('dojo.data.ItemFileReadStore');
 dojo.require('dijit.form.NumberTextBox');
 dojo.require('dijit.form.CheckBox');
+dojo.require('dijit.Dialog');
 dojo.require('fieldmapper.OrgUtils');
 dojo.require('openils.widget.OrgUnitFilteringSelect');
 dojo.require('openils.widget.AutoGrid');
+dojo.require('openils.widget.FlattenerGrid');
+dojo.require('openils.widget.AutoFieldWidget');
+dojo.require('openils.User');
+dojo.require('openils.PermaCrud');
 var zsList;
 
 function buildZSGrid() {
-    zsGrid.loadAll({order_by:{czs : 'name'}});
+
+    if (sourceCode) {
+
+        zaGrid.overrideWidgetArgs.source = {
+            widgetValue : sourceCode, 
+            readOnly : true
+        };
+
+    } else {
+
+        zsGrid.loadAll({order_by:{czs : 'name'}});
+    }
+}
+
+function formatSourceName(val) {
+    return '<a href="' + location.href + '/' + escape(val) + '">' + val + '</a>';
+}
+
+var cloneSourceSelector;
+function showAttrCloneDialog() {
+    attrCloneDialog.show();
+    if (!cloneSourceSelector) {
+        cloneSourceSelector = new openils.widget.AutoFieldWidget({
+            fmClass : 'czs',
+            fmField : 'name',
+            selfReference : true,
+            parentNode : 'attr-clone-source'
+        });
+        cloneSourceSelector.build();
+    }
+}
+
+function cloneFromSource() {
+    var pcrud = new openils.PermaCrud({authtoken : openils.User.authtoken}); 
+    var remoteAttrs = pcrud.search('cza', {source : cloneSourceSelector.widget.attr('value')});
+    var myAttrs = pcrud.search('cza', {source : sourceCode});
+    var newAttrs = [];
+
+    dojo.forEach(remoteAttrs, 
+        function(rattr) {
+
+            // if this source already has an attribute with the same name, don't clobber it
+            if (myAttrs.filter(function(a) { return (a.name() == rattr.name()) })[0]) 
+                return;
+            
+            var newAttr = rattr.clone();
+            newAttr.id(null);
+            newAttr.isnew(true);
+            newAttr.source(sourceCode);
+            newAttrs.push(newAttr);
+        }
+    );
+
+    if (newAttrs.length) {
+        pcrud.create(newAttrs, 
+            {oncomplete : function() { zaGrid.refresh() }});
+    }
+
+    attrCloneDialog.hide();
 }
 
 openils.Util.addOnLoad(buildZSGrid);
diff --git a/docs/RELEASE_NOTES_NEXT/z3950-attr-admin-ui.txt b/docs/RELEASE_NOTES_NEXT/z3950-attr-admin-ui.txt
new file mode 100644 (file)
index 0000000..7ad7102
--- /dev/null
@@ -0,0 +1,16 @@
+Z39.50 Source Attributes Management Interface
+---------------------------------------------
+
+There is a new interface for managing Z39.50 attributes on a Z39.50
+source.  The interface is linked from each source name in the Z39.50
+Source administrative interface.
+
+Cloning
+~~~~~~~
+
+In addition to attribute creation, deletion, and editing, it's also 
+possible to clone a set of attributes from one source into another.
+When cloning, any attributes present in the cloned source that are
+not present in the destination source are copied into the destination 
+source.
+