LP#1329920: (follow-up) set searchFormat as well
[working/Evergreen.git] / Open-ILS / web / js / ui / default / conify / global / acq / distribution_formula.js
1 dojo.require("dojo.dnd.Container");
2 dojo.require("dojo.dnd.Source");
3 dojo.require('openils.widget.AutoGrid');
4 dojo.require('dijit.form.FilteringSelect');
5 dojo.require('openils.PermaCrud');
6 dojo.require('openils.widget.AutoFieldWidget');
7 dojo.requireLocalization('openils.conify', 'conify');
8 var localeStrings = dojo.i18n.getLocalization('openils.conify', 'conify');
9
10
11 var formCache = {};
12 var formula, entryTbody, entryTemplate, dndSource;
13 var virtualId = -1;
14 var pcrud;
15 var _collection_code_textboxes = [];
16 var _collection_code_kludge_active = false;
17 var fundSearchFilter = {active : 't'};
18 var fundLabelFormat = ['${0} (${1})', 'code', 'year'];
19
20 function gridDataLoader() {
21     fListGrid.resetStore();
22     fListGrid.showLoadProgressIndicator();
23     fieldmapper.standardRequest(
24         ["open-ils.acq", "open-ils.acq.distribution_formula.ranged.retrieve"], {
25             "async": true,
26             "params": [
27                 openils.User.authtoken,
28                 fListGrid.displayOffset,
29                 fListGrid.displayLimit
30             ],
31             "onresponse": function(r) {
32                 var form = openils.Util.readResponse(r);
33                 formCache[form.id()] = form;
34                 fListGrid.store.newItem(form.toStoreItem());
35             },
36             "oncomplete": function() {
37                 fListGrid.hideLoadProgressIndicator();
38             }
39         }
40     );
41 }
42
43 function setFundSearchFilter(callback) {
44     new openils.User().getPermOrgList(
45         ['ADMIN_ACQ_DISTRIB_FORMULA'],
46         function(orgs) { 
47             fundSearchFilter.org = orgs;
48             if (callback) callback();
49         },
50         true, true // descendants, id_list
51     );
52 }
53
54 function draw() {
55
56     pcrud = new openils.PermaCrud();
57
58     if(formulaId) {
59         openils.Util.hide('formula-list-div');
60         setFundSearchFilter(drawFormulaSummary);
61     } else {
62
63         openils.Util.hide('formula-entry-div');
64         fListGrid.onPostCreate = function(fmObject) {
65             location.href = location.href + '/' + fmObject.id();
66         }
67
68         fListGrid.dataLoader = gridDataLoader;
69         gridDataLoader();
70     }
71 }
72
73 function cloneSelectedFormula() {
74     var item = fListGrid.getSelectedItems()[0];
75     if(!item) return;
76     var formula = new fieldmapper.acqf().fromStoreItem(item);
77     fieldmapper.standardRequest(
78         ['open-ils.acq', 'open-ils.acq.distribution_formula.clone'],
79         {
80             asnyc : true,
81             params : [
82                 openils.User.authtoken, 
83                 formula.id(), 
84                 dojo.string.substitute(localeStrings.ACQ_DISTRIB_FORMULA_NAME_CLONE, [formula.name()])
85             ],
86             oncomplete : function(r) {
87                 if(r = openils.Util.readResponse(r)) {
88                     location.href = oilsBasePath + '/conify/global/acq/distribution_formula/' + r;
89                 }
90             }
91         }
92     );
93 }
94
95 openils.Util.addOnLoad(draw);
96
97 function getItemCount(rowIndex, item) {
98     if(!item) return '';
99     var form = formCache[this.grid.store.getValue(item, "id")];
100     if(!form) return 0;
101     var count = 0;
102     dojo.forEach(form.entries(), function(e) { count = count + e.item_count(); });
103     return count;
104 }
105
106 function byName(node, name) {
107     return dojo.query('[name='+name+']', node)[0];
108 }
109
110 function drawFormulaSummary() {
111     openils.Util.show('formula-entry-div');
112
113     var entries = pcrud.search('acqdfe', {formula: formulaId}, {order_by:{acqdfe : 'position'}});
114     formula = pcrud.retrieve('acqdf', formulaId);
115     formula.entries(entries);
116
117     dojo.byId('formula_head').innerHTML = formula.name();
118     dojo.byId('formula_head').onclick = function() {
119         var name = prompt(localeStrings.ACQ_DISTRIB_FORMULA_NAME_PROMPT, formula.name());
120         if(name && name != formula.name()) {
121             formula.name(name);
122             pcrud = new openils.PermaCrud();
123             pcrud.update(formula);
124             dojo.byId('formula_head').innerHTML = name;
125         }
126     }
127
128     dojo.forEach(entries, function(entry) { addEntry(entry); } );
129 }
130
131 function addEntry(entry) {
132
133     if(!entryTbody) {
134         entryTbody = dojo.byId('formula-entry-tbody');
135         entryTemplate = entryTbody.removeChild(dojo.byId('formula-entry-tempate'));
136         dndSource = new dojo.dnd.Source(entryTbody);
137         dndSource.selectAll(); 
138         dndSource.deleteSelectedNodes();
139         dndSource.clearItems();
140     }
141
142     if(!entry) {
143         entry = new fieldmapper.acqdfe();
144         entry.formula(formulaId);
145         entry.item_count(1);
146         entry.owning_lib(openils.User.user.ws_ou());
147         entry.id(virtualId--);
148         entry.isnew(true);
149         formula.entries().push(entry);
150     }
151
152     var row = entryTbody.appendChild(entryTemplate.cloneNode(true));
153     row.setAttribute('entry', entry.id());
154     dndSource.insertNodes(false, [row]);
155     byName(row, 'delete').onclick = function() {
156         entry.isdeleted(true);
157         entryTbody.removeChild(row);
158         dndSource.sync();
159     };
160
161     dojo.forEach(
162         ['owning_lib', 'location', 'fund', 'circ_modifier', 'collection_code', 'item_count'],
163         function(field) {
164             new openils.widget.AutoFieldWidget({
165                 forceSync : true,
166                 fmField : field, 
167                 fmObject : entry,
168                 fmClass : 'acqdfe',
169                 labelFormat: (field == 'fund') ? fundLabelFormat : null,
170                 searchFormat: (field == 'fund') ? fundLabelFormat : null,
171                 searchFilter : (field == 'fund') ? fundSearchFilter : null,
172                 parentNode : byName(row, field),
173                 orgDefaultsToWs : true,
174                 orgLimitPerms : ['ADMIN_ACQ_DISTRIB_FORMULA'],
175                 widgetClass : (field == 'item_count') ? 'dijit.form.NumberSpinner' : null,
176                 dijitArgs : (field == 'item_count') ? {min:1, places:0} : null
177             }).build(
178                 function(w, ww) {
179                     if (field == "collection_code") {
180                         /* kludge for glitchy textbox */
181                         _collection_code_textboxes.push(w);
182                     }
183                     dojo.connect(w, 'onChange', 
184                         function(newVal) {
185                             entry[field]( newVal );
186                             entry.ischanged(true);
187                         }
188                     )
189                 }
190             );
191         }
192     );
193
194     /* For some reason (bug) the dndSource intercepts onMouseDown events
195      * that should hit dijit textboxes in our table thingy. Other dijits
196      * (buttons, filteringselects, etc) seem not to be affected.  This
197      * workaround deals with the only textboxes we have for now: the ones
198      * for the collection_code field. */
199     if (!_collection_code_kludge_active) {
200         _collection_code_kludge_active = true;
201         var original = dojo.hitch(dndSource, dndSource.onMouseDown);
202         dndSource.onMouseDown = function(e) {
203             var hits = _collection_code_textboxes.filter(
204                 function(w) {
205                     var c = dojo.coords(w.domNode);
206                     if (e.clientX >= c.x && e.clientX < c.x + c.w) {
207                         if (e.clientY >= c.y && e.clientY < c.y + c.h) {
208                             return true;
209                         }
210                     }
211                     return false;
212                 }
213             );
214
215             if (hits.length) {
216                 hits[0].focus();
217             } else {
218                 original(e);
219             }
220         };
221     }
222 }
223
224 function saveFormula() {
225     var pos = 1;
226     var updatedEntries = [];
227     var deletedEntries = [];
228
229     // remove deleted entries from consideration for collision protection
230     for(var i = 0; i < formula.entries().length; i++) {
231         if(formula.entries()[i].isdeleted())
232             deletedEntries.push(formula.entries().splice(i--, 1)[0])
233     }
234
235     // update entry positions and create temporary collision avoidance entries
236     dojo.forEach(
237         dndSource.getAllNodes(),
238         function(node) {
239
240             var entryId = node.getAttribute('entry');
241             var entry = formula.entries().filter(function(e) {return (e.id() == entryId)})[0];
242
243             if(entry.position() != pos) {
244
245                 // update the position
246                 var changedEntry = entry.clone();
247                 changedEntry.position(pos);
248                 changedEntry.ischanged(true);
249                 updatedEntries.push(changedEntry);
250
251                 // clear the virtual ID
252                 if(changedEntry.isnew())
253                     changedEntry.id(null); 
254
255                 var oldEntry = formula.entries().filter(function(e) {return (e.position() == pos)})[0];
256
257                 if(oldEntry) {
258                     // move the entry currently in that spot temporarily into negative territory
259                     var moveMe = oldEntry.clone();
260                     moveMe.ischanged(true);
261                     moveMe.position(moveMe.position() * -1); 
262                     updatedEntries.unshift(moveMe);
263                 }
264             }
265             pos++;
266         }
267     );
268
269     // finally, for every entry that changed w/o changing position
270     // throw it on the list for update
271     dojo.forEach(
272         formula.entries(),
273         function(entry) {
274             if(entry.ischanged() && !entry.isdeleted() && !entry.isnew()) {
275                 if(updatedEntries.filter(function(e) { return (e.id() == entry.id()) }).length == 0)
276                     updatedEntries.push(entry);
277             }
278         }
279     );
280
281     updatedEntries = deletedEntries.concat(updatedEntries);
282     if(updatedEntries.length) {
283         pcrud = new openils.PermaCrud();
284         try { 
285             pcrud.apply(updatedEntries);
286         } catch(E) {
287             alert('error updating: ' + E);
288             return;
289         }
290         location.href = location.href;
291     }
292 }
293
294