0009768: Use ModelConfig for Timetracker models
[tine20] / tine20 / Timetracker / js / TimesheetGridPanel.js
1 /*
2  * Tine 2.0
3  * 
4  * @package     Timetracker
5  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
6  * @author      Philipp Schüle <p.schuele@metaways.de>
7  * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
8  *
9  */
10  
11 Ext.namespace('Tine.Timetracker');
12
13 /**
14  * Timesheet grid panel
15  * 
16  * @namespace   Tine.Timetracker
17  * @class       Tine.Timetracker.TimesheetGridPanel
18  * @extends     Tine.widgets.grid.GridPanel
19  * 
20  * <p>Timesheet Grid Panel</p>
21  * <p><pre>
22  * </pre></p>
23  * 
24  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
25  * @author      Philipp Schüle <p.schuele@metaways.de>
26  * 
27  * @param       {Object} config
28  * @constructor
29  * Create a new Tine.Timetracker.TimesheetGridPanel
30  */
31 Tine.Timetracker.TimesheetGridPanel = Ext.extend(Tine.widgets.grid.GridPanel, {
32
33     initComponent: function() {
34         this.defaultFilters = [
35             {field: 'start_date', operator: 'within', value: 'weekThis'},
36             {field: 'account_id', operator: 'equals', value: Tine.Tinebase.registry.get('currentAccount')}
37         ];
38
39         this.initDetailsPanel();
40         
41         // only eval grants in action updater if user does not have the right to manage timeaccounts
42         this.evalGrants = ! Tine.Tinebase.common.hasRight('manage', 'Timetracker', 'timeaccounts');
43         
44         Tine.Timetracker.TimesheetGridPanel.superclass.initComponent.call(this);
45     },
46
47     /**
48      * @private
49      */
50     initDetailsPanel: function() {
51         this.detailsPanel = new Tine.widgets.grid.DetailsPanel({
52             gridpanel: this,
53             
54             // use default Tpl for default and multi view
55             defaultTpl: new Ext.XTemplate(
56                 '<div class="preview-panel-timesheet-nobreak">',
57                     '<!-- Preview timeframe -->',           
58                     '<div class="preview-panel preview-panel-timesheet-left">',
59                         '<div class="bordercorner_1"></div>',
60                         '<div class="bordercorner_2"></div>',
61                         '<div class="bordercorner_3"></div>',
62                         '<div class="bordercorner_4"></div>',
63                         '<div class="preview-panel-declaration">' /*+ this.app.i18n._('timeframe')*/ + '</div>',
64                         '<div class="preview-panel-timesheet-leftside preview-panel-left">',
65                             '<span class="preview-panel-bold">',
66                             /*'First Entry'*/'<br/>',
67                             /*'Last Entry*/'<br/>',
68                             /*'Duration*/'<br/>',
69                             '<br/>',
70                             '</span>',
71                         '</div>',
72                         '<div class="preview-panel-timesheet-rightside preview-panel-left">',
73                             '<span class="preview-panel-nonbold">',
74                             '<br/>',
75                             '<br/>',
76                             '<br/>',
77                             '<br/>',
78                             '</span>',
79                         '</div>',
80                     '</div>',
81                     '<!-- Preview summary -->',
82                     '<div class="preview-panel-timesheet-right">',
83                         '<div class="bordercorner_gray_1"></div>',
84                         '<div class="bordercorner_gray_2"></div>',
85                         '<div class="bordercorner_gray_3"></div>',
86                         '<div class="bordercorner_gray_4"></div>',
87                         '<div class="preview-panel-declaration">'/* + this.app.i18n._('summary')*/ + '</div>',
88                         '<div class="preview-panel-timesheet-leftside preview-panel-left">',
89                             '<span class="preview-panel-bold">',
90                             this.app.i18n._('Total Timesheets') + '<br/>',
91                             this.app.i18n._('Billable Timesheets') + '<br/>',
92                             this.app.i18n._('Total Time') + '<br/>',
93                             this.app.i18n._('Time of Billable Timesheets') + '<br/>',
94                             '</span>',
95                         '</div>',
96                         '<div class="preview-panel-timesheet-rightside preview-panel-left">',
97                             '<span class="preview-panel-nonbold">',
98                             '{count}<br/>',
99                             '{countbillable}<br/>',
100                             '{sum}<br/>',
101                             '{sumbillable}<br/>',
102                             '</span>',
103                         '</div>',
104                     '</div>',
105                 '</div>'            
106             ),
107             
108             showDefault: function(body) {
109                 
110                 var data = {
111                     count: this.gridpanel.store.proxy.jsonReader.jsonData.totalcount,
112                     countbillable: (this.gridpanel.store.proxy.jsonReader.jsonData.totalcountbillable) ? this.gridpanel.store.proxy.jsonReader.jsonData.totalcountbillable : 0,
113                     sum:  Tine.Tinebase.common.minutesRenderer(this.gridpanel.store.proxy.jsonReader.jsonData.totalsum),
114                     sumbillable: Tine.Tinebase.common.minutesRenderer(this.gridpanel.store.proxy.jsonReader.jsonData.totalsumbillable)
115                 };
116                 
117                 this.defaultTpl.overwrite(body, data);
118             },
119             
120             showMulti: function(sm, body) {
121                 
122                 var data = {
123                     count: sm.getCount(),
124                     countbillable: 0,
125                     sum: 0,
126                     sumbillable: 0
127                 };
128                 sm.each(function(record){
129                     
130                     data.sum = data.sum + parseInt(record.data.duration);
131                     if (record.data.is_billable_combined == '1') {
132                         data.countbillable++;
133                         data.sumbillable = data.sumbillable + parseInt(record.data.duration);
134                     }
135                 });
136                 data.sum = Tine.Tinebase.common.minutesRenderer(data.sum);
137                 data.sumbillable = Tine.Tinebase.common.minutesRenderer(data.sumbillable);
138                 
139                 this.defaultTpl.overwrite(body, data);
140             },
141             
142             tpl: new Ext.XTemplate(
143                 '<div class="preview-panel-timesheet-nobreak">',    
144                     '<!-- Preview beschreibung -->',
145                     '<div class="preview-panel preview-panel-timesheet-left">',
146                         '<div class="bordercorner_1"></div>',
147                         '<div class="bordercorner_2"></div>',
148                         '<div class="bordercorner_3"></div>',
149                         '<div class="bordercorner_4"></div>',
150                         '<div class="preview-panel-declaration">' /* + this.app.i18n._('Description') */ + '</div>',
151                         '<div class="preview-panel-timesheet-description preview-panel-left" ext:qtip="{[this.encode(values.description)]}">',
152                             '<span class="preview-panel-nonbold">',
153                              '{[this.encode(values.description, "longtext")]}',
154                             '<br/>',
155                             '</span>',
156                         '</div>',
157                     '</div>',
158                     '<!-- Preview detail-->',
159                     '<div class="preview-panel-timesheet-right">',
160                         '<div class="bordercorner_gray_1"></div>',
161                         '<div class="bordercorner_gray_2"></div>',
162                         '<div class="bordercorner_gray_3"></div>',
163                         '<div class="bordercorner_gray_4"></div>',
164                         '<div class="preview-panel-declaration">' /* + this.app.i18n._('Detail') */ + '</div>',
165                         '<div class="preview-panel-timesheet-leftside preview-panel-left">',
166                         // @todo add custom fields here
167                         /*
168                             '<span class="preview-panel-bold">',
169                             'Ansprechpartner<br/>',
170                             'Newsletter<br/>',
171                             'Ticketnummer<br/>',
172                             'Ticketsubjekt<br/>',
173                             '</span>',
174                         */
175                         '</div>',
176                         '<div class="preview-panel-timesheet-rightside preview-panel-left">',
177                             '<span class="preview-panel-nonbold">',
178                             '<br/>',
179                             '<br/>',
180                             '<br/>',
181                             '<br/>',
182                             '</span>',
183                         '</div>',
184                     '</div>',
185                 '</div>',{
186                 encode: function(value, type, prefix) {
187                     if (value) {
188                         if (type) {
189                             switch (type) {
190                                 case 'longtext':
191                                     value = Ext.util.Format.ellipsis(value, 150);
192                                     break;
193                                 default:
194                                     value += type;
195                             }
196                         } else {
197                             value = Ext.util.Format.htmlEncode(value);
198                         }
199                         
200                         var encoded = Ext.util.Format.htmlEncode(value);
201                         encoded = Ext.util.Format.nl2br(encoded);
202                         
203                         return encoded;
204                     } else {
205                         return '';
206                     }
207                 }
208             })
209         });
210     },
211
212     /**
213      * @private
214      */
215     initActions: function() {
216         this.actions_exportTimesheet = new Ext.Action({
217             text: this.app.i18n._('Export Timesheets'),
218             iconCls: 'action_export',
219             scope: this,
220             requiredGrant: 'exportGrant',
221             disabled: true,
222             allowMultiple: true,
223             actionUpdater: this.updateExportAction,
224             menu: {
225                 items: [
226                     new Tine.widgets.grid.ExportButton({
227                         text: this.app.i18n._('Export as ODS'),
228                         format: 'ods',
229                         iconCls: 'tinebase-action-export-ods',
230                         exportFunction: 'Timetracker.exportTimesheets',
231                         gridPanel: this
232                     }),
233                     new Tine.widgets.grid.ExportButton({
234                         text: this.app.i18n._('Export as CSV'),
235                         format: 'csv',
236                         iconCls: 'tinebase-action-export-csv',
237                         exportFunction: 'Timetracker.exportTimesheets',
238                         gridPanel: this
239                     }),
240                     new Tine.widgets.grid.ExportButton({
241                         text: this.app.i18n._('Export as ...'),
242                         iconCls: 'tinebase-action-export-xls',
243                         exportFunction: 'Timetracker.exportTimesheets',
244                         showExportDialog: true,
245                         gridPanel: this
246                     })
247                 ]
248             }
249         });
250         
251         // register actions in updater
252         this.actionUpdater.addActions([
253             this.actions_exportTimesheet
254         ]);
255         
256         Tine.Timetracker.TimesheetGridPanel.superclass.initActions.call(this);
257     },
258
259     updateExportAction: function(action, grants, records) {
260         var exportGrant = true;
261         Ext.each(records, function(record) {
262             var c = record.get('timeaccount_id').container_id;
263             if (c.hasOwnProperty('account_grants')) {
264                 if (! c.account_grants.exportGrant) {
265                     exportGrant = false;
266                     return false;
267                 }
268             }
269         });
270
271         var disable = ! exportGrant;
272         action.setDisabled(disable);
273         return false;
274     },
275
276     /**
277      * add custom items to action toolbar
278      * 
279      * @return {Object}
280      */
281     getActionToolbarItems: function() {
282         return [
283             Ext.apply(new Ext.Button(this.actions_exportTimesheet), {
284                 scale: 'medium',
285                 rowspan: 2,
286                 iconAlign: 'top'
287             })
288         ];
289     },
290     
291     /**
292      * add custom items to context menu
293      * 
294      * @return {Array}
295      */
296     getContextMenuItems: function() {
297         var items = [
298             '-',
299             this.actions_exportTimesheet
300         ];
301         
302         return items;
303     }
304 });