Merge branch 'master' of https://git.tine20.org:443/git/tine20
[tine20] / tine20 / Calendar / js / iMIPDetailsPanel.js
1 /*
2  * Tine 2.0
3  * 
4  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
5  * @author      Cornelius Weiss <c.weiss@metaways.de>
6  * @copyright   Copyright (c) 2011-2012 Metaways Infosystems GmbH (http://www.metaways.de)
7  */
8 Ext.ns('Tine.Calendar');
9
10 /**
11  * display panel for MIME type text/calendar
12  * 
13  * NOTE: this panel is registered on Tine.Calendar::init
14  * 
15  * @namespace   Tine.Calendar
16  * @class       Tine.Calendar.iMIPDetailsPanel
17  * @author      Cornelius Weiss <c.weiss@metaways.de>
18  * @constructor
19  */
20 Tine.Calendar.iMIPDetailsPanel = Ext.extend(Tine.Calendar.EventDetailsPanel, {
21     /**
22      * @cfg {Object} preparedPart
23      * server prepared text/calendar iMIP part 
24      */
25     preparedPart: null,
26     
27     /**
28      * @property actionToolbar
29      * @type Ext.Toolbar
30      */
31     actionToolbar: null,
32     
33     /**
34      * @property iMIPrecord
35      * @type Tine.Calendar.Model.iMIP
36      */
37     iMIPrecord: null,
38     
39     /**
40      * @property statusActions
41      * @type Array
42      */
43     statusActions:[],
44     
45     /**
46      * init this component
47      */
48     initComponent: function() {
49         try {
50             this.app = Tine.Tinebase.appMgr.get('Calendar');
51             
52             this.iMIPrecord = new Tine.Calendar.Model.iMIP(this.preparedPart.preparedData);
53             if (! Ext.isFunction(this.iMIPrecord.get('event').beginEdit)) {
54                 this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
55                     responseText: Ext.util.JSON.encode(this.preparedPart.preparedData.event)
56                 }));
57             }
58             
59             this.initIMIPToolbar();
60             
61             this.on('afterrender', this.showIMIP, this);
62                 
63             Tine.Calendar.iMIPDetailsPanel.superclass.initComponent.call(this);
64         } catch (e) {
65             Tine.log.error('Tine.Calendar.iMIPDetailsPanel::initComponent');
66             Tine.log.error(e.stack ? e.stack : e);
67         }
68     },
69     
70     /**
71      * (re) prepare IMIP
72      */
73     prepareIMIP: function() {
74         this.iMIPclause.setText(this.app.i18n._('Checking Calendar Data...'));
75         
76         Tine.Calendar.iMIPPrepare(this.iMIPrecord.data, function(result, response) {
77             this.preparedPart.preparedData = result;
78             if (response.error) {
79                 // give up!
80                 this.iMIPrecord.set('preconditions', {'GENERIC': 'generic problem'});
81             } else {
82                 this.iMIPrecord = new Tine.Calendar.Model.iMIP(result);
83                 this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
84                     responseText: Ext.util.JSON.encode(result.event)
85                 }));
86             }
87             
88             this.showIMIP();
89         }, this);
90     },
91     
92     /**
93      * process IMIP
94      * 
95      * @param {String} status
96      */
97     processIMIP: function(status, range) {
98         if (this.iMIPrecord.get('event').isRecurBase() && status != 'ACCEPTED' && !range) {
99             Tine.widgets.dialog.MultiOptionsDialog.openWindow({
100                 title: this.app.i18n._('Reply to Recurring Event'),
101                 questionText: this.app.i18n._('You are responding to an recurring event. What would you like to do?'),
102                 height: 170,
103                 scope: this,
104                 options: [
105                     {text: this.app.i18n._('Responde to whole series'), name: 'series'},
106                     {text: this.app.i18n._('Do not responde'), name: 'cancel'}
107                 ],
108                 
109                 handler: function(option) {
110                     if (option != 'cancel') {
111                         this.processIMIP(status, option);
112                     }
113                 }
114             });
115             return;
116         }
117         
118         Tine.log.debug('Tine.Calendar.iMIPDetailsPanel::processIMIP status: ' + status);
119         this.getLoadMask().show();
120         
121         Tine.Calendar.iMIPProcess(this.iMIPrecord.data, status, function(result, response) {
122             this.preparedPart.preparedData = result;
123             if (response.error) {
124                 // precondition changed?  
125                 return this.prepareIMIP();
126             }
127             
128             // load result
129             this.iMIPrecord = new Tine.Calendar.Model.iMIP(result);
130             this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
131                 responseText: Ext.util.JSON.encode(result.event)
132             }));
133             
134             this.showIMIP();
135         }, this);
136     },
137     
138     /**
139      * iMIP action toolbar
140      */
141     initIMIPToolbar: function() {
142         var singleRecordPanel = this.getSingleRecordPanel();
143         
144         this.actions = [];
145         this.statusActions = [];
146         
147         Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeStatus').each(function(status) {
148             // NEEDS-ACTION is not appropriate in iMIP context
149             if (status.id == 'NEEDS-ACTION') return;
150             
151             this.statusActions.push(new Ext.Action({
152                 text: status.get('i18nValue'),
153                 handler: this.processIMIP.createDelegate(this, [status.id]),
154                 icon: status.get('icon')
155             }));
156         }, this);
157         
158         this.actions = this.actions.concat(this.statusActions);
159         
160         // add more actions here (no spam / apply / crush / send event / ...)
161         
162         this.iMIPclause = new Ext.Toolbar.TextItem({
163             text: ''
164         });
165         this.tbar = this.actionToolbar = new Ext.Toolbar({
166             items: [{
167                     xtype: 'tbitem',
168                     cls: 'CalendarIconCls',
169                     width: 16,
170                     height: 16,
171                     style: 'margin: 3px 5px 2px 5px;'
172                 },
173                 this.iMIPclause,
174                 '->'
175             ].concat(this.actions)
176         });
177     },
178     
179     /**
180      * show/layout iMIP panel
181      */
182     showIMIP: function() {
183         try {
184             var singleRecordPanel = this.getSingleRecordPanel(),
185                 preconditions = this.iMIPrecord.get('preconditions'),
186                 method = this.iMIPrecord.get('method'),
187                 event = this.iMIPrecord.get('event'),
188                 existingEvent = this.iMIPrecord.get('existing_event'),
189                 myAttenderRecord = event.getMyAttenderRecord(),
190                 myAttenderstatus = myAttenderRecord ? myAttenderRecord.get('status') : null;
191                 
192             // show container from existing event if exists
193             if (existingEvent && existingEvent.container_id) {
194                 event.set('container_id', existingEvent.container_id);
195             }
196                 
197             // reset actions
198             Ext.each(this.actions, function(action) {action.setHidden(true)});
199             
200             // check preconditions
201             if (preconditions) {
202                 if (preconditions.hasOwnProperty('EVENTEXISTS')) {
203                     this.iMIPclause.setText(this.app.i18n._("The event of this message does not exist"));
204                 }
205                 
206                 else if (preconditions.hasOwnProperty('ORIGINATOR')) {
207                     // display spam box -> might be accepted by user?
208                     this.iMIPclause.setText(this.app.i18n._("The sender is not authorised to update the event"));
209                 }
210                 
211                 else if (preconditions.hasOwnProperty('RECENT')) {
212     //            else if (preconditions.hasOwnProperty('TOPROCESS')) {
213                     this.iMIPclause.setText(this.app.i18n._("This message is already processed"));
214                 }
215                 
216                 else if (preconditions.hasOwnProperty('ATTENDEE')) {
217                     // party crush button?
218                     this.iMIPclause.setText(this.app.i18n._("You are not an attendee of this event"));
219                 } 
220                 
221                 else {
222                     this.iMIPclause.setText(this.app.i18n._("Unsupported message"));
223                 }
224             } 
225             
226             // method specific text / actions
227             else {
228                 switch (method) {
229                     case 'REQUEST':
230                         if (! myAttenderRecord) {
231                             // might happen in shared folders -> we might want to become a party crusher?
232                             this.iMIPclause.setText(this.app.i18n._("This is an event invitation for someone else."));
233                         } else if (myAttenderstatus !== 'NEEDS-ACTION') {
234                             this.iMIPclause.setText(this.app.i18n._("You have already replied to this event invitation."));
235                         } else {
236                             this.iMIPclause.setText(this.app.i18n._('You received an event invitation. Set your response to:'));
237                             Ext.each(this.statusActions, function(action) {action.setHidden(false)});
238                         }
239                         break;
240                         
241                         
242                     case 'REPLY':
243                         // Someone replied => autoprocessing atm.
244                         this.iMIPclause.setText(this.app.i18n._('An invited attendee responded to the invitation.'));
245                         break;
246                         
247                     default:            
248                         this.iMIPclause.setText(this.app.i18n._("Unsupported method"));
249                         break;
250                 }
251             }
252             
253             this.getLoadMask().hide();
254             singleRecordPanel.setVisible(true);
255             singleRecordPanel.setHeight(150);
256             
257             
258             this.record = event;
259             singleRecordPanel.loadRecord(event);
260         } catch (e) {
261             Tine.log.error('Tine.Calendar.iMIPDetailsPanel::showIMIP');
262             Tine.log.error(e.stack ? e.stack : e);
263             
264             singleRecordPanel.setVisible(false);
265         }
266     }
267 });