From: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com> Date: Tue, 5 Jun 2012 21:44:37 +0000 (-0400) Subject: Address LP #983487: Avoid clobbering bib records at authority merge X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=522d8d8292e5b5255c14dd7900597b27e2d4720b;p=evergreen%2Fmasslnc.git Address LP #983487: Avoid clobbering bib records at authority merge If you've set up a relationship between bib record and authority records based on arbitrary sets of controlling and controlled fields, but your authority records don't have the right Subj fixed field value corresponding to a control set that defines the controlling and controlled fields you're using, authority merge operations may wipe out lots of bib data. Yamil Suarez encountered this bug in testing, and in his case what he needed to do was set the Subj fixed field in his authority records to 'A' to match his Song Title Index (see the launchpad bug referened above). Previously, you could not actually save the Subj fixed field in the MARC editor (which showed HeadSubj instead of Subj for authority records, and didn't work). Now you can. Thanks to Mike Rylander for help in figuring out the above. To provide additional protection against merging authority records when they might not be linked with the right control set, the Manage Authorities interface will now also show you the linked control set for any given records. The implementation of that last bit incidentally meant making sure flesh and flesh_fields get passed through to PermaCrud for retrieve() calls via the Javascript openils.PermaCrud wrapper. Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com> Signed-off-by: Bill Erickson <berick@esilibrary.com> --- diff --git a/Open-ILS/src/templates/cat/authority/list.tt2 b/Open-ILS/src/templates/cat/authority/list.tt2 index c58040b4a7..216a4cb8a7 100644 --- a/Open-ILS/src/templates/cat/authority/list.tt2 +++ b/Open-ILS/src/templates/cat/authority/list.tt2 @@ -2,7 +2,14 @@ [% WRAPPER base.tt2 %] <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/cat/authority/list.js'> </script> - +<style type="text/css"> + .authEntry { clear: both; } + .authEntry > *:first-child { float: left; width: 20%; } + .authEntry > .text { float: left; width: 46%; } + .authEntry > .authority-control-set { float: right; width: 33%; ; font-style: italic; } + .authority-control-set .acs-name { font-weight: bold; } + .authority-control-set .acs-id { } +</style> <div dojoType="dijit.form.Form" id="myForm" jsId="myForm" encType="multipart/form-data" action="" method=""> <span style="white-space: nowrap;"> <label for="authTerm">Search term: </label> diff --git a/Open-ILS/web/js/dojo/openils/PermaCrud.js b/Open-ILS/web/js/dojo/openils/PermaCrud.js index ca3835772e..c284c65fb1 100644 --- a/Open-ILS/web/js/dojo/openils/PermaCrud.js +++ b/Open-ILS/web/js/dojo/openils/PermaCrud.js @@ -106,10 +106,14 @@ if(!dojo._hasResource["openils.PermaCrud"]) { retrieve : function ( fm_class /* Fieldmapper class hint */, id /* Fieldmapper object primary key value */, opts /* Option hash */) { if(!opts) opts = {}; + var ffj = {}; + if (opts.join) ffj.join = opts.join; + if (opts.flesh) ffj.flesh = opts.flesh; + if (opts.flesh_fields) ffj.flesh_fields = opts.flesh_fields; var req_hash = dojo.mixin( opts, { method : 'open-ils.pcrud.retrieve.' + fm_class, - params : [ this.auth(), id ] + params : [ this.auth(), id, ffj ] } ); diff --git a/Open-ILS/web/js/ui/default/cat/authority/list.js b/Open-ILS/web/js/ui/default/cat/authority/list.js index 591bfb8d6d..7486427d13 100644 --- a/Open-ILS/web/js/ui/default/cat/authority/list.js +++ b/Open-ILS/web/js/ui/default/cat/authority/list.js @@ -15,10 +15,24 @@ dojo.require('openils.PermaCrud'); dojo.require('openils.XUL'); dojo.require('openils.widget.OrgUnitFilteringSelect'); dojo.require("openils.widget.PCrudAutocompleteBox"); +dojo.require("MARC.FixedFields"); dojo.requireLocalization("openils.authority", "authority"); var auth_strings = dojo.i18n.getLocalization("openils.authority", "authority"); var cgi = new openils.CGI(); +var pcrud = new openils.PermaCrud(); + +var _acs_cache_by_at = {}; +function fetch_control_set(thesaurus) { + if (!_acs_cache_by_at[thesaurus]) { + var at = pcrud.retrieve( + "at", thesaurus, + {"flesh": 1, "flesh_fields": {"at": ["control_set"]}} + ); + _acs_cache_by_at[thesaurus] = at.control_set(); + } + return _acs_cache_by_at[thesaurus]; +} /* // OrgUnits do not currently affect the retrieval of authority records, @@ -40,6 +54,7 @@ function displayAuthorities(data) { dojo.query("record", data).forEach(function(node) { var auth = {}; auth.text = ''; + auth.thesaurus = '|'; auth.id = 0; // Grab each authority record field from the authority record @@ -56,17 +71,38 @@ function displayAuthorities(data) { auth.id = dojox.xml.parser.textContent(dfNode); }); + /* I wrap this in try/catch only because: + * a) this interface hasn't hitherto relied on MARC.Record, and + * b) the functionality we need it for is optional + */ + try { + var marc = new MARC.Record({"rtype": "AUT", "xml": node}); + auth.thesaurus = marc.extractFixedField("Subj", "|"); + } catch (E) { + console.warn( + "MARC.Record didn't work for authority record " + + auth.id + ": " + E + ); + } + idArr.push(parseInt(auth.id)); - // Create the authority record listing entry - dojo.place('<div class="authEntry" id="auth' + auth.id + '"><span class="text" id="authLabel' + auth.id + '">' + auth.text + '</span></div>', "authlist-div", "last"); + // Create the authority record listing entry. XXX i18n + dojo.place( + '<div class="authEntry" id="auth' + auth.id + '">' + + '<div class="text" id="authLabel' + auth.id + '">' + auth.text + '</div>' + + '<div class="authority-control-set">Control Set: <span class="acs-name">' + + fetch_control_set(auth.thesaurus).name() + + '</span> <span class="acs-id">(#' + + fetch_control_set(auth.thesaurus).id() + ')</span></div></div>', + "authlist-div", "last" + ); // Add the menu of new/edit/delete/mark-for-merge options var auth_menu = new dijit.Menu({}); // "Edit" menu item new dijit.MenuItem({"id": "edit_" + auth.id, "onClick": function(){ - var pcrud = new openils.PermaCrud(); var auth_rec = pcrud.retrieve("are", auth.id); if (auth_rec) { loadMarcEditor(pcrud, auth_rec); @@ -100,7 +136,6 @@ function displayAuthorities(data) { "onClick":function(){ auth.text = ''; - var pcrud = new openils.PermaCrud(); var auth_rec = pcrud.retrieve("are", auth.id); // Bit of a hack to get the linked bib count until an explicit ID @@ -145,7 +180,7 @@ function displayAuthorities(data) { }, "label":auth_strings.DELETE}).placeAt(auth_menu, "last"); auth_mb = new dijit.form.DropDownButton({dropDown: auth_menu, label: auth_strings.ACTIONS, id:"menu" + auth.id}); - auth_mb.placeAt("auth" + auth.id, "first"); + auth_mb.placeAt(dojo.create("div", null, "auth" + auth.id, "first"), "first"); auth_menu.startup(); }); @@ -194,7 +229,6 @@ function cancelDelete(recId) { } function confirmDelete(recId) { - var pcrud = new openils.PermaCrud(); var auth_rec = pcrud.retrieve("are", recId); if (auth_rec) { pcrud.eliminate(auth_rec); @@ -214,7 +248,7 @@ function showBibCount(authIds) { var msg = r.recv().content(); dojo.forEach(msg, function(auth) { linkedIds.push(auth.authority); - dojo.place('<span class="bibcount">' + auth.bibs + '</span>', 'authLabel' + auth.authority, 'before'); + dojo.place('<span class="bibcount">' + auth.bibs + '</span> ', 'authLabel' + auth.authority, 'first'); } ); @@ -227,7 +261,7 @@ function showBibCount(authIds) { } }); if (!found) { - dojo.place('<span class="bibcount">0</span>', 'authLabel' + id, 'before'); + dojo.place('<span class="bibcount">0</span> ', 'authLabel' + id, 'first'); } }); } diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.xul b/Open-ILS/xul/staff_client/server/cat/marcedit.xul index 7204883616..195edaea6a 100644 --- a/Open-ILS/xul/staff_client/server/cat/marcedit.xul +++ b/Open-ILS/xul/staff_client/server/cat/marcedit.xul @@ -209,8 +209,8 @@ <textbox id="HeadMain_tb" context="clipboard" class="plain" name="HeadMain" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/> </row> <row> - <label name="HeadSubj" control="HeadSubj_tb" set="AUT" value="HeadSubj" /> - <textbox id="HeadSubj_tb" context="clipboard" class="plain" name="HeadSubj" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/> + <label name="Subj" control="Subj_tb" set="AUT" value="Subj" /> + <textbox id="Subj_tb" context="clipboard" class="plain" name="Subj" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/> <label name="HeadSer" control="HeadSer_tb" set="AUT" value="HeadSer" /> <textbox id="HeadSer_tb" context="clipboard" class="plain" name="HeadSer" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/> <label name="TypeSubd" control="TypeSubd_tb" set="AUT" value="TypeSubd" />