1/** 2 * Created by EMF ENG on 01/19/2015. 3 * Client-Server cooperation 4 * Dependencies: emf.js 5 * 6 */ 7; 8(function (window, EMF) { 9 var CONTENT_TYPE = 'application/json; charset=UTF-8'; 10 var CACHE_EXPIRE = 3000; 11 var _loadStack = 0; 12 var _cache = {}; 13 14 function showLoad() { 15 _loadStack++; 16 if (_loadStack > 1) return; 17 $('body > .load-indicator').toggleClass('hide', false); 18 } 19 20 function hideLoad() { 21 _loadStack--; 22 if (_loadStack > 0) return; 23 $('body > .load-indicator').toggleClass('hide', true); 24 } 25 26 function refreshLoadIndicator() { 27 $('body > .load-indicator').toggleClass('hide', _loadStack === 0); 28 } 29 30 function showError(title, message, buttons, onDismiss, onInit) { 31 const dialog = bootbox.dialog({ 32 message: message, 33 title: '{0}'.f(title), 34 buttons: buttons 35 }); 36 onInit && dialog.init(onInit(dialog)); 37 dialog.find('.modal-dialog').addClass('emf-modal-dialog'); 38 dialog.find('.modal-title').addClass('h3'); 39 onDismiss && dialog.on('hidden.bs.modal', onDismiss); 40 } 41 42 function defaultError(title, message) { 43 showError(title, message, { 44 ok: { 45 label: "OK", 46 className: "btn btn-primary btn-md", 47 callback: function () {} 48 } 49 }); 50 } 51 52 function handleError(response, dropzoneInstance, file, jqXHR) { 53 response = response || { 54 code: -1, 55 status: false 56 } 57 response.handled = true; 58 var error = $.grep(ERRORS, function (e) { 59 return e.codes.indexOf(response.code) !== -1; 60 })[0]; 61 if (!error) { 62 showError('Error', 'An error occured! Error code: {0}'.f(response.code), { 63 ok: { 64 label: "ok", 65 className: "btn-primary btn-md ucase" 66 } 67 }, function () {}); 68 } 69 else { 70 var content = error.getContent ? error.getContent(response, dropzoneInstance, jqXHR) : error.content; 71 if (error.type === 'popup') { 72 file && $(file.previewElement).find('.dz-error-message span').text(content); 73 } 74 else if (error.type === 'modal') { 75 file && $(file.previewElement).find('.dz-error-message').remove(); 76 error.onDismiss = typeof error.onDismiss !== 'function' ? function () {} : error.onDismiss; 77 showError(error.title, content, error.buttons, error.onDismiss, error.init); 78 } 79 } 80 hideLoad(); 81 } 82 83 function ajax(type, url, data, show_loader, handle_error) { 84 type = type.toUpperCase(); 85 var hash = type + url + (data ? JSON.stringify(data) : ''); 86 if (_cache[hash] && Date.now() - _cache[hash].time < CACHE_EXPIRE) { 87 return _cache[hash].promise; 88 } 89 90 show_loader = typeof show_loader === 'undefined' ? true : show_loader; 91 handle_error = typeof handle_error === 'undefined' ? true : handle_error; 92 93 var p = new Promise(function (resolve, reject) { 94 95 function normalAjaxCall() { 96 var obj = { 97 url: url, 98 type: type, 99 contentType: CONTENT_TYPE, 100 data: data || '' 101 }; 102 if (type === 'POST') { 103 obj.dataType = "json"; 104 delete obj.contentType; 105 } 106 else if (type === 'DELETE' || type === 'PUT') { 107 obj.processData = false; 108 if (typeof obj !== "string") obj.data = JSON.stringify(obj.data); 109 } 110 var ajax = $.ajax(obj); 111 ajax.then(function (response, textStatus, jqXHR) { 112 if (show_loader) { 113 hideLoad(); 114 } 115 116 if (response === undefined || response.status || response === "") { 117 resolve(response); 118 return; 119 } 120 121 if (handle_error) { 122 handleError(response, null, null, jqXHR); 123 } else { 124 hideLoad(); 125 jqXHR.responseJSON.handled = true; 126 } 127 128 reject(jqXHR); 129 }, function (response) { 130 if (response.statusText != 'abort') { 131 data = response ? response.responseJSON : { status: false, code: 0 }; 132 if (handle_error) { 133 handleError(data, null, null, response); 134 } else { 135 hideLoad(); 136 response.responseJSON.handled = true; 137 } 138 139 reject(response); 140 } else { 141 if (show_loader) { 142 hideLoad(); 143 } 144 } 145 }); 146 } 147 148 if (EMF.mock) { 149 var mocks = EMF.mock[url]; 150 if (mocks) { 151 $(function () { 152 var message = '<h3>Hey dude, there are some mocks for that request</h3>' + 153 '<p>' + url + '</p>' + 154 '<p>Wanna use one of them?</p>' + 155 '<ul class="mocks">' + 156 $.map(mocks, function(mock, i){ 157 return '<li><a style="cursor: pointer" data-index={0}>{1}</a></li>'.f(i, mock.name); 158 }).join('') + 159 '</ul>'; 160 161 bootbox.dialog({ 162 message: message, 163 title: 'Mock response', 164 buttons: { 165 no: { 166 label: "No", 167 className: "btn btn-primary btn-md", 168 callback: function () { 169 normalAjaxCall(); 170 } 171 } 172 } 173 }); 174 175 $('.mocks').on('click', 'a', function(){ 176 var index = $(this).attr('data-index'); 177 if (show_loader) { 178 hideLoad(); 179 } 180 resolve(mocks[index].data); 181 bootbox.hideAll(); 182 }); 183 }); 184 return; 185 } 186 } 187 188 normalAjaxCall(); 189 }); 190 191 _cache[hash] = { 192 time: Date.now(), 193 promise: p 194 }; 195 if (show_loader) { 196 showLoad(); 197 } 198 199 return p; 200 } 201 202 var appDomain, wwwDomain; 203 204 function getAppDomain() { 205 return new Promise(resolve => { 206 if (appDomain) { 207 resolve(appDomain); 208 return; 209 } 210 211 if (Modernizr && Modernizr.localstorage && 212 (appDomain = localStorage.getItem('appDomain')) 213 ) { 214 resolve(appDomain); 215 return; 216 } 217 218 ajax('GET', '/builder/api/v1/system/app_domain') 219 .then(response => { 220 appDomain = response.data.domain; 221 if (Modernizr && Modernizr.localstorage) { 222 localStorage.setItem('appDomain', appDomain); 223 } 224 resolve(appDomain); 225 }) 226 }) 227 } 228 229 function getWwwDomain() { 230 return new Promise(resolve => { 231 if (wwwDomain) { 232 resolve(wwwDomain); 233 return; 234 } 235 236 if (Modernizr && Modernizr.localstorage && 237 (wwwDomain = localStorage.getItem('wwwDomain')) 238 ) { 239 resolve(wwwDomain); 240 return; 241 } 242 243 ajax('GET', '/builder/api/v1/system/www_domain') 244 .then(response => { 245 wwwDomain = response.data.domain; 246 if (Modernizr && Modernizr.localstorage) { 247 localStorage.setItem('wwwDomain', wwwDomain); 248 } 249 resolve(wwwDomain); 250 }) 251 }) 252 } 253 254 EMF.SERVER = { 255 ajax: ajax, 256 handleError: handleError, 257 showLoad: showLoad, 258 hideLoad: hideLoad, 259 defaultError: defaultError, 260 refreshLoadIndicator: refreshLoadIndicator, 261 262 getAppDomain: getAppDomain(), 263 getWwwDomain: getWwwDomain() 264 }; 265 var unhandledServerExceptionBodyTemplate = ` 266 <h4>What is happened?</h4> 267 <p class="mb-4">There was a problem with API request.` + ' Error code: {0}</p>' + 268 ` 269 <h4>What can I do?</h4> 270 <p>Please report this error so we can be aware of it and repair as soon as possible or contact our Support Team.</p> 271 <div class="text-center"> 272 <a class="btn btn-link collapsed btn-collapse d-flex align-items-center justify-content-center text-info" role="button" data-toggle="collapse" href="#collapseErrorReportForm" aria-expanded="false" aria-controls="collapseErrorReportForm"> 273 Report this issue 274 <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" class="ml-2"> 275 <path class="btn-collapse_collapsed" d="M11.8082 3.04848L11.4151 2.65267C11.2914 2.52906 11.1268 2.46096 10.9509 2.46096C10.7751 2.46096 10.6103 2.52906 10.4866 2.65267L6.00268 7.13681L1.51357 2.6477C1.39006 2.52409 1.22528 2.45609 1.04947 2.45609C0.873666 2.45609 0.708786 2.52409 0.585176 2.6477L0.192002 3.04107C-0.0640005 3.29687 -0.0640005 3.71356 0.192002 3.96937L5.53683 9.33341C5.66034 9.45692 5.82493 9.54395 6.00229 9.54395H6.00434C6.18025 9.54395 6.34483 9.45682 6.46835 9.33341L11.8082 3.9839C11.9319 3.86039 11.9998 3.69083 12 3.51502C12 3.33912 11.9319 3.1719 11.8082 3.04848Z" fill="#2F75EC"/> 276 <path class="btn-collapse_expanded" d="M0.191807 8.95152L0.584883 9.34733C0.708591 9.47094 0.873178 9.53904 1.04908 9.53904C1.22489 9.53904 1.38967 9.47094 1.51338 9.34733L5.99732 4.86319L10.4864 9.3523C10.6099 9.47591 10.7747 9.54391 10.9505 9.54391C11.1263 9.54391 11.2912 9.47591 11.4148 9.3523L11.808 8.95893C12.064 8.70313 12.064 8.28644 11.808 8.03063L6.46317 2.66659C6.33966 2.54308 6.17507 2.45605 5.99771 2.45605H5.99566C
2765.81975 2.45605 5.65517 2.54318 5.53165 2.66659L0.191807 8.0161C0.0680981 8.13961 0.00019455 8.30917 0 8.48498C0 8.66088 0.0680981 8.8281 0.191807 8.95152Z" fill="#2F75EC"/> 277 </svg> 278 </a> 279 </div> 280 <div class="collapse c-form" id="collapseErrorReportForm" aria-expanded="false"> 281 <div class="form-group"> 282 <input type="hidden" class="errorCode form-control" value="{0}"> 283 <input type="hidden" class="errorInfo form-control" value="Unhandled exception. ` + '{1}' + `"> 284 </div> 285 <div class="form-group position-relative"> 286 <input type="text" class="userEmail form-control validate" data-validate="required,email" placeholder="Email (required)" value="` + '{2}' + `"> 287 </div> 288 <div class="form-group position-relative"> 289 <textarea class="userMessage form-control validate" data-validate="required" placeholder="Message (required)" rows="5"></textarea> 290 </div> 291 </div> 292 `; 293 294 function submitErrorReport(dialog) { 295 var 296 $dialog = $(dialog), 297 collapseErrorReportForm = $dialog.find('#collapseErrorReportForm')[0], 298 $errorCode = $($dialog.find(".errorCode")[0]), 299 $errorInfo = $($dialog.find(".errorInfo")[0]), 300 $userEmail = $($dialog.find(".userEmail")[0]), 301 $userMessage = $($dialog.find(".userMessage")[0]); 302 303 if (validation) { 304 validation.hideAll(collapseErrorReportForm); 305 if (!validation.validate(collapseErrorReportForm)) { 306 return false; 307 } 308 } 309 310 var messageData = { 311 errorCode: $errorCode.val(), 312 errorInfo: $errorInfo.val(), 313 userEmail: $userEmail.val(), 314 userMessage: $userMessage.val() 315 }; 316 317 ajax('POST', '/builder/api/v1/system/report_error', messageData, true, false) 318 .then( 319 data => { 320 if (bootbox) { 321 bootbox.alert({ 322 message: "<h4 style='text-align:center'>Success!</h4>", 323 size: 'small' 324 }); 325 } else { 326 alert("Success!"); 327 } 328 }, 329 errorResponse => { 330 var message = "<h4 style='text-align:center'>Failure!</h4>"; 331 332 if (errorResponse.responseJSON.error_message) { 333 message += `<p style='text-align:center'>The reason: ${errorResponse.responseJSON.error_message}</p>`; 334 } 335 336 console.warn(errorResponse); 337 338 if (bootbox) { 339 bootbox.alert({ 340 message, 341 size: 'small' 342 }); 343 } else { 344 alert(message); 345 } 346 } 347 ); 348 349 return true; 350 } 351 352 var ERRORS = [{ 353 codes: [3401, 3403], 354 type: 'silent', 355 title: 'Your session timed out', 356 content: 'The page was left without activity and your session has timed out. Please log in again to continue.', 357 buttons: { 358 login: { 359 label: "Login", 360 className: "btn btn-primary btn-md", 361 callback: function () { 362 window.location.reload(); 363 } 364 } 365 }, 366 onDismiss: function () { 367 window.location.reload(); 368 }, 369 getContent: function (response) { 370 return this.content.f(response.code); 371 } 372 }, { 373 codes: [1000], 374 type: 'modal', 375 title: 'Error - No Images', 376 content: 'You have not selected any images to be uploaded. Please choose images from your computer and drag them into the upload area.', 377 buttons: { 378 ok: { 379 label: "OK", 380 className: "btn btn-primary btn-md", 381 callback: function () {} 382 } 383 } 384 }, { 385 codes: [2000], 386 type: 'popup', 387 title: 'Error - File Limit Exceeded', 388 content: 'The file is larger then the maximum allowed size of {0}MB.', 389 getContent: function (response, instance) { 390 return this.content.f(instance.options.maxFilesize); 391 } 392 }, { 393 codes: [3000], 394 type: 'modal', 395 title: 'Error - File Storage Limit Reached', 396 content: 'You have reached your File Storage limit. Please <a href="{0}">upgrade</a> your account for more storage, extra submissions and features.', 397 getContent: function (response) { 398 return this.content.f(EMF.upgradeUrl); 399 }, 400 buttons: { 401 upgrade: { 402 label: "UPGRADE", 403 className: "btn btn-warning btn-md ucase", 404 callback: function () { 405 window.location.href = EMF.upgradeUrl; 406 } 407 }, 408 cancel: { 409 label: "CANCEL",
410 className: "btn btn-transparent btn-md", 411 callback: function () {} 412 } 413 } 414 }, { 415 codes: [4000], 416 type: 'popup', 417 title: 'Error - File Type Not Allowed', 418 content: 'This file extension is not allowed. Please remove this file' 419 }, { 420 codes: [5000], 421 type: 'modal', 422 title: 'Error - Access Denied', 423 content: 'Sorry, you do not have permissions to upload images. Please contact your account administrator.', 424 buttons: { 425 ok: { 426 label: "OK", 427 className: "btn btn-primary btn-md", 428 callback: function () {} 429 } 430 } 431 }, { 432 codes: [6000, 9000], 433 type: 'popup', 434 title: 'Error - File Already Exists', 435 content: 'This file has already been uploaded', 436 }, { 437 codes: [7000], 438 type: 'modal', 439 title: 'Error - File Access Error', 440 content: 'There was an error accessing the temporary uploaded file. Please try again! If this error happens again, please <a href="mailto:[email protected]">contact our support</a>. Error code: {0}', 441 buttons: { 442 ok: { 443 label: "OK", 444 className: "btn btn-primary btn-md", 445 callback: function () {} 446 } 447 }, 448 getContent: function (response) { 449 return this.content.f(response.code); 450 } 451 }, { 452 codes: [1002], 453 type: 'modal', 454 title: 'Error - Access Denied', 455 content: 'Sorry, you do not have permissions to create new themes. Please contact your account administrator.', 456 buttons: { 457 ok: { 458 label: "OK", 459 className: "btn btn-primary btn-md", 460 callback: function () {} 461 } 462 } 463 }, { 464 codes: [2002, 4002], 465 type: 'modal', 466 title: 'A Database Error Happened!', 467 content: 'An error happened while saving data into the database. If this error happens again, please <a href="mailto:[email protected]">contact our support</a>. Error code: {0}', 468 buttons: { 469 ok: { 470 label: "OK", 471 className: "btn btn-primary btn-md", 472 callback: function () {} 473 } 474 }, 475 getContent: function (response) { 476 return this.content.f(response.code); 477 } 478 }, { 479 codes: [3002], 480 type: 'modal', 481 title: 'Cloud Provider Error!', 482 content: 'An error happened while saving files into our cloud. If this error happens again, please <a href="mailto:[email protected]">contact our support</a>. Error code: {0}', 483 buttons: { 484 ok: { 485 label: "OK", 486 className: "btn btn-primary btn-md", 487 callback: function () {} 488 } 489 }, 490 getContent: function (response) { 491 return this.content.f(response.code); 492 } 493 }, { 494 codes: [-1, 401000, 403000, 405000, 8000, 1401, 2401, 1401, 1404, 404], 495 type: 'modal', 496 title: 'Unhandled server error', 497 content: unhandledServerExceptionBodyTemplate, 498 buttons: { 499 ok: { 500 label: "Submit", 501 className: "btn btn-info submitButton", 502 callback: e => submitErrorReport(e.delegateTarget) 503 }, 504 cancel: { 505 label: "Close", 506 className: "btn btn-transparent info closeButton", 507 callback: () => true 508 } 509 }, 510 init: function(dialog) { 511 var 512 $dialog = $(dialog), 513 collapseErrorReportForm = $dialog.find('#collapseErrorReportForm')[0], 514 $userEmail = $dialog.find(".userEmail"), 515 $userMessage = $dialog.find(".userMessage"), 516 $submitButton = $($dialog.find(".submitButton")[0]); 517 518 $submitButton.hide(); 519 520 if (validation) { 521 $userEmail.keydown(() => { validation.hideAll(collapseErrorReportForm) }); 522 $userEmail.blur(() => validation.validate($userEmail.closest("div")[0])); 523 $userEmail.focus(() => { validation.hideAll(collapseErrorReportForm) }); 524 525 $userMessage.keydown(() => { validation.hideAll(collapseErrorReportForm) }); 526 $userMessage.blur(() => validation.validate($userMessage.closest("div")[0])); 527 $userMessage.focus(() => { validation.hideAll(collapseErrorReportForm) }); 528 } 529 530 dialog.find('.modal-footer').addClass('modal-footer_bordered'); 531 dialog.find('.modal-footer').append('<div class="mt-3">Or contact us at <a href="mailto:[email protected]">[email protected]</a></div>'); 532 533 $(collapseErrorReportForm).keydown(e => { 534 e.keyCode === 13 && 535 submitErrorReport(dialog) && 536 dialog.modal('hide') 537 }) 538 539 $(collapseErrorReportForm).on('show.bs.collapse', () => { $submitButton.show() }) 540 $(collapseErrorReportForm).on('hide.bs.collapse', () => { $submitButton.hide() }) 541 }, 542 getContent: function (response, dropzoneInstance, jqXHR) { 543 bootbox.hideAll(); 544 545 var code = jqXHR.getResponseHeader('X-Debugging-Tracking-Code') || response.code; 546 547 var errorInfo = 'Tracking code: ' + code + '. Status: ' + jqXHR.status + ' ' + jqXHR.statusText 548 549 var user_email;
550 try { 551 var user_info = localStorage.getItem('user_info'); 552 if (user_info) { 553 user_info = JSON.parse(user_info); 554 user_email = user_info.email || ''; 555 } 556 } catch(e) { 557 user_email = ''; 558 } 559 560 return this.content.f(code, errorInfo, user_email); 561 } 562 }, { 563 codes: [422], 564 type: 'silent', 565 title: 'Validation Error', 566 content: '{0}', 567 buttons: { 568 ok: { 569 label: "OK", 570 className: "btn btn-primary btn-md", 571 callback: function () {} 572 } 573 }, 574 getContent: function (response) { 575 var fields = { 576 'old_password': 'Current Password Invalid', 577 'password': 'New Password must have more than 3 characters', 578 'confirmation': 'Confirm does not match' 579 }; 580 var messages = []; 581 for (var name in response.data) { 582 messages.push(response.data[name]); 583 } 584 messages = messages.map(function (v) { 585 return '<span>' + v + '</span><br>'; 586 }); 587 return this.content.f(messages.join('')); 588 } 589 }, { 590 codes: [403], 591 type: 'modal', 592 title: 'Forbidden', 593 content: 'You are not authorized to perform this operation', 594 buttons: { 595 ok: { 596 label: "OK", 597 className: "btn btn-primary btn-md", 598 callback: function () {} 599 } 600 }, 601 getContent: function (response) { 602 return this.content.f(response.code); 603 } 604 }, { 605 codes: [6003, 7003], 606 type: 'modal', 607 title: 'You have no permissions', 608 content: 'There was an error performing this action. Error code: {0}', 609 buttons: { 610 ok: { 611 label: "OK", 612 className: "btn btn-primary btn-md", 613 callback: function () {} 614 } 615 }, 616 getContent: function (response) { 617 return this.content.f(response.code); 618 } 619 }, 620 { 621 codes: [1004], 622 type: 'modal', 623 title: 'Form is under review', 624 content: 'This form is under review so you can not perform any action until review completed', 625 buttons: { 626 ok: { 627 label: "OK", 628 className: "btn btn-primary btn-md", 629 callback: function () {} 630 } 631 } 632 }]; 633})(window, window.EMF);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.