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