distribution formula config UI repairs/enhancements
[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
16
17 function draw() {
18
19     pcrud = new openils.PermaCrud();
20
21     if(formulaId) {
22         openils.Util.hide('formula-list-div');
23         drawFormulaSummary();
24     } else {
25
26         openils.Util.hide('formula-entry-div');
27         fListGrid.onPostCreate = function(fmObject) {
28             location.href = location.href + '/' + fmObject.id();
29         }
30
31         fieldmapper.standardRequest(
32             ['open-ils.acq', 'open-ils.acq.distribution_formula.ranged.retrieve'],
33             {   async: true,
34                 params: [openils.User.authtoken],
35                 onresponse: function (r) { 
36                     var form = openils.Util.readResponse(r);
37                     formCache[form.id()] = form;
38                     fListGrid.store.newItem(form.toStoreItem());
39                 },
40                 oncomplete: function() {
41                     fListGrid.hideLoadProgressIndicator();
42                 }
43             }
44         );
45
46     }
47 }
48
49 function cloneSelectedFormula() {
50     var item = fListGrid.getSelectedItems()[0];
51     if(!item) return;
52     var formula = new fieldmapper.acqf().fromStoreItem(item);
53     fieldmapper.standardRequest(
54         ['open-ils.acq', 'open-ils.acq.distribution_formula.clone'],
55         {
56             asnyc : true,
57             params : [
58                 openils.User.authtoken, 
59                 formula.id(), 
60                 dojo.string.substitute(localeStrings.ACQ_DISTRIB_FORMULA_NAME_CLONE, [formula.name()])
61             ],
62             oncomplete : function(r) {
63                 if(r = openils.Util.readResponse(r)) {
64                     location.href = oilsBasePath + '/conify/global/acq/distribution_formula/' + r;
65                 }
66             }
67         }
68     );
69 }
70
71 openils.Util.addOnLoad(draw);
72
73 function getItemCount(rowIndex, item) {
74     if(!item) return '';
75     var form = formCache[this.grid.store.getValue(item, "id")];
76     if(!form) return 0;
77     var count = 0;
78     dojo.forEach(form.entries(), function(e) { count = count + e.item_count(); });
79     return count;
80 }
81
82 function byName(node, name) {
83     return dojo.query('[name='+name+']', node)[0];
84 }
85
86 function drawFormulaSummary() {
87     openils.Util.show('formula-entry-div');
88
89     var entries = pcrud.search('acqdfe', {formula: formulaId}, {order_by:{acqdfe : 'position'}});
90     formula = pcrud.retrieve('acqdf', formulaId);
91     formula.entries(entries);
92
93     dojo.byId('formula_head').innerHTML = formula.name();
94     dojo.byId('formula_head').onclick = function() {
95         var name = prompt(localeStrings.ACQ_DISTRIB_FORMULA_NAME_PROMPT, formula.name());
96         if(name && name != formula.name()) {
97             formula.name(name);
98             pcrud = new openils.PermaCrud();
99             pcrud.update(formula);
100             dojo.byId('formula_head').innerHTML = name;
101         }
102     }
103
104     dojo.forEach(entries, function(entry) { addEntry(entry); } );
105 }
106
107 function addEntry(entry) {
108
109     if(!entryTbody) {
110         entryTbody = dojo.byId('formula-entry-tbody');
111         entryTemplate = entryTbody.removeChild(dojo.byId('formula-entry-tempate'));
112         dndSource = new dojo.dnd.Source(entryTbody);
113         dndSource.selectAll(); 
114         dndSource.deleteSelectedNodes();
115         dndSource.clearItems();
116     }
117
118     if(!entry) {
119         entry = new fieldmapper.acqdfe();
120         entry.formula(formulaId);
121         entry.item_count(1);
122         entry.owning_lib(openils.User.user.ws_ou());
123         entry.id(virtualId--);
124         entry.isnew(true);
125         formula.entries().push(entry);
126     }
127
128     var row = entryTbody.appendChild(entryTemplate.cloneNode(true));
129     row.setAttribute('entry', entry.id());
130     dndSource.insertNodes(false, [row]);
131     byName(row, 'delete').onclick = function() {
132         entry.isdeleted(true);
133         entryTbody.removeChild(row);
134         dndSource.sync();
135     };
136
137     dojo.forEach(
138         ['owning_lib', 'location', 'item_count'],
139         function(field) {
140             new openils.widget.AutoFieldWidget({
141                 forceSync : true,
142                 fmField : field, 
143                 fmObject : entry,
144                 fmClass : 'acqdfe',
145                 parentNode : byName(row, field),
146                 orgDefaultsToWs : true,
147                 orgLimitPerms : ['ADMIN_ACQ_DISTRIB_FORMULA'],
148                 widgetClass : (field == 'item_count') ? 'dijit.form.NumberSpinner' : null,
149                 dijitArgs : (field == 'item_count') ? {min:1, places:0} : null
150             }).build(
151                 function(w, ww) {
152                     dojo.connect(w, 'onChange', 
153                         function(newVal) {
154                             entry[field]( newVal );
155                             entry.ischanged(true);
156                         }
157                     )
158                 }
159             );
160         }
161     );
162 }
163
164 function saveFormula() {
165     var pos = 1;
166     var updatedEntries = [];
167     var deletedEntries = [];
168
169     // remove deleted entries from consideration for collision protection
170     for(var i = 0; i < formula.entries().length; i++) {
171         if(formula.entries()[i].isdeleted())
172             deletedEntries.push(formula.entries().splice(i--, 1)[0])
173     }
174
175     // update entry positions and create temporary collision avoidance entries
176     dojo.forEach(
177         dndSource.getAllNodes(),
178         function(node) {
179
180             var entryId = node.getAttribute('entry');
181             var entry = formula.entries().filter(function(e) {return (e.id() == entryId)})[0];
182
183             if(entry.position() != pos) {
184
185                 // update the position
186                 var changedEntry = entry.clone();
187                 changedEntry.position(pos);
188                 changedEntry.ischanged(true);
189                 updatedEntries.push(changedEntry);
190
191                 // clear the virtual ID
192                 if(changedEntry.isnew())
193                     changedEntry.id(null); 
194
195                 var oldEntry = formula.entries().filter(function(e) {return (e.position() == pos)})[0];
196
197                 if(oldEntry) {
198                     // move the entry currently in that spot temporarily into negative territory
199                     var moveMe = oldEntry.clone();
200                     moveMe.ischanged(true);
201                     moveMe.position(moveMe.position() * -1); 
202                     updatedEntries.unshift(moveMe);
203                 }
204             }
205             pos++;
206         }
207     );
208
209     // finally, for every entry that changed w/o changing position
210     // throw it on the list for update
211     dojo.forEach(
212         formula.entries(),
213         function(entry) {
214             if(entry.ischanged() && !entry.isdeleted() && !entry.isnew()) {
215                 if(updatedEntries.filter(function(e) { return (e.id() == entry.id()) }).length == 0)
216                     updatedEntries.push(entry);
217             }
218         }
219     );
220
221     updatedEntries = deletedEntries.concat(updatedEntries);
222     if(updatedEntries.length) {
223         pcrud = new openils.PermaCrud();
224         try { 
225             pcrud.apply(updatedEntries);
226         } catch(E) {
227             alert('error updating: ' + E);
228             return;
229         }
230         location.href = location.href;
231     }
232 }
233
234