-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathzsugar.js
1692 lines (1457 loc) · 64.5 KB
/
zsugar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/****************************************************************************
**
** Copyright (C) 2011 Irontec SL. All rights reserved.
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
/***
* com_irontec_zsugarH
*
* This object works as handler for the zSugar Zimlet
* Interaction with zimlet is divided into:
* - A Panel Icon where Messages or Conversations can be droped. It also
* has a context menu when right clicked, and options panel when single/double clicked.
* - A Toolbar Button. It works as dropping a Msg/Conv into the Panel Icon.
* - A Context Menu Button. It works as dropping a Msg/Conv into the Panel Icon.
*
* This zimlets invokes some SugarCRM methods for Importing/Exporting data. The object
* responsible for that task is ironsugar (@see sugarestapi.js). Originally, this method
* invokation was made via SugarCRM REST API (included in version 5.5.2 and above), proxying
* all petitions through a jsp (@see redirect.jsp) which manages how data is sent to
* SugarCRM server.
*
*
*/
function com_irontec_zsugarH() {
}
com_irontec_zsugarH.prototype = new DwtDialog;
com_irontec_zsugarH.prototype = new ZmZimletBase();
com_irontec_zsugarH.prototype.constructor = com_irontec_zsugarH;
com_irontec_zsugarH.prototype.singleClicked = function() {
this.doubleClicked();
};
/***
* com_irontec_zsugarH.prototype.menuItemSelected
*
* This function works as wrapper for the Selected item in the Context
* menu of the Zimlets Panel Icon
*
* @param itemId Selected item in the context menu of the panel zimlet
*/
com_irontec_zsugarH.prototype.menuItemSelected = function(itemId) {
// Detect which Option in the Context Menu has been choosen
switch (itemId) {
/*** Show About Box ***/
case "ISUGAR_ABOUT":
var _view = new DwtComposite(this.getShell()); // Creates an empty div as a child of main shell div
_view.setSize(350, 230); // Set width and height
_view.getHtmlElement().innerHTML = this.getMessage("zsugar_aboutText");
var _dialog = new ZmDialog({title:this.getMessage("zsugar_about"), view:_view, parent:this.getShell(), standardButtons:[DwtDialog.OK_BUTTON]});
_dialog.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, function() {_dialog.popdown();}));
_dialog.popup(); //Show the dialog
break;
/*** Show Status Box (Connection to SugarCRM Status) ***/
case "ISUGAR_STATUS":
var _dialog = appCtxt.getMsgDialog(); // returns DwtMessageDialog
if (this.iscrm.sessid === false) {
var msg = this.getMessage("zsugar_notconnected")
_dialog.setMessage(msg, DwtMessageDialog.CRITICAL_STYLE);
} else {
var msg = this.getMessage("zsugar_connected")
_dialog.setMessage(msg, DwtMessageDialog.INFO_STYLE);
}
_dialog.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, function() {_dialog.popdown();})); // listens for OK button events
_dialog.popup();
break;
/*** Reconnect to SugarCRM ***/
case "ISUGAR_RELOGIN":
this._login(new AjxCallback(this, this._checkCredentials));
break;
}
};
/***
* com_irontec_zsugarH.prototype.initializeToolbar
*
* This function works as hook for adding or editing main toolbar icons
*
* It adds the zSugar button at the end of the bar, just after the
* View Icon. When this button is clicked, it will callback private
* _addSugarMsg function.
*
*/
com_irontec_zsugarH.prototype.initializeToolbar =
function(app, toolbar, controller, viewId) {
if (viewId.slice(0, ZmId.VIEW_CONVLIST.length) == ZmId.VIEW_CONVLIST ||
viewId.slice(0, ZmId.VIEW_TRAD.length) == ZmId.VIEW_TRAD ) {
// Get the index of "View" menu so we can display the button after that
var buttonIndex = 0;
for (var i = 0; i < toolbar.opList.length; i++)
if (toolbar.opList[i] == ZmOperation.VIEW_MENU || toolbar.opList[i] == ZmOperation.ACTIONS_MENU) {
buttonIndex = i + 1;
break;
}
// Configure Toolbar button
var buttonParams = {
text: this.getMessage("zsugar_bn_addSugar"),
tooltip: this.getMessage("zsugar_bn_addSugar_tooltip"),
index: buttonIndex,
image: "ISUGAR-panelIcon"
};
// Creates the button with an id and params containing the button details
var button = toolbar.createOp("SEND_SUGAR_TOOLBAR", buttonParams);
button.addSelectionListener(new AjxListener(this, this._addSugarMsg,controller));
/* If a context menu is available */
if (controller.getActionMenu){
var menu = controller.getActionMenu();
// Find the Last Menu Position
var buttonIndex = 0;
for (var i = 0; i < menu.opList.length; i++)
if (menu.opList[i] == ZmOperation.CREATE_TASK) {
buttonIndex = i + 1;
break;
}
// Add a new button
var menuParams = {
text: this.getMessage("zsugar_bn_addSugar"),
tooltip: this.getMessage("zsugar_bn_addSugar_tooltip"),
index: buttonIndex,
image: "ISUGAR-panelIcon"
};
// When this button is clicked execute callback
var mi = menu.createMenuItem("SEND_SUGAR_MENU", menuParams);
mi.addSelectionListener(new AjxListener(this, this._addSugarMsg,controller));
}
}
};
/***
* com_irontec_zsugarH.prototype.init
*
* Init the Zimlet.
*
* It adds the zSugar button at the end of context menu, just after the
* View Icon. When this button is clicked, it will callback private
* _addSugarMsg function.
*/
com_irontec_zsugarH.prototype.init = function() {
var controller = appCtxt.getCurrentController();
// Get Zimbra Major vesion
this._zimbraMajorVer = appCtxt.getSettings().getInfoResponse.version.charAt(0);
// Try to Login!
this._login(new AjxCallback(this, this._checkCredentials));
};
/***
* com_irontec_zsugarH.prototype._addSugarMsg
*
* Callback function for Toolbar and Context Menu Item
*
* This function works as wrapper for the non-panel icons. It just
* get the Message info and calls _displayMSGDialog, as it will occur
* when some Msg/Conv is droped into the Zimlet Panel Icon
*
*/
com_irontec_zsugarH.prototype._addSugarMsg = function(controller) {
var msg = controller.getMsg();
this._checkExported(msg);
};
/***
* com_irontec_zsugarH.prototype.doDrop
*
* Callback function for Zimlet Panel Icon
*
* This function works as wrapper for the panel icons. It just
* get the Message info and calls _displayMSGDialog.
*
*/
com_irontec_zsugarH.prototype.doDrop = function(obj) {
var msg = obj.srcObj;
// What kind of object are you dropping?
switch(msg.type) {
case "CONV":
// Get First message from conversation
msg = msg.getFirstHotMsg();
// Time to rock. Process this Message!
this._checkExported(msg);
break;
case "MSG":
// Time to rock. Process this Message!
this._checkExported(msg);
break;
case "APPT":
// Time to Rock. Proccess this Appointment!
this._displayAPPTDialog(msg);
break;
default:
return false;
}
};
/***
* com_irontec_szsugarH.prototype.tag
*
* Tags an Email with the proper TagLabel.
* Used to tag Exported mails.
*
*/
com_irontec_zsugarH.prototype.tag = function (msg, tagName) {
// Get Requested tag
var tagObj = appCtxt.getActiveAccount().trees.TAG.getByName(tagName);
// No tag found with that name
if(!tagObj) {
// Create tag
this.createTag(tagName);
// Get created Tag
tagObj = appCtxt.getActiveAccount().trees.TAG.getByName(tagName);
}
// Get Tag Command
var tagId = tagObj.id;
var axnType = "tag";
var soapCmd = ZmItem.SOAP_CMD[msg.type] + "Request";
var itemActionRequest = {};
itemActionRequest[soapCmd] = {_jsns:"urn:zimbraMail"};
var request = itemActionRequest[soapCmd];
var action = request.action = {};
action.id = msg.id;
action.op = axnType;
if (this._zimbraMajorVer >= "8") {
action.tn = tagName;
} else {
action.tag = tagId;
}
var params = {asyncMode: true, callback: null, jsonObj:itemActionRequest};
appCtxt.getAppController().sendRequest(params);
};
com_irontec_zsugarH.prototype.createTag = function (tagName){
// Tag Creation Command
var soapCmd = "CreateTagRequest";
// Get Tag Request Structure
var itemActionRequest = {};
itemActionRequest[soapCmd] = {_jsns:"urn:zimbraMail"};
var request = itemActionRequest[soapCmd];
// Fill Tag Structure
var tag = request.tag = {};
tag.name = tagName;
tag.color = 1; // Blue by default
// Request Creation
var params = {asyncMode: false, callback: null, jsonObj:itemActionRequest};
appCtxt.getAppController().sendRequest(params);
}
/***
* com_irontec_zsugarH.prototype._login
*
* Login Function. Tries to init a session in SugarCRM with the
* data provided in the zimlet configuration panel (single/double
* click in the zimplet panel icon).
*
*/
com_irontec_zsugarH.prototype._login = function(callback) {
var RESTprefix = '/service/v2/rest.php';
var Password;
if ( (this.getUserPropertyInfo("my_zsugar_url").value == "") || (this.getUserPropertyInfo("my_zsugar_username").value == "") || (this.getUserPropertyInfo("my_zsugar_pass")=="") ) {
appCtxt.getAppController().setStatusMsg(this.getMessage("noOptsSelected"));
return;
}
if (this.getUserPropertyInfo("my_zsugar_pass").value === undefined) this.getUserPropertyInfo("my_zsugar_pass").value = "";
if ( this.getUserPropertyInfo("my_zsugar_cleanpass").value == "false" )
Password = hex_md5(this.getUserPropertyInfo("my_zsugar_pass").value);
else
Password = this.getUserPropertyInfo("my_zsugar_pass").value;
this.iscrm = new ironsugar(this.getUserPropertyInfo("my_zsugar_url").value + RESTprefix,this.getUserPropertyInfo("my_zsugar_username").value, Password ,this);
this.iscrm.login(callback);
}
/***
* com_irontec_zsugarH.prototype.checkLoggedIn
*
* Check our actual connection status with SugarCRM and displays
* a Zimbra message.
*
* @TODO This only checks if we are logged in, but gives no feedback if not logged in ;-(
*
*/
com_irontec_zsugarH.prototype._checkCredentials = function(responsetxt) {
if (this.iscrm.sessid !== false) {
appCtxt.getAppController().setStatusMsg(
this.getMessage("zsugar_loggedin") + "<br /><small>" +
this.getMessage("zsugar_name") + " " + this.getMessage("zsugar_version") + "</small>");
} else {
appCtxt.getAppController().setStatusMsg(
this.getMessage("zsugar_notValidAuth") + "<br /><small>" +
this.getMessage("zsugar_name") + " " + this.getMessage("zsugar_version") + "<br />" +
responsetxt.substr(0, 30) + "</small>");
}
}
/***
* com_irontec_zsugarH.prototype._checkAtt
*
* Shows an awesome Zimbra Message while processing Attachments.
* This task may take some large minutes with big attachments, so we must give some kind of
* feedback.
*
*/
com_irontec_zsugarH.prototype._checkAtt = function() {
if (this.attproc == true )
appCtxt.getAppController().setStatusMsg(this.getMessage("zsugar_att_processing")); // Processing Attachments, please wait
}
/***
* com_irontec_zsugarH.prototype._checkAuth
*
* This function checks we are properly logged in into SugarCRM.
* It is called before doing any other tasks.
*
*/
com_irontec_zsugarH.prototype._execIfLogged = function(callback) {
if (this.iscrm.sessid == false) {
appCtxt.getAppController().setStatusMsg(this.getMessage("zsugar_notValidAuth")+"<br /><small>"+this.getMessage("zsugar_name")+" "+this.getMessage("zsugar_version")+"</small>");
} else {
if (callback !== undefined )
callback.run();
}
}
/***************************************************************************
**
** Messages Process
**
**************************************************************************/
/**
* com_irontec_zsugarH.prototype._checkExported
*
*
*/
com_irontec_zsugarH.prototype._checkExported = function(msg) {
// Load the message. This is required when the message is not
// predisplayed in any subpanel
this.msg = msg.load( {forceLoad: true, noTruncate: true, getHtml: true });
// Get Exported tag
var tagName = this.getUserPropertyInfo("my_zsugar_tag").value;
if ( tagName != "" ){
// Get Requested tag
var tagObj = appCtxt.getActiveAccount().trees.TAG.getByName(tagName);
// If Tag exists
if (tagObj){
// Check if message is tagged with this tag
if (msg.tagHash[tagObj.id] !== undefined){
this._dialog = appCtxt.getYesNoMsgDialog(); // returns DwtMessageDialog
var dstyle = DwtMessageDialog.INFO_STYLE; //show info status by default
var dmsg = this.getMessage("zsugar_confirmExport");
var dtit = this.getMessage("zsugar_confirmExportTitle");
// set the button listeners
this._dialog.setButtonListener(DwtDialog.YES_BUTTON, new AjxListener(this, this._confirmExport,msg)); // listens for YES button events
this._dialog.reset(); // reset dialog
this._dialog.setMessage(dmsg, dstyle);
this._dialog.setTitle(dtit);
this._dialog.popup();
return;
}
}
}
// Login and Display Dialog ;-)
this._login(new AjxCallback(this, this._displayMSGDialog, msg));
}
com_irontec_zsugarH.prototype._confirmExport = function(msg) {
this._dialog.popdown();
this._login(new AjxCallback(this, this._displayMSGDialog, msg));
}
/***
* com_irontec_zsugarH.prototype._trimDialogTitle
*
* Prevents the Dialog Title to resize the DialogBox
* Fix for large subjects #0016451
*
* @param title Original Title
* @return finalTitle Title with updated length (if required)
*/
com_irontec_zsugarH.prototype._trimDialogTitle = function(title){
var finalTitle = title;
// Avoid "undefined" title
if (!finalTitle) finalTitle = "";
// If we have to trim the title length
if (finalTitle.length > 85 ) finalTitle = finalTitle.substr(0, 82) + "...";
// Return the title, updated or not
return finalTitle;
}
/***
* com_irontec_zsugarH.prototype._displayMSGDialog
*
* This function displays a Dialog with the following Sections
* - Main Tab: Show selected address related Info from SugarCRM
* * Contact Info
* * Opportunities
* * Projects
* * Accounts
* * Leads
* * Cases
*
* - Address Selector: A combobox with Email Address retrieved
* from the selected mail.
*
* - Attachments Panel: A group of checkboxes to select which
* attachments will be exported to sCRM
*
* Pressing OK button will send us to _ArchiveEmail
* Pressing Cancel button will send us to _cancelDialog
* Pressing Change Subject button will send us to _changeSubject
*
*
* @param msg Message from which data will be displayed
*
* @TODO It's not necesary to create the Dialog each time a message
* it's dropped. It should only be created once, then update it's content
* and show it.
*/
com_irontec_zsugarH.prototype._displayMSGDialog = function(msg) {
// Check we have a valid session
if (this.iscrm.sessid == false) {
return appCtxt.getAppController().setStatusMsg(
this.getMessage("zsugar_notValidAuth") + "<br /><small>" +
this.getMessage("zsugar_name") + " " + this.getMessage("zsugar_version") + "</small>");
}
// Set Message object
this.msg = msg;
// Set Message Subject (Full, not trimmed)
this.subject = msg.subject;
// Clear Alternative Search Address
this.otherAddr = ""
// Get the Dialog Title from Message Subject
var wTitle = this._trimDialogTitle(msg.subject);
// Creates an empty div as a child of main shell div
this.pView = new DwtComposite(this.getShell());
this.pView.setSize(550, 430); // Set width and height
/*** Fill the Main Tab ***/
this.pView.getHtmlElement().innerHTML = this._loadMainView();
this.subjectButtonId = Dwt.getNextId();
this.moreOptsButtonId = Dwt.getNextId();
// Create a button to change the email subject
var subjectButton = new DwtDialog_ButtonDescriptor(this.subjectButtonId, this.getMessage("zsugar_subjectchange"),
DwtDialog.ALIGN_LEFT, new AjxCallback(this, this._changeSubject));
var moreOptsButton = new DwtDialog_ButtonDescriptor(this.moreOptsButtonId, this.getMessage("zsugar_more_options"),
DwtDialog.ALIGN_LEFT);
// pass the title, view and buttons information and create dialog box
this.pbDialog = new ZmDialog({title: wTitle, view: this.pView, parent: this.getShell(),
standardButtons: [DwtDialog.DISMISS_BUTTON, DwtDialog.OK_BUTTON],
extraButtons: [subjectButton, moreOptsButton]});
// Add a menu to the More Options button
var moreBtn = this.pbDialog.getButton(this.moreOptsButtonId);
moreBtn.setMenu(new AjxCallback(this, this._moreOptsMenu), true);
moreBtn.removeSelectionListeners();
// Link The Standard Buttons
this.pbDialog.setButtonListener(DwtDialog.DISMISS_BUTTON, new AjxListener(this, this._cancelDialog));
this.pbDialog.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, this._ArchiveEmail),msg);
// Show the Dialog
this.pbDialog.popup();
/*** Fill the Address Combobox ***/
var addrs = [];
if (msg.isSent ) var _addrs = ("TO,FROM,CC").split(",");
else var _addrs = ("FROM,TO,CC").split(",");
this.addressList = [];
var selected = true;
for (var j = 0;j<_addrs.length;j++) {
var list = msg._addrs[_addrs[j]]['_array'];
for (var k=0;k<list.length;k++) {
this.addressList.push({ email: list[k]['address'], name: list[k]['name'], dispName : list[k]['dispName']});
addrs.push(new DwtSelectOption(list[k]['address'], selected, _addrs[j]+": "+list[k]['address']));
if (selected) {
this.emailAddr = list[k]['address'];
selected = false;
}
}
}
// Add another Fake address to let the user change the search address.
addrs.push(new DwtSelectOption("OTHER",false,this.getMessage("zsugar_otheraddr")+": "+this.otherAddr));
this.cbAddresses = new DwtSelect({parent:this.pbDialog, options:addrs});
this.cbAddresses.getHtmlElement().style.width = '100%';
this.cbAddresses.addChangeListener(new AjxListener(this, this._changeEmailAddress));
var cap = document.getElementById("zsugar_selector");
cap.appendChild(this.cbAddresses.getHtmlElement());
// Create an input box for filtering
this.ibFilter = new DwtInputField({parent:this.pbDialog, size: 30, validationStyle: DwtInputField.CONTINUAL_VALIDATION, validatorCtxtObj: this, validator: this._filterResults });
this.ibFilter.setValue(this.getMessage("zsugar_enter_filter"));
this.ibFilter.addListener(DwtEvent.ONMOUSEDOWN, new AjxListener(this, this._filterClear), 1);
cap = document.getElementById("zsugar_filter");
cap.appendChild(this.ibFilter.getHtmlElement());
/*** Fill the Attachments Tab ***/
var attAr = msg.attachments;
// Delete duplicates (Zimbra bug with some files)
var attAr2 = [];
for (var z = 0; z < attAr.length; z++){
var found = false;
for (var z2 = 0; z2 < attAr2.length; z2++){
if (attAr2[z2].part === attAr[z].part) found = true;
}
if (!found) attAr2.push(attAr[z]);
}
attAr = attAr2;
// Create a Checkbox for each attachment
var ulHTML = [];
for(var k = 0;k<attAr.length;k++) {
if (!attAr[k].filename) continue; // Prevent inline attachments...
ulHTML.push('<li><label><input type="checkbox" checked="true" part="'+attAr[k].part+'" s="'+attAr[k].s+'" id="'+attAr[k].part+attAr[k].s+'" filename="'+attAr[k].filename+'"/>'+attAr[k].filename+'</label></li>');
}
document.getElementById("zsugar_atts").innerHTML = ulHTML.join("");
/*** Request SugarCRM Contact Info ***/
this._updateCRMValue();
};
/**
* com_irontec_zsugarH.prototype._filterClear
*
* Clear the Filter message when user clicks the inputbox
* if its filled with the initial message.
*/
com_irontec_zsugarH.prototype._filterClear = function(ev) {
var input = ev.dwtObj;
if (input.getEnabled() && input.getValue() == this.getMessage("zsugar_enter_filter")) {
input.clear();
}
}
/**
* com_irontec_zsugarH.prototype._filterResults
*
* Filter shown results with that match the given text
*/
com_irontec_zsugarH.prototype._filterResults = function(text) {
// This text is a hint, not a filter text
if (text == this.getMessage("zsugar_enter_filter"))
return;
// We search in lowercase for easier matching
var filterTxt = text.toLowerCase();
/* We do this in two steps.
First check the parent nodes: Contacts and Leads. Then their children, if some of
their children match, it will make the parent node visible. */
// Check all Parent nodes
var ULs = document.getElementById("zsugar_mainTab").getElementsByTagName("ul");
for (var i=0; i<ULs.length; i++) {
var label = ULs[i].getElementsByTagName("label")[0];
var labelTxt = label.lastChild.textContent;
if (filterTxt == "" || labelTxt.toLowerCase().search(filterTxt) > 0) {
label.parentNode.style.display = "block";
} else {
label.parentNode.style.display = "none";
}
// Check all Child nodes
var LIs = ULs[i].getElementsByTagName("li");
for (var j=0; j<LIs.length; j++) {
var labelLI = LIs[j].lastChild;
var labelTxtLI = labelLI.lastChild.textContent;
if (filterTxt == "" || labelTxtLI.toLowerCase().search(filterTxt) > 0) {
labelLI.parentNode.style.display = "block";
label.parentNode.style.display = "block";
} else {
labelLI.parentNode.style.display = "none";
}
}
}
}
com_irontec_zsugarH.prototype._moreOptsMenu = function() {
var button = this.pbDialog.getButton(this.moreOptsButtonId);
var menu = new DwtSelectMenu(button);
var createOpts = new DwtSelectMenuItem(menu);
createOpts.setText(this.getMessage("zsugar_createLead"));
createOpts.setImage("ISUGAR-lead");
createOpts.addSelectionListener(new AjxListener(this, this._newLeadDialog));
return menu;
}
/***
* com_irontec_zsugarH.prototype._loadMainView
*
* Dialog Container HTML Content.
* @see _displayMSGDialog for a short description of each section
*/
com_irontec_zsugarH.prototype._loadMainView = function() {
var html = [], i=0;
html[i++] = "<div id='zsugar_container' style='overflow:auto'>";
html[i++] = "<ul id='zsugar_mainTab'>";
html[i++] = this._getLiLoading();
html[i++] = "</ul></div>";
html[i++] = "<div id='zsugar_selector' style='float:left'></div>";
html[i++] = "<div id='zsugar_filter' align='right'></div>";
html[i++] = "<div id='zsugar_atts' style='overflow:auto'></div> ";
html[i++] = " <div id='zsugar_powered_logo'><a href='"+this.getMessage("zsugar_powered")+"' target='_blank'>";
html[i++] = " <img src='"+this.getResource("resources/Poweredby.png")+"' border='0' align='right'/></a></div>";
return html.join("");
};
/***
* com_irontec_zsugarH.prototype._changeEmailAddress
*
* Callback function for Address Combobox change.
* If address has changed, updates Main Tab information with SugarCRM
* data from the new email address
*/
com_irontec_zsugarH.prototype._changeEmailAddress = function(ev) {
if (this.emailAddr != ev._args.newValue) {
// Check if other address option has been selected
if ( ev._args.newValue != "OTHER" ){
// FROM, TO, or CC address has been selected
this.emailAddr = ev._args.newValue;
this._updateCRMValue();
}else{
// Other address has ben selected, show a popup to request a new address
if (!this.pOtherAddressView){
var sDialogTitle = this.getMessage("zsugar_addrchange"); // Get i18n resource string
this.pOtherAddressView = new DwtComposite(this.getShell()); // Creates an empty div as a child of main shell div
this.pOtherAddressView.setSize(250, 30); // Set width and height
var html = [], i=0;
html[i++] = "<div id='zsugar_otheraddr' style='overflow:auto'>";
html[i++] = this.getMessage("zsugar_otheraddr")+": ";
html[i++] = "<input ' type='text' value='' size='30' maxlength='50' />";
html[i++] = "</div>";
this.pOtherAddressView.getHtmlElement().innerHTML = html.join("");
// pass the title, view & buttons information to create dialog box
this.pbOtherAddressDialog = new ZmDialog({title:sDialogTitle, view:this.pOtherAddressView, parent: this.getShell(),
standardButtons:[DwtDialog.CANCEL_BUTTON, DwtDialog.OK_BUTTON]});
this.pbOtherAddressDialog.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, this._changeAddressOK));
}
var input = document.getElementById("zsugar_otheraddr").getElementsByTagName("input");
input[0].value = this.otherAddr;
this.pbOtherAddressDialog.popup(); //show the dialog
}
}
};
/***
* com_irontec_zsugarH.prototype._changeAddressOK
*
* This function will be called when User confirms the
* address update.
*
*/
com_irontec_zsugarH.prototype._changeAddressOK = function(){
// Get User input data
var input = document.getElementById("zsugar_otheraddr").getElementsByTagName("input");
this.otherAddr = input[0].value;
this.pbOtherAddressDialog.popdown();
// Update this value in Combobox FIXME
this.cbAddresses.rename("OTHER", this.getMessage("zsugar_otheraddr")+": "+this.otherAddr);
this.cbAddresses.setSelected(1); // Update selected value... Ugly hack
this.cbAddresses.setSelectedValue("OTHER");
// Search this email in SugarCRM
this.emailAddr = this.otherAddr;
this._updateCRMValue();
}
/***
* com_irontec_zsugarH.prototype._getLiLoading
*
* Shows an awesome nice looking gif animation of a progress bar
* in the Main Tab when we are fetching data from SugarCRM
*
*/
com_irontec_zsugarH.prototype._getLiLoading = function() {
return "<li id='zsugar_loading' class='center marTop'>"+this.getMessage("zsugar_loading")+"<br /><br /><img src='"+this.getResource("resources/loadingbar.gif")+"' /></li>";
};
/***
* com_irontec_zsugarH.prototype._checkBeforePOST
*
* This function will check before doing any request to SugarCRM
* that we are properly logged in and no other petition is in
* progess. Otherwise, a Zimbra message will be shown informing the
* is still another petition in course.
*/
com_irontec_zsugarH.prototype._checkBeforePOST = function() {
if (this.updating) {
appCtxt.getAppController().setStatusMsg(this.getMessage("zsugar_peddingTransaction"));
return false;
}
return true;
};
/***
* com_irontec_zsugarH.prototype._updateCRMValue
*
* This the main function used to request Contact info from selected
* email address to SugarCRM. SugarCRM response will be proccessed in
* _fetchRelationships callback
*
* @see com_irontec_zsugarH.prototype._fetchRelationships
*/
com_irontec_zsugarH.prototype._updateCRMValue = function() {
// Check we can request data to SugarCRM
if (!this._checkBeforePOST()) return;
// Show our awesome progress bar in the Main Tab!
document.getElementById("zsugar_mainTab").innerHTML = this._getLiLoading();
// Mark us as fetching data
this.updating = true;
this.cbAddresses.disable();
this.ibFilter.setEnabled(false);
this.ibFilter.setValue(this.getMessage("zsugar_enter_filter"));
// This will determine the modules we fetch data and the display order
this.modules = [];
if (this.getUserPropertyInfo("my_zsugar_opportunities").value == "true")
this.modules.push("opportunities");
if (this.getUserPropertyInfo("my_zsugar_project").value == "true")
this.modules.push("project");
if (this.getUserPropertyInfo("my_zsugar_accounts").value == "true")
this.modules.push("accounts");
if (this.getUserPropertyInfo("my_zsugar_leads").value == "true")
this.modules.push("leads");
if (this.getUserPropertyInfo("my_zsugar_cases").value == "true")
this.modules.push("cases");
this.modulesCnt = this.modules.length;
/** This represents the fetched data. Contacts + Leads **/
this.data = undefined;
var callback;
if (this.getUserPropertyInfo("my_zsugar_leads").value == "true"){
callback = this._fetchLeadsData;
}else{
callback = this._fetchRelationships;
}
/**
* Support multiple contacts.
* In version 10107 and below, we get all relationships from one query to sCRM using email address
* Since 10200, well request first ID's for contacts with that email address
* then, we requests relationships from that Contact ID, and treat them separately
**/
if ( this.iscrm.getContactsFromMail(this.emailAddr,callback) === false) {
appCtxt.getAppController().setStatusMsg(this.getMessage("zsugar_noOptsSelected"));
this.updating = false;
this.cbAddresses.enable();
this.ibFilter.setEnabled(true);
return false;
}
};
com_irontec_zsugarH.prototype._fetchLeadsData = function(data){
this.data = data;
/**
* Support for Leads as RootRelation
* From zSugar 1.4.1 we treat Leads as a Contact too
**/
if ( this.iscrm.getLeadsFromMail(this.emailAddr,this._fetchRelationships) === false) {
appCtxt.getAppController().setStatusMsg(this.getMessage("zsugar_noOptsSelected"));
this.updating = false;
this.cbAddresses.enable();
this.ibFilter.setEnabled(true);
return false;
}
};
/**
* com_irontec_zsugarH.prototype._fetchRelationships
*
* This function gets as parameter sCRM response with Contacts Info
* and fetch relationships for each contact using ironsugar.getInfoFromContact
*
* @param data Callback data
*/
com_irontec_zsugarH.prototype._fetchRelationships = function(data){
// Get Main Tab HTML Unsorted List
var oUL = document.getElementById("zsugar_mainTab");
oUL.innerHTML = ''; // Clear Tab
var oLI;
// Append Contact data to this one. This is needed because we fetch Contact and Leads
// data in separate functions and we join them here.
if (data !== undefined && data.entry_list !== undefined && this.data !== undefined)
data.entry_list = data.entry_list.concat(this.data.entry_list);
// Error treatment
switch (true){
case data.entry_list === undefined:
oLI = document.createElement("li");
if (data.number !== undefined) oLI.innerHTML = data.name;
else oLI.innerHTML = this.getMessage("zsugar_unexpected_error");
break;
case data.entry_list.length == 0:
oLI = document.createElement("li");
oLI.innerHTML = this.getMessage("zsugar_noresultsfound");
break;
}
// Show error if required
if (oLI){
oUL.appendChild(oLI);
this.updating = false;
this.cbAddresses.enable();
this.ibFilter.setEnabled(true);
return;
}
// Get Contacts
var Contacts = data.entry_list;
// TODO If we want to sort the Contact list in a specific order, it should be done here
// For each contact
for( var i=0; i < Contacts.length; i++) {
/** Create Contact Checkbox ***/
Contact = new Object();
Contact.type = Contacts[i]['module_name'];
Contact.id = Contacts[i]['name_value_list']['id']['value'];
Contact.name = Contacts[i]['name_value_list']['first_name']['value']+' '+
Contacts[i]['name_value_list']['last_name']['value'];
if (Contact.type == "Contacts")
Contact.imgtype = '<img src="'+ this.getResource('resources/Contacts.png')+'" />';
else
Contact.imgtype = '<img src="'+ this.getResource('resources/Leads.png')+'" />';
/** Create an element to show Contact info in Main Tab screen
* This Element will be another Unsorted List which items will be
* Contact's Opportunities, Accounts, Leads, Cases, and so.. */
var cUL = document.createElement("ul");
cUL.id = Contact.id;
cUL.innerHTML = "<input type='checkbox' iden='"+Contact.id+"' class='item_selector' stype='"+Contact.type.toLowerCase()+"' id='zsugar_item"+Contact.id+"' /><label for='zsugar_item"+Contact.id+"'>"+Contact.imgtype+" "+Contact.name+"</label>";
oUL.appendChild(cUL);
if (this.modulesCnt > 0)
this.iscrm.getModuleInfo(Contact.id, Contact.type, this.modules[0], 0, this._addContactInfo);
}
return true;
}
com_irontec_zsugarH.prototype._addContactInfo = function(contactID, contactModule, relCnt, data) {
// We have data in this module?
if (data.entry_list !== undefined && data.entry_list.length > 0 ){
// Get Main Tab HTML Unsorted List
var oUL = document.getElementById("zsugar_mainTab");
// Get Contact UL
var cUL = document.getElementById(contactID);
// Merge all relationships data in one Array
var rels = data.entry_list;
rels.sort(this._sortResults);
/*** Add Contact Relationships checkboxes ***/
for(var j=0;j<rels.length;j++) {
var module_name = rels[j].module_name;
var id = rels[j].name_value_list.id.value;
var iType = false;
// Determine the relationship type
switch(module_name){
case "Opportunities": var iType = '<img src="' + this.getResource('resources/Opportunities.png')+'" />'; break;
case "Project": var iType = '<img src="'+ this.getResource('resources/Project.png')+'" />'; break;
case "Accounts": var iType = '<img src="'+ this.getResource('resources/Accounts.png')+'" />'; break;
case "Leads": var iType = '<img src="'+ this.getResource('resources/Leads.png')+'" />'; break;
case "Cases": var iType = '<img src="'+ this.getResource('resources/Cases.png')+'" />'; break;
}
// Just a Sanity Check
if (iType == false) continue;
// Add the Relationship Objects to the Contact list
if (module_name == "Leads" ){
var first_name = rels[j].name_value_list.first_name.value;
var last_name = rels[j].name_value_list.last_name.value;
this._newEntity(module_name.toLowerCase(),iType,id,first_name+" "+last_name, cUL);
} else {
var name = rels[j].name_value_list.name.value;
this._newEntity(module_name.toLowerCase(),iType,id, name, cUL);
}
}
// Append a line break just for nicer Look&Feel
oUL.appendChild(document.createElement("br"));
}
// Procceed with the next relation
relCnt++;
if (relCnt < this.modulesCnt){
this.iscrm.getModuleInfo(contactID, contactModule, this.modules[relCnt], relCnt, this._addContactInfo);
}else{
this.updating = false;
this.cbAddresses.enable();
this.ibFilter.setEnabled(true);
}
}
/***
* com_irontec_zsugarH.prototype._newEntity
*
* Main Tab is a HTML Unsorted List. Each Contact, Opportunity, Account, etc data is
* a HTML List item.
*
* Since version 1.2, Main Tab is a HTML Unsorted Lists where each Conctact item becomes
* another HTML Unsorted List. Opportunities, Accounts, Leads, Cases, and so, become HTML
* List Items for the Contact Lists, instead of Main Tab List.
* Ex:
* <ul> Main Tab
* <li><ul> Contact A
* <li> Contact A - Opportunity 1 </li>
* <li> Contact A - Opportunity 2 </li>
* <li> Contact A - Account 1 </li>
* </ul>
* </li>
* <li><ul> Contact B
* <li> Contact B - Opportunity 1 </li>
* <li> Contact B - Account 1 </li>
* <li> Contact B - Lead 1 </li>
* <li> Contact B - Cases 1 </li>
* </ul>
* </li>
* </ul>
*
*/