1$(document).ready(function(){
2 $("#replymessage,#replynote").focus(function () {
3 var gotValidResponse = false;
4 WHMCS.http.jqClient.post("supporttickets.php", { action: "makingreply", id: ticketid, token: csrfToken },
5 function(data){
6 gotValidResponse = true;
7 if (data.isReplying) {
8 $("#replyingAdminMsg").html(data.replyingMsg);
9 $("#replyingAdminMsg").removeClass('alert-warning').addClass('alert-info');
10 if (!$("#replyingAdminMsg").is(":visible")) {
11 $("#replyingAdminMsg").hide().removeClass('hidden').slideDown();
12 }
13 } else {
14 $("#replyingAdminMsg").slideUp();
15 }
16 }, "json")
17 .always(function() {
18 if (!gotValidResponse) {
19 $("#replyingAdminMsg").html('Session Expired. Please <a href="javascript:location.reload()" class="alert-link">reload the page</a> before continuing.');
20 $("#replyingAdminMsg").removeClass('alert-info').addClass('alert-warning');
21 if (!$("#replyingAdminMsg").is(":visible")) {
22 $("#replyingAdminMsg").hide().removeClass('hidden').slideDown();
23 }
24 } else if ($("#replyingAdminMsg").hasClass('alert-warning')) {
25 $("#replyingAdminMsg").slideUp();
26 }
27 });
28 return false;
29 });
30
31 loadTicketCcs();
32
33 $('#selectUserid').on('change', function() {
34 loadTicketCcs();
35 });
36
37 $("#frmAddTicketReply").submit(function (e, options) {
38 options = options || {};
39
40 var formSubmitButton = $('#btnPostReply'),
41 thisElement = jQuery(this),
42 swapClass = 'fa-reply';
43
44 formSubmitButton.attr("disabled", "disabled");
45 formSubmitButton.find('i').removeClass(swapClass).addClass("fa-spinner fa-spin").end();
46
47 if (options.skipValidation) {
48 return true;
49 }
50
51 e.preventDefault();
52
53 post_validate_changes_and_submit(
54 thisElement,
55 formSubmitButton,
56 swapClass
57 );
58 });
59
60 $('#frmTicketOptions').submit(function(e, options) {
61 options = options || {};
62
63 var formSubmitButton = $('#btnSaveChanges'),
64 thisElement = $(this),
65 swapClass = 'fa-save';
66
67 formSubmitButton.attr('disabled', 'disabled');
68 formSubmitButton.find('i').removeClass(swapClass).addClass('fa-spinner fa-spin').end();
69
70 if (options.skipValidation) {
71 return true;
72 }
73
74 e.preventDefault();
75
76 post_validate_changes_and_submit(
77 thisElement,
78 formSubmitButton,
79 swapClass
80 );
81
82
83 });
84
85 $("#frmAddTicketNote").submit(function (e, options) {
86 options = options || {};
87
88 var formSubmitButton = $('#btnAddNote'),
89 thisElement = $(this),
90 swapClass = 'fa-reply';
91
92 formSubmitButton.attr('disabled', 'disabled');
93 formSubmitButton.find('i').removeClass(swapClass).addClass('fa-spinner fa-spin').end();
94
95 if (options.skipValidation) {
96 return true;
97 }
98
99 e.preventDefault();
100
101 post_validate_changes_and_submit(
102 thisElement,
103 formSubmitButton,
104 swapClass
105 );
106 });
107
108 $(window).unload( function () {
109 WHMCS.http.jqClient.post("supporttickets.php", { action: "endreply", id: ticketid, token: csrfToken });
110 });
111 $("#insertpredef, #btnInsertPredefinedReply").click(function () {
112 $("#prerepliescontainer, #ticketPredefinedReplies").fadeToggle();
113 return false;
114 });
115 /**
116 * The following is in place for custom admin themes to facilitate migration.
117 * Deprecated - will be removed in a future version
118 */
119 $("#addfileupload").click(function () {
120 $("#fileuploads").append("<input type=\"file\" name=\"attachments[]\" class=\"form-control top-margin-5\">");
121 return false;
122 });
123 $('.add-file-upload').click(function () {
124 var moreId = $(this).data('more-id');
125 $('#' + moreId).append("<input type=\"file\" name=\"attachments[]\" class=\"form-control top-margin-5\">");
126 return false;
127 });
128 $('#btnAttachFiles').click(function () {
129 $('#ticketReplyAttachments').fadeToggle();
130 });
131 $('#btnNoteAttachFiles').click(function () {
132 $('#ticketNoteAttachments').fadeToggle();
133 });
134 $('#btnAddBillingEntry').click(function (e) {
135 e.preventDefault();
136 $('#ticketReplyBillingEntry').fadeToggle();
137 });
138 $('#btnInsertKbArticle').click(function (e) {
139 e.preventDefault();
140 window.open('supportticketskbarticle.php','kbartwnd','width=500,height=400,scrollbars=yes');
141 });
142 $("#ticketstatus").change(function (e, options) {
143 var currentStatus = $('#currentStatus'),
144 skip = 0;
145
146 options = options || {};
147
148 if (options.skipValidation) {
149 skip = 1;
150 }
151
152 post_validate_and_change(
153 {
154 action: "changestatus",
155 id: ticketid,
156 status: this.options[this.selectedIndex].text,
157 currentStatus: currentStatus.val(),
158 lastReplyId: $('#lastReplyId').val(),
159 currentSubject: $('#currentSubject').val(),
160 currentCc: $('#currentCc').val(),
161 currentUserId: $('#currentUserId').val(),
162 currentDepartmentId: $('#currentdeptid').val(),
163 currentFlag: $('#currentflagto').val(),
164 currentPriority: $('#currentpriority').val(),
165 skip: skip,
166 token: csrfToken
167 },
168 currentStatus,
169 this.options[this.selectedIndex].text,
170 $(this)
171 );
172 });
173 $("#predefq").keypress(function(e){
174 // Stop form submit
175 if(e.which === 13){
176 return false;
177 }
178 });
179 $("#predefq").keyup(function () {
180 var intellisearchlength = $("#predefq").val().length;
181 if (intellisearchlength>2) {
182 WHMCS.http.jqClient.post("supporttickets.php", { action: "loadpredefinedreplies", predefq: $("#predefq").val(), token: csrfToken },
183 function(data){
184 $("#prerepliescontent").html(data);
185 });
186 }
187 });
188
189 jQuery("#watch-ticket").click(function() {
190 var ticketId = jQuery(this).data('ticket-id'),
191 adminId = jQuery(this).data('admin-id'),
192 adminFullName = jQuery(this).data('admin-full-name'),
193 type = jQuery(this).attr('data-type');
194
195 WHMCS.http.jqClient.post(
196 'supporttickets.php', {
197 action: 'watcher_update',
198 ticket_id: ticketId,
199 type: type,
200 token: csrfToken
201 },
202 function (data) {
203 var self = jQuery("#watch-ticket");
204 var adminElementId = 'ticket-watcher-' + adminId;
205 var $ticketWatcher = jQuery('#' + adminElementId);
206
207 if (data == 1 && type == 'watch') {
208 jQuery(self).attr('data-type', 'unwatch');
209 jQuery(self).addClass('btn-danger').removeClass('btn-info');
210 jQuery(self).html(unwatch_ticket);
211
212 // Hide the 'None' watcher.
213 jQuery('#ticket-watcher-0').hide();
214
215 if ($ticketWatcher.length > 0) {
216 $ticketWatcher.show();
217 } else {
218 jQuery('#ticketWatchers').append('<li id="' + adminElementId + '">' + adminFullName + '<li>');
219 }
220 }
221 if (data == 1 && type == 'unwatch') {
222 jQuery(self).attr('data-type', 'watch');
223 jQuery(self).addClass('btn-info').removeClass('btn-danger');
224 jQuery(self).html(watch_ticket);
225
226 $ticketWatcher.hide();
227
228 // Remove any empty list items.
229 jQuery('#ticketWatchers li:empty').remove();
230
231 // Display 'None' is nothing is visible under Ticket Watchers.
232 if (jQuery("#ticketWatchers").children(":visible").length === 0) {
233 jQuery('#ticket-watcher-0').removeClass('hidden')
234 .show();
235 }
236 }
237 }
238 );
239 });
240
241
242 jQuery(".sidebar-ticket-ajax").on('change', function(e, options) {
243 var self = $(this),
244 val = self.data('update-type'),
245 currentValue = $('#current' + val),
246 skip = 0;
247
248 options = options || {};
249
250 if (options.skipValidation) {
251 skip = 1;
252 }
253
254 post_validate_and_change(
255 {
256 action: "viewticket",
257 id: ticketid,
258 updateticket: val,
259 value: self.val(),
260 currentValue: currentValue.val(),
261 lastReplyId: $('#lastReplyId').val(),
262 currentSubject: $('#currentSubject').val(),
263 currentCc: $('#currentCc').val(),
264 currentUserId: $('#currentUserId').val(),
265 currentDepartmentId: $('#currentdeptid').val(),
266 currentFlag: $('#currentflagto').val(),
267 currentPriority: $('#currentpriority').val(),
268 currentStatus: $('#currentStatus').val(),
269 skip: skip,
270 token: csrfToken
271 },
272 currentValue,
273 self.val(),
274 self
275 );
276 });
277
278 jQuery('#btnSelectRelatedService').on('click', function() {
279 var expandable = jQuery(this).data('expandable');
280 jQuery(this).addClass('disabled').prop('disabled', true);
281 expandRelServices(function() {
282 jQuery('#relatedservicestbl').find('.related-service').removeClass('hidden');
283 jQuery('#btnSelectRelatedService').hide();
284 jQuery('#btnSelectRelatedServiceSave').removeClass('hidden').show().removeClass('disabled').prop('disabled', false);
285 jQuery('#btnSelectRelatedServiceCancel').removeClass('hidden').show().removeClass('disabled').prop('disabled', false);
286 });
287 });
288
289 jQuery('#btnRelatedServiceExpand').on('click', function() {
290 if (jQuery(this).prop('disabled')) {
291 return;
292 }
293 expandRelServices();
294 });
295
296 jQuery('#btnSelectRelatedServiceSave').on('click', function() {
297 var table = jQuery('#relatedservicestbl'),
298 selectedService = table.find('input[name="related_service[]"]:checked'),
299 type = null,
300 id = 0;
301
302 if (selectedService.length === 0) {
303 jQuery.growl.warning(
304 {
305 title: '',
306 message: 'You must select a service'
307 }
308 );
309 return false;
310 }
311
312 type = selectedService.data('type');
313 id = selectedService.val();
314
315 jQuery(this).prop('disabled', true).addClass('disabled');
316 jQuery('#btnSelectRelatedServiceCancel').prop('disabled', true).addClass('disabled');
317
318 let saveRequestedService = () => {
319 let dfd = jQuery.Deferred();
320
321 WHMCS.http.jqClient.jsonPost(
322 {
323 url: WHMCS.adminUtils.getAdminRouteUrl(
324 `/support/ticket/${ticketid}/client/${userid}/services/save`
325 ),
326 data: {
327 token: csrfToken,
328 type: type,
329 id: id
330 },
331 success: function (data) {
332 if (data.success) {
333 dfd.resolve(data);
334 } else {
335 dfd.fail(data);
336 }
337 }
338 }
339 );
340
341 return dfd.promise();
342 }
343
344 let getDisplayServices = () => {
345 let dfd = jQuery.Deferred();
346
347 WHMCS.http.jqClient.jsonPost(
348 {
349 url: WHMCS.adminUtils.getAdminRouteUrl(
350 `/support/ticket/${ticketid}/client/${userid}/services`
351 ),
352 data: {
353 token: csrfToken,
354 type: type,
355 skipTen: false,
356 showTen: true
357 },
358 success: function (data) {
359 dfd.resolve(data);
360 }
361 }
362 );
363
364 return dfd.promise();
365 }
366
367 jQuery.when(
368 saveRequestedService()
369 ).then(
370 data => {
371 jQuery.growl.notice({title: '', message: data.successMessage});
372
373 let tableRow = selectedService.closest('tr');
374 table.find('.rowhighlight').removeClass('rowhighlight');
375 table.find('th').closest('tr').after(tableRow);
376 tableRow.attr('data-original', 'true').addClass('rowhighlight');
377
378 return getDisplayServices();
379 },
380 data => {
381 jQuery.growl.warning({title: '', message: data.errorMessage});
382 }
383 ).then(
384 data => {
385 table.find('.related-service').addClass('hidden');
386 table.find('tr')
387 .splice(2)
388 .forEach(row => row.remove());
389
390 jQuery('#btnSelectRelatedServiceSave').hide();
391 jQuery('#btnSelectRelatedServiceCancel').hide();
392 jQuery('#btnSelectRelatedService').prop('disabled', false).show()
393 .removeClass('disabled hidden');
394 jQuery('#btnRelatedServiceExpand').prop('disabled', false).removeClass('disabled');
395
396 table.find('tbody').append(data.body);
397 }
398 );
399 });
400
401 jQuery('#btnSelectRelatedServiceCancel').on('click', function() {
402 var table = jQuery('#relatedservicestbl');
403 table.find('.related-service').addClass('hidden');
404 jQuery(this).hide();
405 jQuery('#btnSelectRelatedServiceSave').hide().addClass('hidden');
406 jQuery('#btnSelectRelatedService').show().prop('disabled', false).removeClass('disabled');;
407 if (!jQuery('#btnRelatedServiceExpand').hasClass('disabled')) {
408 table.find('tr[data-original!="true"]').remove();
409 jQuery('#btnRelatedServiceExpand').prop('disabled', false).removeClass('disabled');
410 }
411 });
412
413 jQuery(document).on('click', '#relatedservicestbl tr', function() {
414 if(!jQuery('#relatedservicestbl .related-service').hasClass('hidden')) {
415 jQuery(this).find('input').prop('checked', true);
416 }
417 });
418
419 jQuery(document).on('click', '#relatedservicestbl tr a', function(e) {
420 e.stopPropagation();
421 });
422
423});
424
425var replyingAdminMessage = $("#replyingAdminMsg");
426
427function doDeleteReply(id) {
428 if (confirm(langdelreplysure)) {
429 window.location='supporttickets.php?action=viewticket&id='+ticketid+'&sub=del&idsd='+id+'&token='+csrfToken;
430 }
431}
432function doDeleteTicket() {
433 if (confirm(langdelticketsure)) {
434 window.location='supporttickets.php?sub=deleteticket&id='+ticketid+'&token='+csrfToken;
435 }
436}
437function doDeleteNote(id) {
438 if (confirm(langdelnotesure)) {
439 window.location='supporttickets.php?action=viewticket&id='+ticketid+'&sub=delnote&idsd='+id+'&token='+csrfToken;
440 }
441}
442function loadTab(target,type,offset) {
443 WHMCS.http.jqClient.post("supporttickets.php", { action: "get" + type, id: ticketid, userid: userid, target: target, offset: offset, token: csrfToken },
444 function (data) {
445 if ($("#tab" + target + "box #tab_content").length > 0) {
446 $("#tab" + target + "box #tab_content").html(data);
447 } else {
448 $("#tab" + target).html(data);
449 }
450 });
451}
452function expandRelServices(completeFunction) {
453 var button = jQuery('#btnRelatedServiceExpand');
454 if (button.hasClass('disabled')) {
455 if (completeFunction instanceof Function) {
456 completeFunction();
457 }
458 return;
459 }
460
461 button.addClass('disabled').prop('disabled', true).find('span').toggleClass('hidden');
462 WHMCS.http.jqClient.jsonPost(
463 {
464 url: WHMCS.adminUtils.getAdminRouteUrl('/support/ticket/' + ticketid + '/client/' + userid + '/services'),
465 data: {
466 token: csrfToken
467 },
468 success: function(data) {
469 jQuery('#relatedservicestbl').find('tbody').append(data.body);
470 },
471 always: function() {
472 button.find('span').toggleClass('hidden');
473 if (completeFunction instanceof Function) {
474 completeFunction();
475 }
476 }
477 }
478 );
479}
480
481function editTicket(id) {
482 $(".editbtns"+id+" input[type=button]").prop('disabled', true);
483 $(".editbtns"+id+" img.saveSpinner").show();
484 WHMCS.http.jqClient.post("supporttickets.php", { action: "getmsg", ref: id, token: csrfToken })
485 .done(function(data){
486 $(".editbtns"+id).toggle();
487 $("#content"+id+" div.message").hide();
488 $("#content"+id+" div.message").after('<textarea rows="15" style="width:99%" id="ticketedit'+id+'">'+langloading+'</textarea>');
489 $("#ticketedit"+id).val(data);
490 })
491 .always(function(){
492 $(".editbtns"+id+" img.saveSpinner").hide();
493 $(".editbtns"+id+" input[type=button]").removeProp('disabled');
494 });
495}
496function editTicketCancel(id) {
497 $("#ticketedit"+id).hide();
498 $("#content"+id+" div.message").show();
499 $(".editbtns"+id+" input[type=button]").prop('disabled', false);
500 $(".editbtns"+id).toggle();
501}
502function editTicketSave(id) {
503 $(".editbtns"+id+" input[type=button]").prop('disabled', true);
504 $("#ticketedit"+id).prop('disabled', true);
505 $(".editbtns"+id+" img.saveSpinner").show();
506 WHMCS.http.jqClient.post("supporttickets.php", { action: "updatereply", ref: id, text: $("#ticketedit"+id).val(), token: csrfToken })
507 .done(function(data){
508 $("#content"+id+" div.message").html(data);
509 })
510 .always(function(){
511 $(".editbtns"+id+" img.saveSpinner").hide();
512 editTicketCancel(id);
513 });
514}
515function quoteTicket(id,ids) {
516 $(".tab").removeClass("tabselected");
517 $("#tab0").addClass("tabselected");
518 $(".tabbox").hide();
519 $("#tab0box").show();
520 WHMCS.http.jqClient.post("supporttickets.php", { action: "getquotedtext", id: id, ids: ids, token: csrfToken },
521 function(data){
522 $("#replymessage").val(data+"\n\n"+$("#replymessage").val());
523 });
524 return false;
525}
526function selectpredefcat(catid) {
527 WHMCS.http.jqClient.post("supporttickets.php", { action: "loadpredefinedreplies", cat: catid, token: csrfToken },
528 function(data){
529 $("#prerepliescontent").html(data);
530 });
531}
532function selectpredefreply(artid) {
533 WHMCS.http.jqClient.post("supporttickets.php", { action: "getpredefinedreply", id: artid, token: csrfToken },
534 function(data){
535 $("#replymessage").addToReply(data);
536 });
537 $("#prerepliescontainer, #ticketPredefinedReplies").fadeOut();
538}
539
540function post_validate_and_change(vars, updateElement, newValue, self)
541{
542 var gotValidResponse = false,
543 responseMsg = '',
544 done = false;
545 WHMCS.http.jqClient.post(
546 "supporttickets.php",
547 vars,
548 function(data){
549 gotValidResponse = true;
550 if (typeof data.changes !== 'undefined') {
551 if (data.changes === true) {
552 // there have been changes
553 swal({
554 title: changesTitle,
555 text: changes + "\r\n\r\n" + data.changeList,
556 icon: 'info',
557 dangerMode: true,
558 showCancelButton: true,
559 confirmButtonColor: "#DD6B55",
560 confirmButtonText: continueText
561 },
562 function(){
563 replyingAdminMessage.slideUp();
564 self.trigger('change', { 'skipValidation': true });
565 }
566 )
567 } else {
568 done = true;
569 updateElement.val(newValue);
570 jQuery('#frmTicketOptions').find('[name=' + self.data('update-type') + ']').val(newValue);
571 jQuery.growl.notice({ title: "", message: "Saved successfully!" });
572 }
573 } else {
574 // access denied
575 responseMsg = 'Access Denied. Please try again.';
576 }
577 },
578 "json"
579 )
580 .always(function()
581 {
582 if (!gotValidResponse) {
583 responseMsg = 'Session Expired. Please <a href="javascript:location.reload()" class="alert-link">reload the page</a> before continuing.';
584 }
585
586 if (responseMsg) {
587 replyingAdminMessage.html(responseMsg);
588 replyingAdminMessage.removeClass('alert-info').addClass('alert-warning');
589 if (!replyingAdminMessage.is(":visible")) {
590 $("#replyingAdminMsg").hide().removeClass('hidden').slideDown();
591 }
592 $('html, body').animate({
593 scrollTop: replyingAdminMessage.offset().top - 15
594 }, 400);
595 } else {
596 replyingAdminMessage.slideUp();
597 }
598 }
599 );
600 return done;
601}
602
603function post_validate_changes_and_submit(form, submitButton, swapClass)
604{
605 var gotValidResponse = false,
606 allowPost = false,
607 responseMsg = '';
608
609 replyingAdminMessage = $("#replyingAdminMsg");
610
611 WHMCS.http.jqClient.post(
612 'supporttickets.php',
613 {
614 action: 'validatereply',
615 id: ticketid,
616 status: $("#ticketstatus").val(),
617 lastReplyId: $('#lastReplyId').val(),
618 currentSubject: $('#currentSubject').val(),
619 currentCc: $('#currentCc').val(),
620 currentUserId: $('#currentUserId').val(),
621 currentDepartmentId: $('#currentdeptid').val(),
622 currentFlag: $('#currentflagto').val(),
623 currentPriority: $('#currentpriority').val(),
624 currentStatus: $('#currentStatus').val(),
625 token: csrfToken
626 },
627 function(data){
628 gotValidResponse = true;
629 if (data.valid) {
630 if (data.changes) {
631 // there have been ticket changes
632 allowPost = false;
633 swal({
634 title: changesTitle,
635 text: changes + "\r\n\r\n" + data.changeList,
636 icon: 'info',
637 dangerMode: true,
638 showCancelButton: true,
639 confirmButtonColor: "#DD6B55",
640 confirmButtonText: continueText
641 },
642 function(){
643 replyingAdminMessage.slideUp();
644 form.attr('data-no-clear', 'false');
645 form.trigger('submit', { 'skipValidation': true });
646 }
647 )
648 } else {
649 allowPost = true;
650 }
651 } else {
652 // access denied
653 responseMsg = 'Access Denied. Please try again.';
654 }
655 }, "json")
656 .always(function() {
657 if (!gotValidResponse) {
658 responseMsg = 'Session Expired. Please <a href="javascript:location.reload()" class="alert-link">reload the page</a> before continuing.';
659 }
660
661 if (responseMsg) {
662 allowPost = false;
663 replyingAdminMessage.html(responseMsg);
664 replyingAdminMessage.removeClass('alert-info').addClass('alert-warning');
665 if (!replyingAdminMessage.is(':visible')) {
666 $("#replyingAdminMsg").hide().removeClass('hidden').slideDown();
667 }
668 $('html, body').animate({
669 scrollTop: replyingAdminMessage.offset().top - 15
670 }, 400);
671 }
672
673 if (allowPost) {
674 replyingAdminMessage.slideUp();
675 form.attr('data-no-clear', 'false');
676 form.trigger('submit', { 'skipValidation': true });
677 } else {
678 submitButton.removeAttr('disabled');
679 submitButton.find('i').removeClass('fa-spinner fa-spin').addClass(swapClass).end();
680 }
681 });
682}
683
684function loadTicketCcs()
685{
686 var userId = jQuery('#selectUserid').val(),
687 currentCcs = jQuery('#inputTicketCc').val().split(',');
688 if (!userId) {
689 userId = 0;
690 }
691 WHMCS.http.jqClient.jsonPost(
692 {
693 url: WHMCS.adminUtils.getAdminRouteUrl(
694 '/support/ticket/open/client/' + userId + '/additional/data'
695 ),
696 data: {
697 token: csrfToken,
698 showTen: true
699 },
700 success: function(data) {
701 var ccs = jQuery(".selectize-ticketCc")[0].selectize;
702 if (typeof ccs !== 'undefined') {
703 ccs.clearOptions();
704 if (data.ccs.length) {
705 var i, n, ccIndex;
706 ccs.addOption(data.ccs);
707 for (i = 0, n = data.ccs.length; i < n; i++) {
708 var ccData = data.ccs[i];
709 ccIndex = currentCcs.findIndex(function(checkValue){
710 return checkValue === ccData.text;
711 });
712 if (ccIndex !== -1) {
713 ccs.addItem(ccData.text, true);
714 currentCcs.splice(ccIndex, 1);
715 }
716 }
717 }
718 if (currentCcs.length) {
719 currentCcs.forEach(function (value) {
720 if (value) {
721 ccs.addOption(
722 {
723 name: value,
724 text: value
725 }
726 );
727 }
728 })
729 ccs.addItems(currentCcs, true);
730 }
731 }
732 }
733 }
734 );
735}
736