From cb560b73c69ae32756be7579671fca98f19d4074 Mon Sep 17 00:00:00 2001 From: erickson Date: Thu, 2 Sep 2010 21:10:04 +0000 Subject: [PATCH] back-porting: 17399 17413 => optimized distrib formula management UI git-svn-id: svn://svn.open-ils.org/ILS/branches/rel_2_0@17459 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Acq/Order.pm | 44 +++++ Open-ILS/web/images/dimple.png | Bin 0 -> 155 bytes Open-ILS/web/images/licenses.txt | 3 + Open-ILS/web/js/dojo/openils/conify/nls/conify.js | 4 +- .../conify/global/acq/distribution_formula.js | 198 +++++++++++++++++++-- .../conify/global/acq/distribution_formula.tt2 | 93 ++++++---- 6 files changed, 293 insertions(+), 49 deletions(-) create mode 100644 Open-ILS/web/images/dimple.png create mode 100644 Open-ILS/web/images/licenses.txt diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm index 044e5d166a..a99ac82828 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm @@ -3124,4 +3124,48 @@ sub fetch_and_check_li { } +__PACKAGE__->register_method( + method => "clone_distrib_form", + api_name => "open-ils.acq.distribution_formula.clone", + stream => 1, + signature => { + desc => q/Clone a distribution formula/, + params => [ + {desc => "Authentication token", type => "string"}, + {desc => "Original formula ID", type => 'integer'}, + {desc => "Name of new formula", type => 'string'}, + ], + return => {desc => "ID of newly created formula"} + } +); + +sub clone_distrib_form { + my($self, $client, $auth, $form_id, $new_name) = @_; + + my $e = new_editor("xact"=> 1, "authtoken" => $auth); + return $e->die_event unless $e->checkauth; + + my $old_form = $e->retrieve_acq_distribution_formula($form_id) or return $e->die_event; + return $e->die_event unless $e->allowed('ADMIN_ACQ_DISTRIB_FORMULA', $old_form->owner); + + my $new_form = Fieldmapper::acq::distribution_formula->new; + + $new_form->owner($old_form->owner); + $new_form->name($new_name); + $e->create_acq_distribution_formula($new_form) or return $e->die_event; + + my $entries = $e->search_acq_distribution_formula_entry({formula => $form_id}); + for my $entry (@$entries) { + my $new_entry = Fieldmapper::acq::distribution_formula_entry->new; + $new_entry->$_($entry->$_()) for $entry->real_fields; + $new_entry->formula($new_form->id); + $new_entry->clear_id; + $e->create_acq_distribution_formula_entry($new_entry) or return $e->die_event; + } + + $e->commit; + return $new_form->id; +} + 1; + diff --git a/Open-ILS/web/images/dimple.png b/Open-ILS/web/images/dimple.png new file mode 100644 index 0000000000000000000000000000000000000000..4d0b91bfea743f38796fabf7e599ce6f23b6e246 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c4!3HFg*81KCQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jiflby978y+CnqE%Y+!g~rLiqRKupY!)##3c#F?_f!jB9^ zSAeX0+j64=oSmChIht?q{Qv*|I@==_jcaTSt)|kvPPx6SfCe#my85}Sb4q9e0Ol?* A$p8QV literal 0 HcmV?d00001 diff --git a/Open-ILS/web/images/licenses.txt b/Open-ILS/web/images/licenses.txt new file mode 100644 index 0000000000..3392eb524c --- /dev/null +++ b/Open-ILS/web/images/licenses.txt @@ -0,0 +1,3 @@ +dimple.png derived from: +http://mxr.mozilla.org/mozilla-central/source/toolkit/themes/pinstripe/global/splitter/dimple.png +Mozilla Public License/GPL/GLPL diff --git a/Open-ILS/web/js/dojo/openils/conify/nls/conify.js b/Open-ILS/web/js/dojo/openils/conify/nls/conify.js index eea305da1e..363d21dbdf 100644 --- a/Open-ILS/web/js/dojo/openils/conify/nls/conify.js +++ b/Open-ILS/web/js/dojo/openils/conify/nls/conify.js @@ -85,6 +85,8 @@ "SURVEY_QUESTION": "Question:", "SURVEY_ID": "Survey ID # ${0}", "SURVEY_FOOT_LABEL": "Questions & Answers", - "EVENT_DEF_LABEL" : "${0}: ${1}" + "EVENT_DEF_LABEL" : "${0}: ${1}", + "ACQ_DISTRIB_FORMULA_NAME_PROMPT" : "Enter new formula name", + "ACQ_DISTRIB_FORMULA_NAME_CLONE" : "${0} (Clone)" } diff --git a/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js b/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js index 10d19904ba..b992d26006 100644 --- a/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js +++ b/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js @@ -1,11 +1,23 @@ +dojo.require("dojo.dnd.Container"); +dojo.require("dojo.dnd.Source"); dojo.require('openils.widget.AutoGrid'); dojo.require('dijit.form.FilteringSelect'); dojo.require('openils.PermaCrud'); -var formula; +dojo.require('openils.widget.AutoFieldWidget'); +dojo.requireLocalization('openils.conify', 'conify'); +var localeStrings = dojo.i18n.getLocalization('openils.conify', 'conify'); + + var formCache = []; +var formula, entryTbody, entryTemplate, dndSource; +var virtualId = -1; +var pcrud; + function draw() { + pcrud = new openils.PermaCrud(); + if(formulaId) { openils.Util.hide('formula-list-div'); drawFormulaSummary(); @@ -33,18 +45,31 @@ function draw() { } } -openils.Util.addOnLoad(draw); -function drawFormulaSummary() { - openils.Util.show('formula-entry-div'); - dfeListGrid.overrideEditWidgets.formula = new - dijit.form.TextBox({style:'display:none', value: formulaId}); - dfeListGrid.loadAll({order_by:{acqdfe : 'formula'}}, {formula : formulaId}); - var pcrud = new openils.PermaCrud(); - var formulaName = pcrud.retrieve('acqdf', formulaId); - dojo.byId('formula_head').innerHTML = formulaName.name(); +function cloneSelectedFormula() { + var item = fListGrid.getSelectedItems()[0]; + if(!item) return; + var formula = new fieldmapper.acqf().fromStoreItem(item); + fieldmapper.standardRequest( + ['open-ils.acq', 'open-ils.acq.distribution_formula.clone'], + { + asnyc : true, + params : [ + openils.User.authtoken, + formula.id(), + dojo.string.substitute(localeStrings.ACQ_DISTRIB_FORMULA_NAME_CLONE, [formula.name()]) + ], + oncomplete : function(r) { + if(r = openils.Util.readResponse(r)) { + location.href = oilsBasePath + '/conify/global/acq/distribution_formula/' + r; + } + } + } + ); } +openils.Util.addOnLoad(draw); + function getItemCount(rowIndex, item) { if(!item) return ''; var form = formCache[this.grid.store.getValue(item, "id")]; @@ -54,3 +79,156 @@ function getItemCount(rowIndex, item) { return count; } +function byName(node, name) { + return dojo.query('[name='+name+']', node)[0]; +} + +function drawFormulaSummary() { + openils.Util.show('formula-entry-div'); + + var entries = pcrud.search('acqdfe', {formula: formulaId}, {order_by:{acqdfe : 'position'}}); + formula = pcrud.retrieve('acqdf', formulaId); + formula.entries(entries); + + dojo.byId('formula_head').innerHTML = formula.name(); + dojo.byId('formula_head').onclick = function() { + var name = prompt(localeStrings.ACQ_DISTRIB_FORMULA_NAME_PROMPT, formula.name()); + if(name && name != formula.name()) { + formula.name(name); + pcrud = new openils.PermaCrud(); + pcrud.update(formula); + dojo.byId('formula_head').innerHTML = name; + } + } + + dojo.forEach(entries, function(entry) { addEntry(entry); } ); +} + +function addEntry(entry) { + + if(!entryTbody) { + entryTbody = dojo.byId('formula-entry-tbody'); + entryTemplate = entryTbody.removeChild(dojo.byId('formula-entry-tempate')); + dndSource = new dojo.dnd.Source(entryTbody); + dndSource.selectAll(); + dndSource.deleteSelectedNodes(); + dndSource.clearItems(); + } + + if(!entry) { + entry = new fieldmapper.acqdfe(); + entry.formula(formulaId); + entry.item_count(1); + entry.owning_lib(openils.User.user.ws_ou()); + entry.id(virtualId--); + entry.isnew(true); + formula.entries().push(entry); + } + + var row = entryTbody.appendChild(entryTemplate.cloneNode(true)); + row.setAttribute('entry', entry.id()); + dndSource.insertNodes(false, [row]); + byName(row, 'delete').onclick = function() { + entry.isdeleted(true); + entryTbody.removeChild(row); + dndSource.sync(); + }; + + dojo.forEach( + ['owning_lib', 'location', 'item_count'], + function(field) { + new openils.widget.AutoFieldWidget({ + forceSync : true, + fmField : field, + fmObject : entry, + fmClass : 'acqdfe', + parentNode : byName(row, field), + orgDefaultsToWs : true, + orgLimitPerms : ['ADMIN_ACQ_DISTRIB_FORMULA'], + widgetClass : (field == 'item_count') ? 'dijit.form.NumberSpinner' : null, + dijitArgs : (field == 'item_count') ? {min:1, places:0} : null + }).build( + function(w, ww) { + dojo.connect(w, 'onChange', + function(newVal) { + entry[field]( newVal ); + entry.ischanged(true); + } + ) + } + ); + } + ); +} + +function saveFormula() { + var pos = 1; + var updatedEntries = []; + var deletedEntries = []; + + // remove deleted entries from consideration for collision protection + for(var i = 0; i < formula.entries().length; i++) { + if(formula.entries()[i].isdeleted()) + deletedEntries.push(formula.entries().splice(i--, 1)[0]) + } + + // update entry positions and create temporary collision avoidance entries + dojo.forEach( + dndSource.getAllNodes(), + function(node) { + + var entryId = node.getAttribute('entry'); + var entry = formula.entries().filter(function(e) {return (e.id() == entryId)})[0]; + + if(entry.position() != pos) { + + // update the position + var changedEntry = entry.clone(); + changedEntry.position(pos); + changedEntry.ischanged(true); + updatedEntries.push(changedEntry); + + // clear the virtual ID + if(changedEntry.isnew()) + changedEntry.id(null); + + var oldEntry = formula.entries().filter(function(e) {return (e.position() == pos)})[0]; + + if(oldEntry) { + // move the entry currently in that spot temporarily into negative territory + var moveMe = oldEntry.clone(); + moveMe.ischanged(true); + moveMe.position(moveMe.position() * -1); + updatedEntries.unshift(moveMe); + } + } + pos++; + } + ); + + // finally, for every entry that changed w/o changing position + // throw it on the list for update + dojo.forEach( + formula.entries(), + function(entry) { + if(entry.ischanged() && !entry.isdeleted() && !entry.isnew()) { + if(updatedEntries.filter(function(e) { return (e.id() == entry.id()) }).length == 0) + updatedEntries.push(entry); + } + } + ); + + updatedEntries = deletedEntries.concat(updatedEntries); + if(updatedEntries.length) { + pcrud = new openils.PermaCrud(); + try { + pcrud.apply(updatedEntries); + } catch(E) { + alert('error updating: ' + E); + return; + } + location.href = location.href; + } +} + + diff --git a/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2 b/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2 index bb932ca975..94a7e2ec3d 100644 --- a/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2 +++ b/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2 @@ -1,22 +1,23 @@ [% WRAPPER default/base.tt2 %] [% ctx.page_title = 'Distribution Formulas' %] - @@ -27,6 +28,7 @@ function formatName(value) {
+
-
-
-
-
-
-
- - -
-
-
-
- - - - -
-
+
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + +
Owning LibraryShelving LocationItem Count
X
+ + + + +
+
+
+ + + +
+ [% END %] -- 2.11.0