From 7e12a0c8d7eacdbd8ca454b55678ae256408bcde Mon Sep 17 00:00:00 2001 From: Lebbeous Fogle-Weekley Date: Mon, 11 Nov 2013 17:52:03 -0500 Subject: [PATCH] LP#1272074 Context menus suggesting values for marc fixed field editor Signed-off-by: Lebbeous Fogle-Weekley Signed-off-by: Dan Wells --- .../perlmods/lib/OpenILS/Application/Cat.pm | 57 +++++++++ .../xul/staff_client/server/cat/marcedit.js | 111 ++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm index ab74ed83a8..e48cc62c0a 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm @@ -1323,6 +1323,63 @@ sub acn_sms_msg { +__PACKAGE__->register_method( + method => "fixed_field_values_by_rec_type", + api_name => "open-ils.cat.biblio.fixed_field_values.by_rec_type", + argc => 2, + signature => { + desc => 'Given a record type (as in cmfpm.rec_type), return fixed fields and their possible values as known to the DB', + params => [ + {desc => 'Record Type', type => 'string'}, + {desc => '(Optional) Fixed field', type => 'string'}, + ] + }, + return => {desc => 'an object in which the keys are fixed fields and the values are arrays representing the set of all unique values for that fixed field in that record type', type => 'object' } +); + + +sub fixed_field_values_by_rec_type { + my ($self, $conn, $rec_type, $fixed_field) = @_; + + my $e = new_editor; + my $values = $e->json_query({ + select => { + crad => ["fixed_field"], + ccvm => [qw/code value/], + }, + distinct => 1, + from => { + ccvm => { + crad => { + join => { + cmfpm => { + fkey => "fixed_field", + field => "fixed_field" + } + } + } + } + }, + where => { + "+cmfpm" => {rec_type => $rec_type}, + defined $fixed_field ? + ("+crad" => {fixed_field => $fixed_field}) : () + }, + order_by => [ + {class => "crad", field => "fixed_field"}, + {class => "ccvm", field => "code"} + ] + }) or return $e->die_event; + + my $result = {}; + for my $row (@$values) { + $result->{$row->{fixed_field}} ||= []; + push @{$result->{$row->{fixed_field}}}, [@$row{qw/code value/}]; + } + + return $result; +} + 1; # vi:et:ts=4:sw=4 diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.js b/Open-ILS/xul/staff_client/server/cat/marcedit.js index 27f5870928..02cfa1e5fc 100644 --- a/Open-ILS/xul/staff_client/server/cat/marcedit.js +++ b/Open-ILS/xul/staff_client/server/cat/marcedit.js @@ -42,6 +42,9 @@ var p; var auth_pages = {}; var show_auth_menu = false; +var _fixed_field_values = {}, _fixed_field_context_menus = {}; +var _fixed_field_anonymous_func_counter = 0; + function $(id) { return document.getElementById(id); } var acs; // AuthorityControlSet @@ -408,6 +411,7 @@ function my_init() { loadRecord(); + if (! xulG.fast_add_item) { document.getElementById('fastItemAdd_checkbox').hidden = true; } @@ -883,6 +887,113 @@ function changeFFEditor (type) { } }); + getFFValuesForType( + type, + function() { + updateFFEditorContexts(grid, type); + }, + function() { + alert( /* XXX i18n - the marc editor either isn't tied in to + an overall i18n infrastructure, or it's different + enough from other Evergreen parts that I don't + understand the right way to do i18n here */ + "failed to load fixed field values for rec_type '" + + type + "'\n" + ); + } + ); +} + +function getFFValuesForType(type, callback, errback) { + if (_fixed_field_values[type]) { + callback(); + } else { + dojo.require("openils.Util"); + + fieldmapper.standardRequest( + ["open-ils.cat", + "open-ils.cat.biblio.fixed_field_values.by_rec_type"], { + "async": true, + "params": [type], + "oncomplete": function(r) { + if (r = openils.Util.readResponse(r)) { + _fixed_field_values[type] = r; + callback(); + } else { + errback(); + } + }, + "onerror": errback + } + ); + } +} + +function updateFFEditorContexts(grid, type) { + + /* XXX Dojo to navigate a XUL DOM. Bad form? We do it elsewhere in this + * file, but I think I've heard it scoffed at. */ + + var rows_node = dojo.query("rows", grid)[0]; + dojo.query("row", rows_node).forEach( + function(row) { + dojo.query("textbox", row).forEach( + function(tb) { + var name = tb.getAttribute("name"); + if (_fixed_field_values[type][name]) { + tb.setAttribute( + "context", getFFContextMenu(type, name) + ); + } else { + tb.setAttribute("context", "clipboard"); + } + } + ); + } + ); +} + +function getFFContextMenu(type, name) { + if (!_fixed_field_context_menus[type]) { + _fixed_field_context_menus[type] = {}; + } + + var context_menu_id = "_fixed_field_context_menus_" + type + "_" + name; + + if (!_fixed_field_context_menus[type][name]) { + var p = document.getElementsByTagName("popupset")[0]; + var m = document.createElement("menupopup"); + m.setAttribute("id", context_menu_id); + _fixed_field_values[type][name].forEach( + function(v) { + var mi = document.createElement("menuitem"); + var funcname = "_ff_anon_" + + String(_fixed_field_anonymous_func_counter++); + + /* These anon functions linger and take up memory, but due + * to caching there's a limit on how much, and that limit is + * a function of the size of the dataset defined in the + * ccvm/cmfpm tables. */ + var code = v[0]; + var el = document.getElementById(name + "_tb"); + window[funcname] = function() { + el.value = code; + updateFixedFields(el); + }; + + /* In XUL land we can't set an element's + * attribute like oncommand to a code reference. It has to be + * an actual string to be eval'd. */ + mi.setAttribute("oncommand", funcname + "()"); + mi.setAttribute("label", v[0] + ": " + v[1]); /* XXX i18n ? */ + m.appendChild(mi); + } + ); + _fixed_field_context_menus[type][name] = m; + p.appendChild(m); + } + + return context_menu_id; } function fillFixedFields () { -- 2.43.2