Merge pull request #1858 from shackbarth/1854
[xtuple] / lib / enyo-x / source / views / transaction_list_container.js
1 /*jshint bitwise:true, indent:2, curly:true, eqeqeq:true, immed:true,
2 latedef:true, newcap:true, noarg:true, regexp:true, undef:true,
3 trailing:true, white:true, strict:false*/
4 /*global XT:true, XM:true, XV:true, _:true, enyo:true */
5
6 (function () {
7
8   /**
9     Expected to a have a parameter widget that contains an order and
10     a transaction date.
11
12     @name XV.TransactionListContainer
13     @extends XV.SearchContainer
14    */
15   var transactionListContainer =  /** @lends XV.TransactionListContainer# */ {
16     name: "XV.TransactionListContainer",
17     kind: "XV.SearchPanels",
18     classes: 'xv-search',
19     published: {
20       prerequisite: "",
21       notifyMessage: "",
22       list: null,
23       actions: null,
24       transactionDate: null,
25       model: null,
26       callback: null
27     },
28     events: {
29       onPrevious: "",
30       onWorkspace: ""
31     },
32     handlers: {
33       onListItemMenuTap: "showListItemMenu",
34       onParameterChange: "requery",
35       onProcessingChanged: "processingChanged",
36       onSelectionChanged: "selectionChanged",
37       onUpdateHeader: "updateHeader"
38     },
39     init: false,
40     components: [
41       {name: "parameterPanel", kind: "FittableRows", classes: "left",
42         components: [
43         {kind: "onyx.Toolbar", classes: "onyx-menu-toolbar", components: [
44           {kind: "font.TextIcon", name: "backButton",
45             content: "_back".loc(), ontap: "close", icon: "chevron-left"},
46           {kind: "onyx.MenuDecorator", onSelect: "actionSelected", components: [
47             {kind: "font.TextIcon", icon: "cog",
48               content: "_actions".loc(), name: "actionButton"},
49             {kind: "onyx.Menu", name: "actionMenu"}
50           ]}
51         ]},
52         {classes: "xv-header", name: "transactionListHeader", content: "_search".loc()},
53         {kind: "XV.ScrollableGroupbox", name: "parameterScroller", classes: "xv-search-container", fit: true}
54       ]},
55       {name: "listPanel", kind: "FittableRows", components: [
56         // the onyx-menu-toolbar class keeps the popups from being hidden
57         {kind: "onyx.MoreToolbar", name: "contentToolbar",
58           classes: "onyx-menu-toolbar", movedClass: "xv-toolbar-moved", components: [
59           {name: "rightLabel", content: "_search".loc(), classes: "xv-toolbar-label"},
60           {name: "spacer", classes: "spacer", fit: true},
61           {kind: "font.TextIcon", name: "printButton", showing: false,
62             content: "_print".loc(), ontap: "print", icon: "print"},
63           {kind: "font.TextIcon", name: "refreshButton",
64             content: "_refresh".loc(), onclick: "requery", icon: "rotate-right"},
65           {kind: "font.TextIcon", name: "postButton",
66             disabled: true, icon: "save", classes: "save",
67             content: "_post".loc(), ontap: "post"},
68           {name: "listItemMenu", kind: "onyx.Menu", floating: true,
69             onSelect: "listActionSelected", maxHeight: 500}
70         ]},
71         {name: "messageHeader", content: "", classes: ""},
72         {name: "header", classes: "xv-header", showing: false},
73         {name: "contentHeader"},
74         {name: "contentPanels", kind: "Panels", margin: 0, fit: true,
75           draggable: false, panelCount: 0, classes: "scroll-ios xv-content-panel"},
76         {kind: "onyx.Popup", name: "spinnerPopup", centered: true,
77             modal: true, floating: true, scrim: true,
78             onHide: "popupHidden", components: [
79           {kind: "onyx.Spinner"},
80           {name: "spinnerMessage", content: "_processing".loc() + "..."}
81         ]}
82       ]}
83     ],
84     actionSelected: function (inSender, inEvent) {
85       var action = inEvent.originator.action,
86         method = action.method || action.name;
87       this[method](inSender, inEvent);
88     },
89     close: function () {
90       var callback = this.getCallback();
91
92       this.doPrevious();
93       if (callback) { callback(); }
94     },
95     buildMenu: function () {
96       if (!this.getActions()) {
97         return;
98       }
99       var actionMenu = this.$.actionMenu,
100         actions = this.getActions().slice(0),
101         that = this;
102
103       // reset the menu
104       actionMenu.destroyClientControls();
105
106       // then add whatever actions are applicable
107       _.each(actions, function (action) {
108         var name = action.name,
109           prerequisite = action.prerequisite,
110           isDisabled = prerequisite ? !that[prerequisite]() : false;
111         actionMenu.createComponent({
112           name: name,
113           kind: XV.MenuItem,
114           content: action.label || ("_" + name).loc(),
115           action: action,
116           disabled: isDisabled
117         });
118
119       });
120       actionMenu.render();
121       this.$.actionButton.setShowing(actions.length);
122     },
123     create: function () {
124       this.inherited(arguments);
125       var disabled = !XT.session.privileges.get("AlterTransactionDates"),
126         parameterWidget;
127       this.setList({list: this.getList()});
128       parameterWidget = this.$.parameterWidget;
129       parameterWidget.$.transactionDate.$.input.setDisabled(disabled);
130       if (!this.getActions()) {
131         this.setActions([]);
132       }
133       this.buildMenu();
134       this.$.contentToolbar.resized();
135     },
136     fetch: function (options) {
137       if (!this.init) { return; }
138       options = options ? _.clone(options) : {};
139       var list = this.$.list,
140         query,
141         parameterWidget,
142         parameters;
143       if (!list) { return; }
144       query = list.getQuery() || {};
145       parameterWidget = this.$.parameterWidget;
146       parameters = parameterWidget && parameterWidget.getParameters ?
147         parameterWidget.getParameters() : [];
148       options.showMore = _.isBoolean(options.showMore) ?
149         options.showMore : false;
150
151       // Build conditions
152       if (parameters.length) {
153         query.parameters = parameters;
154       } else {
155         delete query.parameters;
156       }
157       list.setQuery(query);
158       list.fetch(options);
159     },
160     /**
161       Capture order changed and transaction date changed events.
162       Depends on a very specific implementation of parameter widget
163       that includes `order` and `transactionDate` parameters.
164     */
165     parameterChanged: function (inSender, inEvent) {
166       var originator = inEvent ? inEvent.originator : false,
167         name = originator ? originator.name : false,
168         that = this,
169         options,
170         value;
171
172       if (name === "transactionDate") {
173         value = originator.$.input.getValue();
174         value = XT.date.applyTimezoneOffset(value, true);
175         value = XT.date.toMidnight(value);
176         this.setTransactionDate(value);
177         this.buildMenu();
178         return;
179       } else if (name === "order") {
180         value = originator.getParameter().value;
181         this.setModel(value);
182         this.buildMenu();
183       } else if (name === "shipment") {
184         return;
185       }
186
187       options = {
188         success: function () {
189           that.selectionChanged();
190         }
191       };
192       this.fetch(options);
193     },
194     popupHidden: function (inSender, inEvent) {
195       if (!this._popupDone) {
196         inEvent.originator.show();
197       }
198     },
199     processingChanged: function (inSender, inEvent) {
200       if (inEvent.isProcessing) {
201         this.spinnerShow();
202       } else {
203         this.requery();
204         this.spinnerHide();
205       }
206     },
207     /**
208       Overload: Piggy back on existing handler for `onParameterChanged event`
209       by forwarding this requery to `parameterChanged`.
210     */
211     requery: function (inSender, inEvent) {
212       this.parameterChanged(inSender, inEvent);
213       return true;
214     },
215     /**
216       Whenever a user makes a selection, rebuild the menu
217       and set the transaction date on the selected models
218       to match what has been selected here.
219     */
220     selectionChanged: function () {
221       this.transactionDateChanged();
222       this.buildMenu();
223     },
224     /**
225       @param {Object} Options
226       @param {String} [options.list] Class name
227     */
228     setList: function (options) {
229       var component,
230         contentHeader = this.$.contentHeader,
231         list = options.list;
232
233       component = this.createComponent({
234         name: "list",
235         container: this.$.contentPanels,
236         kind: list,
237         fit: true
238       });
239       this.$.rightLabel.setContent(component.label);
240       if (component) {
241         this.createComponent({
242           name: "parameterWidget",
243           classes: "xv-parameter",
244           showSaveFilter: false,
245           showLayout: false,
246           defaultParameters: null,
247           container: this.$.parameterScroller,
248           kind: component.getParameterWidget(),
249           memoizeEnabled: false,
250           fit: true
251         });
252
253         contentHeader.destroyClientControls();
254         if (component.headerComponents) {
255           contentHeader.createComponents(component.headerComponents);
256           contentHeader.render();
257         }
258       }
259
260       this.init = true;
261       this.render();
262     },
263     spinnerHide: function () {
264       this._popupDone = true;
265       this.$.spinnerPopup.hide();
266     },
267     spinnerShow: function () {
268       this._popupDone = false;
269       this.$.spinnerPopup.show();
270     },
271     transactionDateChanged: function () {
272       var transDate = this.getTransactionDate(),
273         collection = this.$.list.getValue(),
274         i;
275
276       // Update the transaction dates on all models to match
277       // What has been selected
278       for (i = 0; i < collection.length; i++) {
279         collection.at(i).transactionDate = transDate;
280       }
281     },
282     updateHeader: function (inSender, inEvent) {
283       if (inEvent.noItemFound) {
284         this.$.transactionListHeader.setContent("_noItemFound".loc() + ": " + inEvent.data);
285
286       } else if (this.$.transactionListHeader.getContent() !== "_search".loc()) {
287         this.$.transactionListHeader.setContent("");
288       }
289     }
290   };
291
292   enyo.mixin(transactionListContainer, XV.ListMenuManagerMixin);
293   enyo.kind(transactionListContainer);
294
295 }());