#5524: make exceptions working in IE again
[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         this.app = Tine.Tinebase.appMgr.get('Calendar');
50
51         this.iMIPrecord = new Tine.Calendar.Model.iMIP(this.preparedPart.preparedData);
52         if (! Ext.isFunction(this.iMIPrecord.get('event').beginEdit)) {
53             this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
54                 responseText: Ext.util.JSON.encode(this.preparedPart.preparedData.event)
55             }));
56         }
57
58         this.initIMIPToolbar();
59
60         this.on('afterrender', this.showIMIP, this);
61
62         Tine.Calendar.iMIPDetailsPanel.superclass.initComponent.call(this);
63     },
64     
65     /**
66      * (re) prepare IMIP
67      */
68     prepareIMIP: function() {
69         this.iMIPclause.setText(this.app.i18n._('Checking Calendar Data...'));
70         
71         Tine.Calendar.iMIPPrepare(this.iMIPrecord.data, function(result, response) {
72             this.preparedPart.preparedData = result;
73             if (response.error) {
74                 // give up!
75                 this.iMIPrecord.set('preconditions', {'GENERIC': 'generic problem'});
76             } else {
77                 this.iMIPrecord = new Tine.Calendar.Model.iMIP(result);
78                 this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
79                     responseText: Ext.util.JSON.encode(result.event)
80                 }));
81             }
82             
83             this.showIMIP();
84         }, this);
85     },
86     
87     /**
88      * process IMIP
89      * 
90      * @param {String} status
91      */
92     processIMIP: function(status, range) {
93         if (this.iMIPrecord.get('event').isRecurBase() && status != 'ACCEPTED' && !range) {
94             Tine.widgets.dialog.MultiOptionsDialog.openWindow({
95                 title: this.app.i18n._('Reply to Recurring Event'),
96                 questionText: this.app.i18n._('You are responding to an recurring event. What would you like to do?'),
97                 height: 170,
98                 scope: this,
99                 options: [
100                     {text: this.app.i18n._('Respond to whole series'), name: 'series'},
101                     {text: this.app.i18n._('Do not respond'), name: 'cancel'}
102                 ],
103                 
104                 handler: function(option) {
105                     if (option != 'cancel') {
106                         this.processIMIP(status, option);
107                     }
108                 }
109             });
110             return;
111         }
112         
113         Tine.log.debug('Tine.Calendar.iMIPDetailsPanel::processIMIP status: ' + status);
114         this.getLoadMask().show();
115         
116         Tine.Calendar.iMIPProcess(this.iMIPrecord.data, status, function(result, response) {
117             this.preparedPart.preparedData = result;
118             if (response.error) {
119                 // precondition changed?  
120                 return this.prepareIMIP();
121             }
122             
123             // load result
124             this.iMIPrecord = new Tine.Calendar.Model.iMIP(result);
125             this.iMIPrecord.set('event', Tine.Calendar.backend.recordReader({
126                 responseText: Ext.util.JSON.encode(result.event)
127             }));
128             
129             this.showIMIP();
130         }, this);
131     },
132     
133     /**
134      * iMIP action toolbar
135      */
136     initIMIPToolbar: function() {
137         var singleRecordPanel = this.getSingleRecordPanel();
138         
139         this.actions = [];
140         this.statusActions = [];
141         
142         Tine.Tinebase.widgets.keyfield.StoreMgr.get('Calendar', 'attendeeStatus').each(function(status) {
143             // NEEDS-ACTION is not appropriate in iMIP context
144             if (status.id == 'NEEDS-ACTION') return;
145             
146             this.statusActions.push(new Ext.Action({
147                 text: status.get('i18nValue'),
148                 handler: this.processIMIP.createDelegate(this, [status.id]),
149                 icon: status.get('icon')
150             }));
151         }, this);
152         
153         this.actions = this.actions.concat(this.statusActions);
154         
155         // add more actions here (no spam / apply / crush / send event / ...)
156         
157         this.iMIPclause = new Ext.Toolbar.TextItem({
158             text: ''
159         });
160         this.tbar = this.actionToolbar = new Ext.Toolbar({
161             items: [{
162                     xtype: 'tbitem',
163                     cls: 'CalendarIconCls',
164                     width: 16,
165                     height: 16,
166                     style: 'margin: 3px 5px 2px 5px;'
167                 },
168                 this.iMIPclause,
169                 '->'
170             ].concat(this.actions)
171         });
172     },
173     
174     /**
175      * show/layout iMIP panel
176      */
177     showIMIP: function() {
178         var singleRecordPanel = this.getSingleRecordPanel(),
179             preconditions = this.iMIPrecord.get('preconditions'),
180             method = this.iMIPrecord.get('method'),
181             event = this.iMIPrecord.get('event'),
182             existingEvent = this.iMIPrecord.get('existing_event'),
183             myAttenderRecord = event.getMyAttenderRecord(),
184             myAttenderstatus = myAttenderRecord ? myAttenderRecord.get('status') : null;
185             
186         // show container from existing event if exists
187         if (existingEvent && existingEvent.container_id) {
188             event.set('container_id', existingEvent.container_id);
189         }
190             
191         // reset actions
192         Ext.each(this.actions, function(action) {action.setHidden(true)});
193         
194         // check preconditions
195         if (preconditions) {
196             if (preconditions.hasOwnProperty('EVENTEXISTS')) {
197                 this.iMIPclause.setText(this.app.i18n._("The event of this message does not exist"));
198             }
199             
200             else if (preconditions.hasOwnProperty('ORIGINATOR')) {
201                 // display spam box -> might be accepted by user?
202                 this.iMIPclause.setText(this.app.i18n._("The sender is not authorised to update the event"));
203             }
204             
205             else if (preconditions.hasOwnProperty('RECENT')) {
206 //            else if (preconditions.hasOwnProperty('TOPROCESS')) {
207                 this.iMIPclause.setText(this.app.i18n._("This message is already processed"));
208             }
209             
210             else if (preconditions.hasOwnProperty('ATTENDEE')) {
211                 // party crush button?
212                 this.iMIPclause.setText(this.app.i18n._("You are not an attendee of this event"));
213             } 
214             
215             else {
216                 this.iMIPclause.setText(this.app.i18n._("Unsupported message"));
217             }
218         } 
219         
220         // method specific text / actions
221         else {
222             switch (method) {
223                 case 'REQUEST':
224                     if (! myAttenderRecord) {
225                         // might happen in shared folders -> we might want to become a party crusher?
226                         this.iMIPclause.setText(this.app.i18n._("This is an event invitation for someone else."));
227                     } else if (myAttenderstatus !== 'NEEDS-ACTION') {
228                         this.iMIPclause.setText(this.app.i18n._("You have already replied to this event invitation."));
229                     } else {
230                         this.iMIPclause.setText(this.app.i18n._('You received an event invitation. Set your response to:'));
231                         Ext.each(this.statusActions, function(action) {action.setHidden(false)});
232                     }
233                     break;
234                     
235                     
236                 case 'REPLY':
237                     // Someone replied => autoprocessing atm.
238                     this.iMIPclause.setText(this.app.i18n._('An invited attendee responded to the invitation.'));
239                     break;
240                     
241                 default:            
242                     this.iMIPclause.setText(this.app.i18n._("Unsupported method"));
243                     break;
244             }
245         }
246         
247         this.getLoadMask().hide();
248         singleRecordPanel.setVisible(true);
249         singleRecordPanel.setHeight(150);
250         
251         
252         this.record = event;
253         singleRecordPanel.loadRecord(event);
254     }
255 });