1// Create language switcher instance 2var lang = new Lang(); 3var langStrings = { token: {} }; 4loadLanguageList(); 5var falbackLanguage = 6 languageList.filter( 7 (p) => p.code == language(moment.locale(navigator.languages[0])) 8 ).length > 0 9 ? language(moment.locale(navigator.languages[0])) 10 : "en"; 11lang.init({ 12 //defaultLang: 'en', 13 currentLang: getCookie("organizrLanguage") 14 ? getCookie("organizrLanguage") 15 : falbackLanguage, 16 cookie: { 17 name: "organizrLanguage", 18 expiry: 365, 19 path: "/", 20 }, 21 allowCookieOverride: true, 22}); 23var OAuthLoginNeeded = false; 24var directToHash = false; 25var pingOrg = false; 26var checkCommitLoadStatus = false; 27var timeouts = {}; 28var increment = 0; 29var tabInformation = {}; 30var tabActionsList = []; 31tabActionsList["refresh"] = []; 32tabActionsList["close"] = []; 33var customHTMLEditorObject = []; 34$.xhrPool = []; 35// Add new jquery serializeObject function 36$.fn.serializeObject = function () { 37 var o = {}; 38 var a = this.serializeArray(); 39 $.each(a, function () { 40 if (o[this.name] !== undefined) { 41 if (!o[this.name].push) { 42 o[this.name] = [o[this.name]]; 43 } 44 o[this.name].push(this.value || ""); 45 } else { 46 o[this.name] = this.value || ""; 47 } 48 }); 49 return o; 50}; 51// Start Organizr 52$(document).ready(function () { 53 if (getCookie("organizrOAuth")) { 54 OAuthLoginNeeded = true; 55 } 56 launch(); 57 local("r", "loggingIn"); 58}); 59/* NORMAL FUNCTIONS */ 60function setLangCookie(lang) { 61 Cookies.set("organizrLanguage", lang, { 62 expires: 365, 63 path: "/", 64 }); 65} 66 67function highlightObject(json) { 68 if (typeof json != "string") { 69 json = JSON.stringify(json, undefined, "\t"); 70 } 71 json = json 72 .replace(/&/g, "&") 73 .replace(/</g, "<") 74 .replace(/>/g, ">"); 75 return json.replace( 76 /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, 77 function (match) { 78 var cls = "number"; 79 if (/^"/.test(match)) { 80 if (/:$/.test(match)) { 81 cls = "key"; 82 } else { 83 cls = "string"; 84 } 85 } else if (/true|false/.test(match)) { 86 cls = "boolean"; 87 } else if (/null/.test(match)) { 88 cls = "null"; 89 } 90 return '<span class="' + cls + '">' + match + "</span>"; 91 } 92 ); 93} 94function orgDebug() { 95 let cmd = $("#debug-input").val(); 96 let result = ""; 97 if (cmd !== "") { 98 result = eval(cmd); 99 } 100 if (result !== "") { 101 $("#debugResultsBox").removeClass("hidden"); 102 $("#debugResults").html(formatDebug(result)); 103 $(".cmdName").text(cmd); 104 if (bowser.mobile !== true) { 105 $("#debugResults > .whitebox").slimScroll(); 106 } 107 } else { 108 } 109} 110function getDepth(object) { 111 var level = 1; 112 for (var key in object) { 113 if (!object.hasOwnProperty(key)) continue; 114 115 if (typeof object[key] == "object") { 116 var depth = getDepth(object[key]) + 1; 117 level = Math.max(depth, level); 118 } 119 } 120 return level; 121} 122function jsonToHTML(json) { 123 var html = ""; 124 $.each(json, function (i, v) { 125 if (typeof v === "object") { 126 html += '<p class="tab0">' + i + ":</p>"; 127 $.each(v, function (index, value) { 128 if (typeof value === "object") { 129 html += '<p class="tab1">' + index + ":</p>"; 130 html += jsonToHTML2(value); 131 } else { 132 html += '<p class="tab1">' + index + ": " + value + "</p>"; 133 } 134 }); 135 } else { 136 html += '<p class="tab0">' + i + ": " + v + "</p>"; 137 } 138 }); 139 return html; 140} 141function jsonToHTML2(json) { 142 var html = ""; 143 $.each(json, function (i, v) { 144 if (typeof v === "object") { 145 html += '<p class="tab2">' + i + ":</p>"; 146 $.each(v, function (index, value) { 147 if (typeof value === "object") { 148 html += '<p class="tab3">' + index + ":</p>"; 149 html += jsonToHTML3(value); 150 } else { 151 html += '<p class="tab3">' + index + ": " + value + "</p>"; 152 } 153 }); 154 } else { 155 html += '<p class="tab2">' + i + ": " + v + "</p>"; 156 } 157 }); 158 return html; 159} 160function jsonToHTML3(json) { 161 var html = ""; 162 $.each(json, function (i, v) { 163 if (typeof v === "object") { 164 html += '<p class="tab4">' + i + ":</p>"; 165 $.each(v, function (index, value) { 166 if (typeof value === "object") { 167 html += '<p class="tab5">' + index + ":</p>"; 168 html += jsonToHTML2(value); 169 } else { 170 html += '<p class="tab5">' + index + ": " + value + "</p>"; 171 } 172 }); 173 } else { 174 html += '<p class="tab4">' + i + ": " + v + "</p>"; 175 } 176 }); 177 return html; 178} 179 180function copyDebug() { 181 var pre = $("#debugPreInfo").find(".whitebox").text(); 182 var debug = $("#debugResults").find(".whitebox").text(); 183 clipboard(true, pre + debug); 184 console.log(pre + debug); 185} 186function formatDebug(result) { 187 var formatted = ""; 188 switch (typeof result) { 189 case "object": 190 formatted = jsonToHTML(result); 191 break; 192 default: 193 formatted = result; 194 } 195 return ( 196 '<pre class="whitebox bg-org text-success default-scroller">' + 197 formatted + 198 "</pre>" 199 ); 200} 201function getDebugPreInfo() { 202 var formatted = 203 "Version: " + 204 activeInfo.version + 205 "<br/>Branch: " + 206 activeInfo.branch + 207 "<br/>Server OS: " + 208 activeInfo.serverOS + 209 "<br/>PHP: " + 210 activeInfo.phpVersion + 211 "<br/>Install Type: " + 212 (activeInfo.settings.misc.docker ? "Official Docker" : "Native") + 213 "<br/>Auth Type: " + 214 activeInfo.settings.misc.authType + 215 "<br/>Auth Backend: " + 216 activeInfo.settings.misc.authBackend + 217 "<br/>Installed Plugins: " + 218 formatDebug(activeInfo.settings.misc.installedPlugins) + 219 "<br/>Installed Themes: " + 220 formatDebug(activeInfo.settings.misc.installedThemes) + 221 "<br/>Theme: " + 222 activeInfo.theme + 223 "<br/>Local: " + 224 activeInfo.settings.user.local + 225 "<br/>oAuth: " + 226 activeInfo.settings.user.oAuthLogin + 227 "<br/>Agent: " + 228 activeInfo.settings.user.agent; 229 formatted = 230 '<pre class="whitebox bg-org text-success">' + formatted + "</pre>"; 231 $("#debugPreInfo").html(formatted); 232 if (bowser.mobile !== true) { 233 $("#debugPreInfo > .whitebox").slimScroll(); 234 } 235} 236function orgDebugList(cmd) { 237 if (cmd !== "") { 238 $("#debug-input").val(cmd); 239 orgDebug(); 240 } 241} 242function updateIssueLink(line) { 243 let preNumber = line.match(/\S*\#(.*)/g); 244 if (preNumber !== null) { 245 preNumber = preNumber.toString(); 246 let numberSplit = preNumber.split("#"); 247 let issueType = numberSplit[0].replace("(", "").replace(")", ""); 248 let issueNumber = numberSplit[1].replace("(", "").replace(")", ""); 249 let issueWord = 250 issueType.toLowerCase() == "fr" 251 ? '<i class="icon-arrow-up-circle"></i> feature' 252 : '<i class="fa fa-github"></i> issue';
253 let colorType = 254 issueType.toLowerCase() == "fr" ? "label-info" : "label-primary"; 255 let issueLink = 256 issueType.toLowerCase() == "fr" 257 ? "https://feature.organizr.app/posts/" + issueNumber 258 : "https://github.com/causefx/Organizr/issues/" + issueNumber; 259 issueLink = 260 '<span class="label upgrade-label text-uppercase ' + 261 colorType + 262 ' label-rounded font-12 pull-right"><a class="text-white text-uppercase" href="' + 263 issueLink + 264 '" target="_blank">' + 265 issueWord + 266 "</a></span>"; 267 return line.replace(preNumber, issueLink); 268 } else { 269 return line; 270 } 271} 272function clipboard(trigger = true, string = null) { 273 let clipboard = $("#internal-clipboard"); 274 if (string) { 275 clipboard.attr("data-clipboard-text", string); 276 } 277 if (trigger) { 278 clipboard.click(); 279 } 280} 281function getLangStrings() { 282 let strings = JSON.stringify(window.langStrings, null, "\t"); 283 clipboard(true, strings); 284 organizrConsole("JSON Function", "Copied JSON Strings to clipboard"); 285} 286function getHiddenProp() { 287 var prefixes = ["webkit", "moz", "ms", "o"]; 288 // if 'hidden' is natively supported just return it 289 if ("hidden" in document) return "hidden"; 290 // otherwise loop over all the known prefixes until we find one 291 for (var i = 0; i < prefixes.length; i++) { 292 if (prefixes[i] + "Hidden" in document) return prefixes[i] + "Hidden"; 293 } 294 // otherwise it's not supported 295 return null; 296} 297function isHidden() { 298 var prop = getHiddenProp(); 299 if (!prop) return false; 300 return document[prop]; 301} 302function loadLanguageList() { 303 $.each(languageList, function (i, v) { 304 lang.dynamic(v.code, "js/langpack/" + v.filename); 305 }); 306} 307function sleep(ms) { 308 return new Promise((resolve) => setTimeout(resolve, ms)); 309} 310function contains(target, pattern) { 311 var value = 0; 312 pattern.forEach(function (word) { 313 value = value + target.includes(word); 314 }); 315 return value === 1; 316} 317function isNumberKey(evt) { 318 var charCode = evt.which ? evt.which : event.keyCode; 319 if (charCode < 48 || charCode > 57) return false; 320 return true; 321} 322function setTabInfo(id, action, value) { 323 let tabInfo = findTab(id); 324 if (!tabInfo) { 325 organizrConsole("Set Tab Info", "No Tab Info Found... Id: " + id, "error"); 326 return false; 327 } 328 let tab = cleanClass(tabInfo.name); 329 if ( 330 tab == "Organizr-Support" || 331 tab == "Organizr-Docs" || 332 tab == "Feature-Request" 333 ) { 334 return false; 335 } 336 if (tab !== null && action !== null && value !== null) { 337 switch (action) { 338 case "active": 339 $.each(tabInformation, function (i, v) { 340 tabInformation[i]["active"] = false; 341 }); 342 break; 343 default: 344 //nada 345 } 346 tabInformation[id][action] = value; 347 } else { 348 return false; 349 } 350} 351function tabTimerAction() { 352 if (tabActionsList.close.length > 0) { 353 $.each(tabActionsList.close, function (i, v) { 354 var tab = v.tab; 355 var minutes = tabInformation[v.id]["tabInfo"]["timeout_ms"] / 1000 / 60; 356 var process = false; 357 if (tabInformation[v.id]["loaded"]) { 358 if (tabInformation[v.id]["active"] && idleTime >= 1) { 359 process = true; 360 } 361 if (tabInformation[v.id]["active"] === false) { 362 process = true; 363 } 364 if (process) { 365 tabInformation[v.id]["increments"] = 366 tabInformation[v.id]["increments"] + 1; 367 if (tabInformation[v.id]["increments"] >= minutes) { 368 tabInformation[v.id]["increments"] = 0; 369 organizrConsole("Tab Function", "Auto Closing tab: " + tab); 370 closeTab(v.id); 371 } 372 } 373 } 374 }); 375 } 376 if (tabActionsList.refresh.length > 0) { 377 $.each(tabActionsList.refresh, function (i, v) { 378 var tab = v.tab; 379 var minutes = tabInformation[v.id]["tabInfo"]["timeout_ms"] / 1000 / 60; 380 var process = false; 381 if (tabInformation[v.id]["loaded"]) { 382 tabInformation[v.id]["increments"] = 383 tabInformation[v.id]["increments"] + 1; 384 if (tabInformation[v.id]["increments"] >= minutes) { 385 tabInformation[v.id]["increments"] = 0; 386 organizrConsole("Tab Function", "Auto Reloading tab: " + tab); 387 reloadTab(v.id); 388 } 389 } 390 }); 391 } 392} 393function timerIncrement() { 394 increment = increment + 1; 395 tabTimerAction();
396 //check for cookieExpiry 397 if (hasCookie) { 398 if (getCookie("organizrToken")) { 399 //do nothing 400 } else { 401 location.reload(); 402 } 403 } 404 idleTime = idleTime + 1; 405 if (typeof activeInfo !== "undefined") { 406 if ( 407 activeInfo.settings.lockout.enabled && 408 activeInfo.settings.user.oAuthLogin !== true 409 ) { 410 if ( 411 idleTime > activeInfo.settings.lockout.timer && 412 $("#lockScreen").length !== 1 413 ) { 414 if ( 415 activeInfo.user.groupID <= activeInfo.settings.lockout.minGroup && 416 activeInfo.user.groupID >= activeInfo.settings.lockout.maxGroup 417 ) { 418 lock(); 419 } 420 } 421 } 422 } 423} 424function ajaxblocker( 425 element = null, 426 action = "out", 427 message = "Loading...", 428 background = "#707cd2", 429 border = "#5761a9", 430 colorText = "#fff" 431) { 432 switch (action) { 433 case "in": 434 case "fadein": 435 $(element).block({ 436 message: 437 '<p style="margin:0;padding:8px;font-size:24px;" lang="en">' + 438 message + 439 "</p>", 440 css: { 441 color: colorText, 442 border: "1px solid " + border, 443 backgroundColor: background, 444 }, 445 }); 446 break; 447 case "out": 448 case "fadeout": 449 $(element).unblock(); 450 break; 451 default: 452 $(element).unblock(); 453 } 454} 455function ajaxloader(element = null, action = "out") { 456 var loader = ` 457 <div class="ajaxloader"> 458 <svg class="circular" viewBox="25 25 50 50"> 459 <circle class="path" cx="50" cy="50" fill="none" r="20" stroke-miterlimit="10" stroke-width="5"></circle> 460 </svg> 461 </div>`; 462 switch (action) { 463 case "in": 464 case "fadein": 465 $(loader).appendTo(element); 466 break; 467 case "out": 468 case "fadeout": 469 $(".ajaxloader").remove(); 470 break; 471 default: 472 $(".ajaxloader").remove(); 473 } 474} 475function getDefault(id) { 476 let tabInfo = findTab(id); 477 if (!tabInfo) { 478 if (getHash() === false) { 479 organizrConsole("Get Default", "No Tab Info Found... Id: " + id, "error"); 480 organizrConsole( 481 "Get Default", 482 "Trying to load next tab in cycle", 483 "error" 484 ); 485 loadNextTab(true); 486 return false; 487 } 488 } 489 if ( 490 getHash() === false || 491 (getHash() === "OrganizrLogin" && activeInfo.user.loggedin) 492 ) { 493 if (tabInfo) { 494 switchTab(id); 495 } else { 496 $(".allTabsList").first().children().click(); 497 } 498 } else if (getHash() == "OrganizrLogin") { 499 loadNextTab(true); 500 } else { 501 let hashTab = getHash(); 502 let hashType = isNaN(hashTab) ? "name" : "id"; 503 let tabInfo = findTab(hashTab, hashType); 504 if (!tabInfo) { 505 organizrConsole( 506 "Get Hash", 507 "No Tab Info Found... Hash: " + hashTab, 508 "error" 509 ); 510 switchTab(id); 511 return false; 512 } 513 let type = tabInfo.type; 514 if (typeof hashTab !== "undefined" && typeof type !== "undefined") { 515 directToHash = true; 516 switchTab(tabInfo.id); 517 } else { 518 console.warn("Tab Function: " + hashTab + " is not a defined tab"); 519 switchTab(id); 520 } 521 } 522} 523function getTabType(id) { 524 let tabInfo = findTab(id); 525 if (!tabInfo) { 526 organizrConsole( 527 "Tab Type Function", 528 "No Tab Info Found... Id: " + id, 529 "error" 530 ); 531 return false; 532 } 533 return tabInfo.type; 534} 535function getHash() { 536 if ($(location).attr("hash")) { 537 return dirtyHash($(location).attr("hash").substr(1)); 538 } 539 return false; 540} 541function setHash(hash) { 542 window.location.hash = "#" + cleanHash(hash); 543} 544function getQueryVariable(variable) { 545 var query = window.location.search.substring(1); 546 var vars = query.split("&"); 547 for (var i = 0; i < vars.length; i++) { 548 var pair = vars[i].split("="); 549 if (pair[0] == variable) { 550 return pair[1]; 551 } 552 } 553 return false; 554} 555function iconPrefix(source) { 556 var tabIcon = source.split("::"); 557 var icons = { 558 materialize: "mdi mdi-", 559 fontawesome: "fa fa-", 560 themify: "ti-", 561 simpleline: "icon-", 562 weathericon: "wi wi-", 563 alphanumeric: "fa-fw", 564 }; 565 if (Array.isArray(tabIcon) && tabIcon.length === 2) { 566 if (tabIcon[0] !== "url" && tabIcon[0] !== "alphanumeric") { 567 return '<i class="' + icons[tabIcon[0]] + tabIcon[1] + ' fa-fw"></i>'; 568 } else if (tabIcon[0] == "alphanumeric") { 569 return '<i class="fa-fw">' + tabIcon[1] + "</i>"; 570 } else { 571 return '<img class="fa-fw" src="' + tabIcon[1] + '" alt="tabIcon" />'; 572 } 573 } else { 574 return '<img class="fa-fw" src="' + source + '" alt="tabIcon" />'; 575 } 576} 577function iconPrefixSplash(source) { 578 var tabIcon = source.split("::"); 579 var icons = { 580 materialize: "mdi mdi-", 581 fontawesome: "fa fa-", 582 themify: "ti-", 583 simpleline: "icon-", 584 weathericon: "wi wi-",
585 alphanumeric: "fa-fw", 586 }; 587 if (Array.isArray(tabIcon) && tabIcon.length === 2) { 588 if (tabIcon[0] !== "url" && tabIcon[0] !== "alphanumeric") { 589 return '<i class="' + icons[tabIcon[0]] + tabIcon[1] + ' fa-fw"></i>'; 590 } else if (tabIcon[0] == "alphanumeric") { 591 return '<i class="fa-fw">' + tabIcon[1] + "</i>"; 592 } else { 593 return tabIcon[1]; 594 } 595 } else { 596 return source; 597 } 598} 599function cleanClass(string) { 600 return string.replace(/ +/g, "-").replace(/\W+/g, "-"); 601} 602function cleanHash(hash) { 603 hash = encodeURI(hash); 604 return hash.replaceAll("%20", "-"); 605} 606function dirtyHash(hash) { 607 hash = hash.replaceAll("-", "%20"); 608 return decodeURI(hash); 609} 610// What the hell is this? I don't remember this lol 611function noTabs(arrayItems) { 612 if (arrayItems.data.user.loggedin === true) { 613 organizrAPI2("GET", "api/v2/page/tabs") 614 .success(function (data) { 615 try { 616 var json = data.response; 617 organizrConsole("Organizr Function", "No tabs available"); 618 $(json.data).appendTo($(".organizr-area")); 619 $(".organizr-area").removeClass("hidden"); 620 $("#preloader").fadeOut(); 621 } catch (e) { 622 organizrCatchError(e, data); 623 } 624 }) 625 .fail(function (xhr) { 626 OrganizrApiError(xhr, "Error"); 627 }); 628 } else { 629 $(".show-login").trigger("click"); 630 } 631} 632function formatImage(icon) { 633 if (!icon.id || icon.text == "Select or type Image") { 634 return icon.text; 635 } 636 var baseUrl = "/user/pages/images/flags"; 637 var $icon = $( 638 '<span><img src="' + 639 icon.id + 640 '" class="img-chooser" /> ' + 641 icon.text + 642 "</span>" 643 ); 644 return $icon; 645} 646function formatIcon(icon) { 647 if (!icon.id || icon.text == "Select or type Icon") { 648 return icon.text; 649 } 650 var $icon = $("<span>" + iconPrefix(icon.id) + icon.text + "</span>"); 651 return $icon; 652} 653function logout() { 654 message( 655 "", 656 " Goodbye!", 657 activeInfo.settings.notifications.position, 658 "#FFF", 659 "success", 660 "10000" 661 ); 662 organizrAPI2("GET", "api/v2/logout") 663 .success(function (data) { 664 local("set", "message", "Goodbye|Logout Successful|success"); 665 history.replaceState(null, null, " "); 666 if ( 667 activeInfo.settings.misc.authProxyOverrideLogout && 668 activeInfo.settings.misc.authProxyLogoutURL !== "" 669 ) { 670 location.href = activeInfo.settings.misc.authProxyLogoutURL; 671 } else { 672 location.reload(); 673 } 674 }) 675 .fail(function (xhr) { 676 OrganizrApiError(xhr, "Logout Failed"); 677 }); 678} 679function reloadOrganizr() { 680 location.reload(); 681} 682function hideFrames(split = null) { 683 let extra = split ? "-right" : ""; 684 $(".iFrame-listing" + extra + " div[class^='frame-container']") 685 .addClass("hidden") 686 .removeClass("show"); 687 $(".internal-listing" + extra + " div[class^='internal-container']") 688 .addClass("hidden") 689 .removeClass("show"); 690 $(".plugin-listing" + extra + " div[class^='plugin-container']") 691 .addClass("hidden") 692 .removeClass("show"); 693} 694function closeSideMenu() { 695 $(".content-wrapper").removeClass("show-sidebar"); 696} 697function removeMenuActive() { 698 $("#side-menu a").removeClass("active"); 699} 700function swapDisplay(type, split) { 701 let extra = split ? "-right" : ""; 702 switch (type) { 703 case "internal": 704 $("body").removeClass("fix-header"); 705 $(".iFrame-listing" + extra) 706 .addClass("hidden") 707 .removeClass("show"); 708 $(".internal-listing" + extra) 709 .addClass("show") 710 .removeClass("hidden"); 711 $(".login-area").addClass("hidden").removeClass("show"); 712 $(".plugin-listing" + extra) 713 .addClass("hidden") 714 .removeClass("show"); 715 //$('body').removeClass('fix-header'); 716 if (split) { 717 $("#page-wrapper").addClass("split"); 718 $("#page-wrapper-right").removeClass("hidden"); 719 } 720 break; 721 case "iframe": 722 $("body").addClass("fix-header"); 723 $(".iFrame-listing" + extra) 724 .addClass("show") 725 .removeClass("hidden"); 726 $(".internal-listing" + extra) 727 .addClass("hidden") 728 .removeClass("show"); 729 $(".login-area").addClass("hidden").removeClass("show"); 730 $(".plugin-listing" + extra) 731 .addClass("hidden") 732 .removeClass("show"); 733 //$('body').addClass('fix-header'); 734 if (split) { 735 $("#page-wrapper").addClass("split"); 736 $("#page-wrapper-right").removeClass("hidden"); 737 } 738 break; 739 case "login": 740 $("body").removeClass("fix-header"); 741 $(".iFrame-listing" + extra) 742 .addClass("hidden") 743 .removeClass("show"); 744 $(".internal-listing" + extra) 745 .addClass("hidden") 746 .removeClass("show"); 747 $(".login-area").addClass("show").removeClass("hidden"); 748 $(".plugin-listing" + extra) 749 .addClass("hidden") 750 .removeClass("show"); 751 if (activeInfo.settings.misc.minimalLoginScreen == true) { 752 $(".sidebar").addClass("hidden"); 753 $(".navbar").addClass("hidden"); 754 $("#page-wrapper").addClass("hidden"); 755 } 756 if (split) { 757 $("#page-wrapper").addClass("split"); 758 $("#page-wrapper-right").removeClass("hidden"); 759 } 760 break; 761 case "plugin": 762 $(".iFrame-listing" + extra) 763 .addClass("hidden") 764 .removeClass("show"); 765 $(".internal-listing" + extra) 766 .addClass("hidden") 767 .removeClass("show"); 768 $(".login-area").addClass("hidden").removeClass("show"); 769 $(".plugin-listing" + extra) 770 .addClass("show") 771 .removeClass("hidden"); 772 if (split) { 773 $("#page-wrapper").addClass("split"); 774 $("#page-wrapper-right").removeClass("hidden"); 775 } 776 break; 777 default: 778 } 779} 780function toggleParentActive(id) { 781 var childTab = $("#menu-" + id); 782 if (childTab.parent().hasClass("nav-second-level")) { 783 if (!childTab.parent().hasClass("in")) { 784 childTab.parent().addClass("collapse in"); 785 childTab.parent().parent().addClass("active"); 786 } 787 } 788} 789function swapBodyClass(id) { 790 let tabInfo = findTab(id); 791 if (!tabInfo) { 792 organizrConsole("Swap Body", "No Tab Info Found... Id: " + id, "error"); 793 return false;
794 } 795 let prior = $("body").attr("data-active-tab"); 796 let priorId = $("body").attr("data-active-tab-id"); 797 if (prior !== "") { 798 $("body").removeClass("active-tab-" + prior); 799 $("body").removeClass("active-tab-" + priorId); 800 } 801 $("body").attr("data-active-tab", tabInfo.name); 802 $("body").attr("data-active-tab-id", tabInfo.id); 803 $("body").addClass("active-tab-" + tabInfo.name); 804 $("body").addClass("active-tab-" + tabInfo.id); 805} 806function editPageTitle(title) { 807 document.title = title + " - " + activeInfo.appearance.title; 808} 809function switchToPlugin(plugin) { 810 closeSideMenu(); 811 removeMenuActive(); 812 swapDisplay("plugin"); 813 $(".plugin-container").each(function () { 814 $(this).addClass("hidden").removeClass("show"); 815 }); 816 $("#container-plugin-" + plugin) 817 .addClass("show") 818 .removeClass("hidden"); 819} 820function switchTab(id, split = null) { 821 let tabInfo = findTab(id); 822 if (!tabInfo) { 823 organizrConsole("Switch Tab", "No Tab Info Found... Id: " + id, "error"); 824 return false; 825 } 826 if (activeInfo.settings.misc.collapseSideMenuOnClick) { 827 if (!$(".navbar ").hasClass("sidebar-hidden")) { 828 toggleSideMenu(); 829 } 830 } 831 let extra = split ? "right-" : ""; 832 let type = tabInfo.type; 833 // need to rework for split 834 if (type !== 2) { 835 hideFrames(split); 836 closeSideMenu(); 837 removeMenuActive(); 838 toggleParentActive(id); 839 swapBodyClass(id); 840 } 841 if (type !== 2 && type !== "plugin") { 842 setHash(tabInfo.name); 843 } 844 switch (type) { 845 case 0: 846 case "0": 847 case "internal": 848 swapDisplay("internal", split); 849 var newTab = $("#internal-" + extra + id); 850 $("#menu-" + id) 851 .find("a") 852 .addClass("active"); 853 editPageTitle(tabInfo.name); 854 if (newTab.hasClass("loaded")) { 855 organizrConsole("Tab Function", "Switching to tab: " + tabInfo.name); 856 newTab.addClass("show").removeClass("hidden"); 857 setTabInfo(id, "active", true); 858 } else { 859 //$("#preloader").fadeIn(); 860 organizrConsole("Tab Function", "Loading new tab for: " + tabInfo.name); 861 $("#menu-" + id + " a") 862 .children() 863 .addClass("tabLoaded"); 864 newTab.addClass("show loaded").removeClass("hidden"); 865 loadInternal(id, split); 866 setTabInfo(id, "active", true); 867 setTabInfo(id, "loaded", true); 868 //$("#preloader").fadeOut(); 869 } 870 break; 871 case 1: 872 case "1": 873 case "iframe": 874 swapDisplay("iframe", split); 875 var newTab = $("#container-" + extra + id); 876 var tabURL = newTab.attr("data-url"); 877 $("#menu-" + id) 878 .find("a") 879 .addClass("active"); 880 editPageTitle(tabInfo.name); 881 if (newTab.hasClass("loaded")) { 882 organizrConsole("Tab Function", "Switching to tab: " + tabInfo.name); 883 newTab.addClass("show").removeClass("hidden"); 884 setTabInfo(id, "active", true); 885 } else { 886 $("#preloader").fadeIn(); 887 organizrConsole("Tab Function", "Loading new tab for: " + tabInfo.name); 888 $("#menu-" + id + " a") 889 .children() 890 .addClass("tabLoaded"); 891 newTab.addClass("show loaded").removeClass("hidden"); 892 $(buildFrame(id, extra)).appendTo(newTab); 893 setTabInfo(id, "active", true); 894 setTabInfo(id, "loaded", true); 895 $("#preloader").fadeOut(); 896 } 897 $("#frame-" + id).focus(); 898 break; 899 case 2: 900 case 3: 901 case "2": 902 case "3": 903 case "_blank": 904 case "popout": 905 popTab(id); 906 break; 907 case "plugin": 908 swapDisplay("plugin"); 909 $("#container-plugin-" + id) 910 .addClass("show") 911 .removeClass("hidden"); 912 break; 913 default: 914 organizrConsole("Tab Function", "Action not set", "error"); 915 } 916} 917function popTab(id) { 918 let tabInfo = findTab(id); 919 if (!tabInfo) { 920 organizrConsole( 921 "Pop Tab Function", 922 "No Tab Info Found... Id: " + id, 923 "error" 924 ); 925 return false; 926 } 927 let name = tabInfo.name; 928 switch (tabInfo.type) { 929 case 0: 930 case "0": 931 case "internal": 932 console.warn( 933 "Tab Function: New window not supported for tab id: " + 934 id + 935 " | " + 936 name 937 ); 938 break; 939 case 1: 940 case "1": 941 case "iframe": 942 case 2: 943 case 3: 944 case "2": 945 case "3": 946 case "_blank": 947 case "popout": 948 organizrConsole( 949 "Tab Function", 950 "Creating New Window for tab id: " + id + " | " + name 951 ); 952 window.open(tabInfo.access_url, "_blank"); 953 break; 954 default: 955 organizrConsole("Tab Function", "Action not set", "error"); 956 } 957} 958function closeTab(id) { 959 let tabInfo = findTab(id); 960 if (!tabInfo) { 961 organizrConsole( 962 "Close Tab Function", 963 "No Tab Info Found... Id: " + id, 964 "error" 965 ); 966 return false;
967 } 968 // check if current tab? 969 if ($(".active-tab-" + id).length > 0) { 970 closeCurrentTab(event); 971 } else { 972 if ($(".frame-" + id).hasClass("loaded")) { 973 switch (tabInfo.type) { 974 case 0: 975 case "0": 976 case "internal": 977 // quick check if homepage 978 if (tabInfo.access_url == "api/v2/page/homepage") { 979 organizrConsole( 980 "Organizr Function", 981 "Clearing All Homepage AJAX calls" 982 ); 983 clearAJAX("homepage"); 984 $.xhrPool.abortAll(); 985 } 986 organizrConsole("Tab Function", "Closing tab: " + tabInfo.name); 987 $("#internal-" + id).html(""); 988 $("#menu-" + id + " a").removeClass("active"); 989 $("#menu-" + id + " a") 990 .children() 991 .removeClass("tabLoaded"); 992 $("#internal-" + id).removeClass("loaded show"); 993 $("#menu-" + id).removeClass("active"); 994 setTabInfo(id, "loaded", false); 995 break; 996 case 1: 997 case "1": 998 case "iframe": 999 organizrConsole("Tab Function", "Closing tab: " + tab); 1000 $("#menu-" + id + " a").removeClass("active"); 1001 $("#menu-" + id + " a") 1002 .children() 1003 .removeClass("tabLoaded"); 1004 $("#container-" + id).removeClass("loaded show"); 1005 $("#frame-" + id).remove(); 1006 setTabInfo(id, "loaded", false); 1007 break; 1008 case 2: 1009 case 3: 1010 case "2": 1011 case "3": 1012 case "_blank": 1013 case "popout": 1014 break; 1015 default: 1016 organizrConsole("Tab Function", "Action not set", "error"); 1017 } 1018 } 1019 } 1020} 1021function reloadTab(id) { 1022 let tabInfo = findTab(id); 1023 if (!tabInfo) { 1024 organizrConsole( 1025 "Reload Tab Function", 1026 "No Tab Info Found... Id: " + id, 1027 "error" 1028 ); 1029 return false; 1030 } 1031 $("#preloader").fadeIn(); 1032 organizrConsole("Tab Function", "Reloading tab: " + tabInfo.name); 1033 switch (tabInfo.type) { 1034 case 0: 1035 case "0": 1036 case "internal": 1037 if (tabInfo.access_url == "api/v2/page/homepage") { 1038 organizrConsole( 1039 "Organizr Function", 1040 "Clearing All Homepage AJAX calls" 1041 ); 1042 clearAJAX("homepage"); 1043 $.xhrPool.abortAll(); 1044 } 1045 $("#frame-" + id).html(""); 1046 loadInternal(id); 1047 break; 1048 case 1: 1049 case "1": 1050 case "iframe": 1051 $("#frame-" + id).attr("src", $("#frame-" + id).attr("src")); 1052 break; 1053 case 2: 1054 case 3: 1055 case "2": 1056 case "3": 1057 case "_blank": 1058 case "popout": 1059 break; 1060 default: 1061 organizrConsole("Tab Function", "Action not set", "error"); 1062 } 1063 $("#preloader").fadeOut(); 1064} 1065function reloadCurrentTab() { 1066 //$("#preloader").fadeIn(); 1067 organizrConsole("Tab Function", "Reloading Current tab"); 1068 let id = null; 1069 let iframe = $(".iFrame-listing").find(".show"); 1070 let internal = $(".internal-listing").find(".show"); 1071 if (iframe.length > 0) { 1072 var type = "iframe"; 1073 } else if (internal.length > 0) { 1074 var type = "internal"; 1075 } else { 1076 var type = "not set"; 1077 } 1078 switch (type) { 1079 case 0: 1080 case "0": 1081 case "internal": 1082 let activeInternal = $(".internal-listing").find(".show"); 1083 if (activeInternal) { 1084 id = activeInternal.attr("id"); 1085 id = id.split("-")[1]; 1086 } 1087 if (id) { 1088 var tabInfo = findTab(id); 1089 if (!tabInfo) { 1090 organizrConsole( 1091 "Reload Current Tab Function", 1092 "No Tab Info Found... Id: " + id, 1093 "error" 1094 ); 1095 return false; 1096 } 1097 } else { 1098 return false; 1099 } 1100 if (tabInfo.access_url == "api/v2/page/homepage") { 1101 organizrConsole( 1102 "Organizr Function", 1103 "Clearing All Homepage AJAX calls" 1104 ); 1105 clearAJAX("homepage"); 1106 $.xhrPool.abortAll(); 1107 } 1108 $(activeInternal).html(""); 1109 loadInternal(id); 1110 break; 1111 case 1: 1112 case "1": 1113 case "iframe": 1114 let activeFrame = $(".iFrame-listing").find(".show").children("iframe"); 1115 if (RegExp("^/.*").test(activeFrame.attr("src"))) { 1116 activeFrame.attr("src", activeFrame[0].contentWindow.location.pathname); 1117 } else { 1118 activeFrame.attr("src", activeFrame.attr("src")); 1119 } 1120 break; 1121 case 2: 1122 case 3: 1123 case "2": 1124 case "3": 1125 case "_blank": 1126 case "popout": 1127 break; 1128 default: 1129 console.error("Tab Function: Action not set"); 1130 } 1131 //$("#preloader").fadeOut(); 1132} 1133function loadNextTab(loadNextTabIfNotLoaded = false) { 1134 let next = $("#page-wrapper").find(".loaded").attr("id"); 1135 if (next) { 1136 next = next.split("-")[1]; 1137 } 1138 if (typeof next !== "undefined") { 1139 let parent = $("#menu-" + next).parent(); 1140 if ( 1141 parent.hasClass("in") === false && 1142 parent.hasClass("nav-second-level") 1143 ) { 1144 parent.parent().find("a").first().trigger("click"); 1145 } 1146 switchTab(next); 1147 } else { 1148 if (loadNextTabIfNotLoaded) { 1149 if (findTab(0, "type")) { 1150 var id = findTab(0, "type")["id"]; 1151 } else { 1152 var id = findTab(1, "type")["id"]; 1153 } 1154 tabActions(1, id); 1155 } else { 1156 organizrConsole("Tab Function", "No Available Tab to open", "error"); 1157 } 1158 } 1159} 1160function closeCurrentTab(event) { 1161 let extra = ""; 1162 let split = ""; 1163 if (typeof event !== "undefined") { 1164 if (event.ctrlKey && event.altKey && !event.shiftKey) { 1165 extra = "-right"; 1166 split = true; 1167 } 1168 } 1169 if ($(".plugin-listing").hasClass("show")) { 1170 hideFrames(split); 1171 loadNextTab(); 1172 return false;
1173 } 1174 let id = $("body").attr("data-active-tab-id"); 1175 let tabInfo = findTab(id); 1176 if (!tabInfo) { 1177 organizrConsole( 1178 "Close Current Tab Function", 1179 "No Tab Info Found... Id: " + id, 1180 "error" 1181 ); 1182 return false; 1183 } 1184 var iframe = $(".iFrame-listing" + extra).find(".show"); 1185 var internal = $(".internal-listing" + extra).find(".show"); 1186 if (iframe.length > 0) { 1187 var type = "iframe"; 1188 } else if (internal.length > 0) { 1189 var type = "internal"; 1190 } else { 1191 var type = "not set"; 1192 } 1193 switch (type) { 1194 case 0: 1195 case "0": 1196 case "internal": 1197 // quick check if homepage 1198 if (tabInfo.access_url == "api/v2/page/homepage") { 1199 organizrConsole( 1200 "Organizr Function", 1201 "Clearing All Homepage AJAX calls" 1202 ); 1203 clearAJAX("homepage"); 1204 $.xhrPool.abortAll(); 1205 } 1206 organizrConsole("Organizr Function", "Closing tab: " + tabInfo.name); 1207 $("#internal" + extra + "-" + id).html(""); 1208 $("#menu-" + id + " a").removeClass("active"); 1209 $("#menu-" + id + " a") 1210 .children() 1211 .removeClass("tabLoaded"); 1212 $("#internal" + extra + "-" + id).removeClass("loaded show"); 1213 $("#menu-" + id).removeClass("active"); 1214 setTabInfo(id, "loaded", false); 1215 setTabInfo(id, "active", false); 1216 loadNextTab(); 1217 break; 1218 case 1: 1219 case "1": 1220 case "iframe": 1221 organizrConsole("Organizr Function", "Closing tab: " + tabInfo.name); 1222 $("#menu-" + id + " a").removeClass("active"); 1223 $("#menu-" + id + " a") 1224 .children() 1225 .removeClass("tabLoaded"); 1226 $("#container" + extra + "-" + id) 1227 .removeClass("loaded show") 1228 .addClass("hidden"); 1229 $("#frame" + extra + "-" + id).remove(); 1230 setTabInfo(id, "loaded", false); 1231 setTabInfo(id, "active", false); 1232 loadNextTab(); 1233 break; 1234 case 2: 1235 case 3: 1236 case "2": 1237 case "3": 1238 case "_blank": 1239 case "popout": 1240 break; 1241 default: 1242 organizrConsole("Tab Function", "No Available Tab to open", "error"); 1243 } 1244} 1245function openInNewBrowserTab() { 1246 let id = $("body").attr("data-active-tab-id"); 1247 let tabInfo = findTab(id); 1248 if (!tabInfo) { 1249 organizrConsole( 1250 "Open In New Browser Tab Function", 1251 "No Tab Info Found... Id: " + id, 1252 "error" 1253 ); 1254 return false; 1255 } 1256 let url = tabInfo.access_url; 1257 window.open(url, "_blank"); 1258} 1259function findTab(query, term = "id") { 1260 let tabInfo = activeInfo.tabs.filter((tab) => tab[term] == query); 1261 return tabInfo.length >= 1 ? tabInfo[0] : false; 1262} 1263function tabActions(event, id, redirectURL = "") { 1264 if (event.which == 3) { 1265 return false; 1266 } 1267 let tabInfo = findTab(id); 1268 if (!tabInfo) { 1269 organizrConsole( 1270 "Tab Action Function", 1271 "No Tab Info Found... Id: " + id, 1272 "error" 1273 ); 1274 return false; 1275 } 1276 let type = tabInfo.type; 1277 let name = tabInfo.name; 1278 if ((event.ctrlKey && !event.shiftKey && !event.altKey) || event.which == 2) { 1279 popTab(id); 1280 } else if (event.altKey && !event.shiftKey && !event.ctrlKey) { 1281 closeTab(id); 1282 } else if (event.shiftKey && !event.ctrlKey && !event.altKey) { 1283 reloadTab(id); 1284 } else if (event.ctrlKey && event.shiftKey && !event.altKey) { 1285 organizrConsole("Tab Function", "Action not defined yet", "info"); 1286 } else if (event.ctrlKey && event.altKey && !event.shiftKey) { 1287 organizrConsole("Tab Function", "Action not defined yet", "info"); 1288 switchTab(id, true); 1289 } else if (event.shiftKey && event.altKey && !event.ctrlKey) { 1290 organizrConsole("Tab Function", "Action not defined yet", "info"); 1291 } else { 1292 switchTab(id); 1293 if (type !== 2) { 1294 $(".splash-screen").removeClass("in").addClass("hidden"); 1295 } 1296 if (redirectURL) { 1297 $(".close-popup").trigger("click"); 1298 $("#frame-" + id).attr("src", redirectURL); 1299 } 1300 } 1301} 1302function reverseObject(object) { 1303 var newObject = {}; 1304 var keys = []; 1305 for (var key in object) { 1306 keys.push(key); 1307 } 1308 for (var i = keys.length - 1; i >= 0; i--) { 1309 var value = object[keys[i]]; 1310 newObject[keys[i]] = value; 1311 } 1312 return newObject; 1313} 1314function hasValue(test) { 1315 if (Array.isArray(test) && test[0] !== "") { 1316 return true; 1317 } else { 1318 return false;
1319 } 1320} 1321function arrayContains(needle, arrhaystack) { 1322 return arrhaystack.indexOf(needle) > -1; 1323} 1324/* END NORMAL FUNCTIONS */ 1325/* BUILD FUNCTIONS */ 1326/* END BUILD FUNCTIONS */ 1327/* ORGANIZR API FUNCTIONS */ 1328function selectOptions(options, active) { 1329 var selectOptions = ""; 1330 $.each(options, function (i, v) { 1331 activeTest = active.split(","); 1332 if (activeTest.length > 1) { 1333 var selected = arrayContains(v.value, activeTest) ? "selected" : ""; 1334 } else { 1335 var selected = active.toString() == v.value ? "selected" : ""; 1336 } 1337 var disabled = v.disabled ? " disabled" : ""; 1338 selectOptions += 1339 "<option " + 1340 selected + 1341 disabled + 1342 ' value="' + 1343 v.value + 1344 '">' + 1345 v.name + 1346 "</option>"; 1347 }); 1348 return selectOptions; 1349} 1350function accordionOptions(options, parentID) { 1351 var accordionOptions = ""; 1352 $.each(options, function (i, v) { 1353 var id = v.id; 1354 var extraClass = v.class ? " " + v.class : ""; 1355 var header = v.header ? " " + v.header : ""; 1356 if (typeof v.body == "object") { 1357 if (typeof v.body.length == "undefined") { 1358 var body = buildFormItem(v.body); 1359 } else { 1360 var body = ""; 1361 $.each(v.body, function (int, val) { 1362 body += buildFormItem(val); 1363 }); 1364 } 1365 } else { 1366 var body = v.body; 1367 } 1368 accordionOptions += 1369 ` 1370 <div class="panel"> 1371 <div class="panel-heading" id="` + 1372 id + 1373 `-heading" role="tab"> 1374 <a class="panel-title collapsed" data-toggle="collapse" href="#` + 1375 id + 1376 `-collapse" data-parent="#` + 1377 parentID + 1378 `" aria-expanded="false" aria-controls="` + 1379 id + 1380 `-collapse"><span lang="en">` + 1381 header + 1382 `</span></a> 1383 </div> 1384 <div class="panel-collapse collapse" id="` + 1385 id +
1386 `-collapse" aria-labelledby="` + 1387 id + 1388 `-heading" role="tabpanel" aria-expanded="false" style="height: 0px;"> 1389 <div class="panel-body">` + 1390 body + 1391 `</div> 1392 </div> 1393 </div> 1394 `; 1395 }); 1396 return accordionOptions; 1397} 1398function buildAccordion(array, open = false) { 1399 var items = ""; 1400 var mainId = createRandomString(10); 1401 $.each(array, function (i, v) { 1402 var collapse = open && i == 0 ? "collapse in" : "collapse"; 1403 var collapsed = open && i == 0 ? "" : "collapsed"; 1404 var id = mainId + "-" + i; 1405 items += 1406 ` 1407 <div class="panel"> 1408 <div class="panel-heading bg-org" id="` + 1409 id + 1410 `-heading" role="tab"> <a class="panel-title ` + 1411 collapsed + 1412 `" data-toggle="collapse" href="#` + 1413 id + 1414 `-collapse" data-parent="#` + 1415 mainId + 1416 `" aria-expanded="false" aria-controls="` + 1417 id + 1418 `-collapse"> <span lang="en">` + 1419 v.title + 1420 `</span> </a> </div> 1421 <div class="panel-collapse ` + 1422 collapse + 1423 `" id="` + 1424 id +
1425 `-collapse" aria-labelledby="` + 1426 id + 1427 `-heading" role="tabpanel"> 1428 <div class="panel-body" lang="en"> ` + 1429 v.body + 1430 ` </div> 1431 </div> 1432 </div> 1433 `; 1434 }); 1435 return ( 1436 '<div class="panel-group" id="' + 1437 mainId + 1438 '" aria-multiselectable="true" role="tablist">' + 1439 items + 1440 "</div>" 1441 ); 1442} 1443function buildFormItem(item) { 1444 var placeholder = item.placeholder 1445 ? ' placeholder="' + item.placeholder + '"' 1446 : ""; 1447 var id = item.id ? ' id="' + item.id + '"' : ""; 1448 var type = item.type ? ' data-type="' + item.type + '"' : ""; 1449 var label = item.label ? ' data-label="' + item.label + '"' : ""; 1450 var value = item.value ? ' value="' + item.value + '"' : ""; 1451 var textarea = item.value ? item.value : ""; 1452 var name = item.name ? ' name="' + item.name + '"' : ""; 1453 var extraClass = item.class ? " " + item.class : ""; 1454 var icon = item.icon ? " " + item.icon : ""; 1455 var text = item.text ? " " + item.text : ""; 1456 var attr = item.attr ? " " + item.attr : ""; 1457 var disabled = item.disabled ? " disabled" : ""; 1458 var href = item.href ? ' href="' + item.href + '"' : ""; 1459 var pwd1 = createRandomString(6); 1460 var pwd2 = createRandomString(6); 1461 var pwd3 = createRandomString(6); 1462 var helpInfo = item.help 1463 ? '<div class="collapse" id="help-info-' + 1464 item.name + 1465 '"><blockquote lang="en">' + 1466 item.help + 1467 "</blockquote></div>" 1468 : ""; 1469 var smallLabel = item.smallLabel 1470 ? '<label><span lang="en">' + item.smallLabel + "</span></label>" + helpInfo 1471 : "" + helpInfo; 1472 var pwgMgr = 1473 ` 1474 <input name="disable-pwd-mgr-` + 1475 pwd1 + 1476 `" type="password" id="disable-pwd-mgr-` + 1477 pwd1 + 1478 `" style="display: none;" value="disable-pwd-mgr-` + 1479 pwd1 + 1480 `" /> 1481 <input name="disable-pwd-mgr-` + 1482 pwd2 + 1483 `" type="password" id="disable-pwd-mgr-` + 1484 pwd2 + 1485 `" style="display: none;" value="disable-pwd-mgr-` + 1486 pwd2 + 1487 `" /> 1488 <input name="disable-pwd-mgr-` + 1489 pwd3 + 1490 `" type="password" id="disable-pwd-mgr-` + 1491 pwd3 + 1492 `" style="display: none;" value="disable-pwd-mgr-` + 1493 pwd3 + 1494 `" /> 1495 `; 1496 //+tof(item.value,'c')+` 1497 switch (item.type) { 1498 case "select-input": 1499 return ( 1500 smallLabel + 1501 '<input list="' + 1502 item.name + 1503 'Options" data-changed="false" lang="en" type="text" class="form-control' + 1504 extraClass + 1505 '"' + 1506 placeholder + 1507 value + 1508 id + 1509 name + 1510 disabled + 1511 type + 1512 label + 1513 attr + 1514 ' autocomplete="new-password" /><datalist id="' + 1515 item.name + 1516 'Options">' + 1517 selectOptions(item.options, item.value) + 1518 "</datalist>" 1519 ); 1520 case "input": 1521 case "text": 1522 return ( 1523 smallLabel + 1524 '<input data-changed="false" lang="en" type="text" class="form-control' + 1525 extraClass + 1526 '"' + 1527 placeholder + 1528 value + 1529 id + 1530 name + 1531 disabled + 1532 type + 1533 label + 1534 attr + 1535 ' autocomplete="new-password" />' 1536 ); 1537 case "number": 1538 return ( 1539 smallLabel + 1540 '<input data-changed="false" lang="en" type="number" class="form-control' + 1541 extraClass + 1542 '"' + 1543 placeholder + 1544 value + 1545 id + 1546 name + 1547 disabled + 1548 type + 1549 label + 1550 attr + 1551 ' autocomplete="new-password" />' 1552 ); 1553 case "textbox": 1554 return ( 1555 smallLabel + 1556 '<textarea data-changed="false" class="form-control' + 1557 extraClass + 1558 '"' + 1559 placeholder + 1560 id + 1561 name + 1562 disabled + 1563 type + 1564 label + 1565 attr + 1566 ' autocomplete="new-password">' + 1567 textarea + 1568 "</textarea>" 1569 ); 1570 case "password": 1571 return ( 1572 smallLabel + 1573 pwgMgr + 1574 '<input data-changed="false" lang="en" type="password" class="form-control' + 1575 extraClass + 1576 '"' + 1577 placeholder + 1578 value + 1579 id + 1580 name + 1581 disabled + 1582 type + 1583 label + 1584 attr + 1585 ' autocomplete="new-password" />' 1586 ); 1587 case "password-alt": 1588 return ( 1589 smallLabel + 1590 '<div class="input-group">' + 1591 pwgMgr + 1592 '<input data-changed="false" lang="en" type="password" class="password-alt form-control' + 1593 extraClass + 1594 '"' + 1595 placeholder + 1596 value + 1597 id + 1598 name + 1599 disabled + 1600 type + 1601 label + 1602 attr + 1603 ' autocomplete="new-password" /><span class="input-group-btn"> <button class="btn btn-default showPassword" type="button"><i class="fa fa-eye passwordToggle"></i></button></span></div>' 1604 ); 1605 case "password-alt-copy": 1606 return ( 1607 smallLabel + 1608 '<div class="input-group">' + 1609 pwgMgr + 1610 '<input data-changed="false" lang="en" type="password" class="password-alt form-control' + 1611 extraClass + 1612 '"' + 1613 placeholder + 1614 value + 1615 id + 1616 name + 1617 disabled + 1618 type + 1619 label + 1620 attr + 1621 ' autocomplete="new-password" /><span class="input-group-btn"> <button class="btn btn-primary clipboard" type="button" data-clipboard-text="' + 1622 item.value + 1623 '"><i class="fa icon-docs"></i></button></span><span class="input-group-btn"> <button class="btn btn-inverse showPassword" type="button"><i class="fa fa-eye passwordToggle"></i></button></span></div>' 1624 ); 1625 case "hidden": 1626 return ( 1627 '<input data-changed="false" lang="en" type="hidden" class="form-control' + 1628 extraClass + 1629 '"' + 1630 placeholder + 1631 value + 1632 id + 1633 name + 1634 disabled + 1635 type + 1636 label + 1637 attr + 1638 " />" 1639 ); 1640 case "select": 1641 return ( 1642 smallLabel + 1643 '<select data-changed="false" class="form-control' + 1644 extraClass + 1645 '"' + 1646 placeholder + 1647 value + 1648 id + 1649 name + 1650 disabled + 1651 type + 1652 label + 1653 attr + 1654 ">" + 1655 selectOptions(item.options, item.value) + 1656 "</select>" 1657 ); 1658 case "select2": 1659 var select2ID = item.id ? "#" + item.id : "." + item.name; 1660 let settings = item.settings ? item.settings : "{}"; 1661 return ( 1662 smallLabel + 1663 '<select class="m-b-10 ' + 1664 extraClass + 1665 '"' + 1666 placeholder + 1667 value + 1668 id + 1669 name + 1670 disabled + 1671 type + 1672 label + 1673 attr + 1674 ' multiple="multiple" data-placeholder="">' + 1675 selectOptions(item.options, item.value) + 1676 '</select><script>$("' + 1677 select2ID + 1678 '").select2(' + 1679 settings + 1680 ').on("select2:unselecting", function() { $(this).data("unselecting", true); }).on("select2:opening", function(e) { if ($(this).data("unselecting")) { $(this).removeData("unselecting"); e.preventDefault(); } });</script>' 1681 ); 1682 case "switch": 1683 case "checkbox": 1684 return ( 1685 smallLabel + 1686 '<input data-changed="false" type="checkbox" class="js-switch' + 1687 extraClass + 1688 '" data-size="medium" data-color="#99d683" data-secondary-color="#f96262"' + 1689 name + 1690 value + 1691 tof(item.value, "c") + 1692 id + 1693 disabled + 1694 type + 1695 label + 1696 attr + 1697 ' /><input data-changed="false" type="hidden"' + 1698 name + 1699 'value="false">' 1700 ); 1701 case "button": 1702 return ( 1703 smallLabel + 1704 '<button class="btn btn-sm btn-success btn-rounded waves-effect waves-light b-none' + 1705 extraClass + 1706 '" ' + 1707 href + 1708 attr + 1709 ' type="button"><span class="btn-label"><i class="' + 1710 icon + 1711 '"></i></span><span lang="en">' + 1712 text + 1713 "</span></button>" 1714 ); 1715 case "blank": 1716 return ""; 1717 case "accordion": 1718 return ( 1719 '<div class="panel-group' + 1720 extraClass + 1721 '"' + 1722 placeholder + 1723 value + 1724 id + 1725 name + 1726 disabled + 1727 type + 1728 label + 1729 attr + 1730 ' aria-multiselectable="true" role="tablist">' + 1731 accordionOptions(item.options, item.id) + 1732 "</div>" 1733 ); 1734 case "html": 1735 return item.html; 1736 case "arrayMultiple": 1737 return '<span class="text-danger">BuildFormItem Class not setup...'; 1738 case "cron": 1739 return `${smallLabel}<div class="input-group"><input data-changed="false" class="form-control ${extraClass}" ${placeholder} ${value} ${id} ${name} ${disabled} ${type} ${label} ${attr} autocomplete="new-password"><span class="input-group-btn"><button class="btn btn-info test-cron" type="button"><i class="fa fa-flask"></i></button></span></div>`; 1740 case "folder": 1741 return `${smallLabel}<div class="input-group"><input data-changed="false" class="form-control ${extraClass}" ${placeholder} ${value} ${id} ${name} ${disabled} ${type} ${label} ${attr} autocomplete="new-password"><span class="input-group-btn"><button class="btn btn-info test-folder" type="button"><i class="fa fa-flask"></i></button></span></div>`; 1742 default: 1743 return '<span class="text-danger">BuildFormItem Class not setup...'; 1744 } 1745} 1746function checkCronFile() { 1747 $(".cron-results-container").removeClass("hidden"); 1748 organizrAPI2("GET", "api/v2/test/cron") 1749 .success(function (data) {
1750 try { 1751 $(".cron-results").text("Cron file is setup correctly"); 1752 } catch (e) { 1753 $(".cron-results").text("Unknown error"); 1754 organizrCatchError(e, data); 1755 } 1756 }) 1757 .fail(function (xhr) { 1758 $(".cron-results").text("Cron file is not setup or is setup incorrectly"); 1759 OrganizrApiError(xhr); 1760 }); 1761} 1762function buildPluginsItem(array, type = "enabled") { 1763 var activePlugins = ""; 1764 var inactivePlugins = ""; 1765 $.each(array, function (i, v) { 1766 var settingsPage = 1767 v.settings == true && type == "enabled" 1768 ? ` 1769 <!-- Plugin Settings Page --> 1770 <form id="` + 1771 v.idPrefix + 1772 `-settings-page" class="mfp-hide white-popup mfp-with-anim addFormTick col-md-10 col-md-offset-1" autocomplete="off"> 1773 <div class="panel bg-org panel-info"> 1774 <div class="panel-heading"> 1775 <span lang="en">` + 1776 v.name + 1777 ` Settings</span> 1778 <button type="button" class="btn bg-org btn-circle close-popup pull-right"><i class="fa fa-times"></i> </button> 1779 <button id="` + 1780 v.idPrefix + 1781 `-settings-page-save" onclick="submitSettingsForm('` + 1782 v.idPrefix + 1783 `-settings-page')" class="btn btn-sm btn-info btn-rounded waves-effect waves-light pull-right hidden animated loop-animation rubberBand m-r-20" type="button"><span class="btn-label"><i class="fa fa-save"></i></span><span lang="en">Save</span></button> 1784 </div> 1785 <div class="panel-wrapper collapse in" aria-expanded="true"> 1786 <div class="bg-org"> 1787 <fieldset id="` + 1788 v.idPrefix + 1789 `-settings-items" style="border:0;" class=""><h2>Loading...</h2></fieldset> 1790 </div> 1791 <div class="clearfix"></div> 1792 </div> 1793 </div> 1794 </form> 1795 ` 1796 : ""; 1797 var href = 1798 v.settings == true 1799 ? "#" + v.idPrefix + "-settings-page" 1800 : "javascript:void(0);"; 1801 if (v.enabled == true) { 1802 var activeToggle = 1803 `<li><a class="btn default btn-outline disablePlugin" href="javascript:void(0);" data-plugin-name="` + 1804 v.name + 1805 `" data-config-prefix="` + 1806 v.configPrefix + 1807 `" data-config-name="` + 1808 v.configPrefix + 1809 `-enabled"><i class="ti-power-off fa-2x"></i></a></li>`; 1810 var settings = 1811 `<li><a class="btn default btn-outline popup-with-form" href="` + 1812 href + 1813 `" data-effect="mfp-3d-unfold"data-plugin-name="` + 1814 v.name + 1815 `" id="` + 1816 v.idPrefix + 1817 `-settings-button" data-config-prefix="` + 1818 v.configPrefix + 1819 `" data-api="${v.api}" data-settings="${v.settings}" data-bind="${v.bind}"><i class="ti-panel fa-2x"></i></a></li>`; 1820 } else { 1821 var activeToggle = 1822 `<li><a class="btn default btn-outline enablePlugin" href="javascript:void(0);" data-plugin-name="` + 1823 v.name + 1824 `" data-config-prefix="` + 1825 v.configPrefix + 1826 `" data-config-name="` + 1827 v.configPrefix + 1828 `-enabled"><i class="ti-plug fa-2x"></i></a></li>`; 1829 var settings = ""; 1830 } 1831 var plugin = 1832 ` 1833 <div class="col-lg-2 col-md-2 col-sm-6 col-xs-6 m-b-10"> 1834 <div class="white-box m-0"> 1835 <div class="el-card-item p-0"> 1836 <div class="el-card-avatar el-overlay-1 m-0"> <img class="lazyload" data-src="` + 1837 v.image + 1838 `"> 1839 <div class="el-overlay"> 1840 <ul class="el-info"> 1841 ${settings} ${activeToggle} 1842 </ul> 1843 </div> 1844 </div> 1845 <div class="el-card-content"> 1846 <h3 class="box-title elip">` + 1847 v.name + 1848 `</h3> 1849 <small class="elip text-uppercase p-b-10">` + 1850 v.category + 1851 `</small> 1852 </div> 1853 </div> 1854 </div> 1855 </div> 1856 `; 1857 if (v.enabled == true) { 1858 activePlugins += plugin + settingsPage; 1859 } else { 1860 inactivePlugins += plugin + settingsPage; 1861 } 1862 }); 1863 activePlugins = 1864 activePlugins.length !== 0 1865 ? activePlugins 1866 : '<h2 class="text-center" lang="en">Nothing Active</h2>'; 1867 inactivePlugins = 1868 inactivePlugins.length !== 0 1869 ? inactivePlugins 1870 : '<h2 class="text-center" lang="en">Everything Active</h2>'; 1871 return type === "enabled" 1872 ? ` 1873 <div class="panel bg-org panel-info"> 1874 <div class="panel-heading"> 1875 <span lang="en">Active Plugins</span> 1876 </div> 1877 <div class="panel-wrapper collapse in" aria-expanded="true"> 1878 <div class="panel-body bg-org"> 1879 <div class="row el-element-overlay m-b-40">` + 1880 activePlugins + 1881 `</div> 1882 </div> 1883 </div> 1884 </div> 1885 <div class="clearfix"></div>` 1886 : ` 1887 <div class="panel bg-org panel-info"> 1888 <div class="panel-heading"> 1889 <span lang="en">Inactive Plugins</span> 1890 </div> 1891 <div class="panel-wrapper collapse in" aria-expanded="true"> 1892 <div class="panel-body bg-org"> 1893 <div class="row el-element-overlay m-b-40">` + 1894 inactivePlugins + 1895 `</div> 1896 </div> 1897 </div> 1898 </div>`; 1899} 1900function buildPluginsItemOld(array) { 1901 var activePlugins = ""; 1902 var inactivePlugins = ""; 1903 $.each(array, function (i, v) { 1904 var settingsPage = 1905 v.settings == true 1906 ? ` 1907 <!-- Plugin Settings Page --> 1908 <form id="` + 1909 v.idPrefix + 1910 `-settings-page" class="mfp-hide white-popup mfp-with-anim addFormTick col-md-10 col-md-offset-1" autocomplete="off"> 1911 <div class="panel bg-org panel-info"> 1912 <div class="panel-heading">
1913 <span lang="en">` + 1914 v.name + 1915 ` Settings</span> 1916 <button type="button" class="btn bg-org btn-circle close-popup pull-right"><i class="fa fa-times"></i> </button> 1917 <button id="` + 1918 v.idPrefix + 1919 `-settings-page-save" onclick="submitSettingsForm('` + 1920 v.idPrefix + 1921 `-settings-page')" class="btn btn-sm btn-info btn-rounded waves-effect waves-light pull-right hidden animated loop-animation rubberBand m-r-20" type="button"><span class="btn-label"><i class="fa fa-save"></i></span><span lang="en">Save</span></button> 1922 </div> 1923 <div class="panel-wrapper collapse in" aria-expanded="true"> 1924 <div class="bg-org"> 1925 <fieldset id="` + 1926 v.idPrefix + 1927 `-settings-items" style="border:0;" class=""><h2>Loading...</h2></fieldset> 1928 </div> 1929 <div class="clearfix"></div> 1930 </div> 1931 </div> 1932 </form> 1933 ` 1934 : ""; 1935 var href = 1936 v.settings == true 1937 ? "#" + v.idPrefix + "-settings-page" 1938 : "javascript:void(0);"; 1939 if (v.enabled == true) { 1940 var activeToggle = 1941 `<li><a class="btn default btn-outline disablePlugin" href="javascript:void(0);" data-plugin-name="` + 1942 v.name + 1943 `" data-config-prefix="` + 1944 v.configPrefix + 1945 `" data-config-name="` + 1946 v.configPrefix + 1947 `-enabled"><i class="ti-power-off fa-2x"></i></a></li>`; 1948 var settings = 1949 `<li><a class="btn default btn-outline popup-with-form" href="` + 1950 href + 1951 `" data-effect="mfp-3d-unfold"data-plugin-name="` + 1952 v.name + 1953 `" id="` + 1954 v.idPrefix + 1955 `-settings-button" data-config-prefix="` + 1956 v.configPrefix + 1957 `" data-api="${v.api}" data-settings="${v.settings}" data-bind="${v.bind}"><i class="ti-panel fa-2x"></i></a></li>`; 1958 } else { 1959 var activeToggle = 1960 `<li><a class="btn default btn-outline enablePlugin" href="javascript:void(0);" data-plugin-name="` + 1961 v.name + 1962 `" data-config-prefix="` + 1963 v.configPrefix + 1964 `" data-config-name="` + 1965 v.configPrefix + 1966 `-enabled"><i class="ti-plug fa-2x"></i></a></li>`; 1967 var settings = ""; 1968 } 1969 var plugin = 1970 ` 1971 <div class="col-lg-2 col-md-2 col-sm-4 col-xs-4"> 1972 <div class="white-box m-0"> 1973 <div class="el-card-item p-0"> 1974 <div class="el-card-avatar el-overlay-1 m-0"> <img class="lazyload" data-src="` + 1975 v.image + 1976 `"> 1977 <div class="el-overlay"> 1978 <ul class="el-info"> 1979 ${settings} ${activeToggle} 1980 </ul> 1981 </div> 1982 </div> 1983 <div class="el-card-content"> 1984 <h3 class="box-title elip">` + 1985 v.name + 1986 `</h3> 1987 <small class="elip text-uppercase p-b-10">` + 1988 v.category + 1989 `</small> 1990 </div> 1991 </div> 1992 </div> 1993 </div> 1994 `; 1995 if (v.enabled == true) { 1996 activePlugins += plugin + settingsPage; 1997 } else { 1998 inactivePlugins += plugin + settingsPage; 1999 } 2000 }); 2001 activePlugins = 2002 activePlugins.length !== 0 2003 ? activePlugins 2004 : '<h2 class="text-center" lang="en">Nothing Active</h2>'; 2005 inactivePlugins = 2006 inactivePlugins.length !== 0 2007 ? inactivePlugins 2008 : '<h2 class="text-center" lang="en">Everything Active</h2>'; 2009 var panes = 2010 ` 2011 <select class="form-control settings-dropdown-box plugin-menu w-100 visible-xs"> 2012 <option value="#settings-plugins-active-anchor" lang="en">Active</option> 2013 <option value="#settings-plugins-inactive-anchor" lang="en">Inactive</option> 2014 <option value="#settings-plugins-marketplace-anchor" lang="en">Marketplace</option> 2015 </select> 2016 <ul class="nav customtab2 nav-tabs nav-non-mobile hidden-xs" data-dropdown="plugin-menu" role="tablist"> 2017 <li onclick="changeSettingsMenu('Settings::Plugins::Active')" role="presentation" class="active"><a id="settings-plugins-active-anchor" href="#settings-plugins-active" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="false"><span class="visible-xs"><i class="ti-file"></i></span><span class="hidden-xs" lang="en">Active</span></a> 2018 </li> 2019 <li onclick="changeSettingsMenu('Settings::Plugins::Inactive')" role="presentation" class=""><a id="settings-plugins-inactive-anchor" href="#settings-plugins-inactive" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="false"><span class="visible-xs"><i class="ti-zip"></i></span><span class="hidden-xs" lang="en">Inactive</span></a> 2020 </li> 2021 <li onclick="changeSettingsMenu('Settings::Plugins::Marketplace');loadMarketplace('plugins');" role="presentation" class=""><a id="settings-plugins-marketplace-anchor" href="#settings-plugins-marketplace" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="false"><span class="visible-xs"><i class="ti-shopping-cart-full"></i></span><span class="hidden-xs" lang="en">Marketplace</span></a> 2022 </li> 2023 </ul> 2024 <!-- Tab panes --> 2025 <div class="tab-content"> 2026 <div role="tabpanel" class="tab-pane fade in active" id="settings-plugins-active"> 2027 <div class="panel bg-org panel-info"> 2028 <div class="panel-heading"> 2029 <span lang="en">Active Plugins</span> 2030 </div> 2031 <div class="panel-wrapper collapse in" aria-expanded="true"> 2032 <div class="panel-body bg-org"> 2033 <div class="row el-element-overlay m-b-40">` + 2034 activePlugins + 2035 `</div> 2036 </div>
2037 </div> 2038 </div> 2039 <div class="clearfix"></div> 2040 </div> 2041 <div role="tabpanel" class="tab-pane fade" id="settings-plugins-inactive"> 2042 <div class="panel bg-org panel-info"> 2043 <div class="panel-heading"> 2044 <span lang="en">Inactive Plugins</span> 2045 </div> 2046 <div class="panel-wrapper collapse in" aria-expanded="true"> 2047 <div class="panel-body bg-org"> 2048 <div class="row el-element-overlay m-b-40">` + 2049 inactivePlugins + 2050 `</div> 2051 </div> 2052 </div> 2053 </div> 2054 </div> 2055 <div role="tabpanel" class="tab-pane fade" id="settings-plugins-marketplace"> 2056 <div class="panel bg-org panel-info"> 2057 <div class="panel-heading"> 2058 <span lang="en">Plugin Marketplace</span> 2059 </div> 2060 <div class="panel-wrapper collapse in" aria-expanded="true"> 2061 <div class="table-responsive"> 2062 <table class="table table-hover manage-u-table"> 2063 <thead> 2064 <tr> 2065 <th width="70" class="text-center" lang="en">PLUGIN</th> 2066 <th></th> 2067 <th lang="en">CATEGORY</th> 2068 <th lang="en">STATUS</th> 2069 <th lang="en" style="text-align:center">INFO</th> 2070 <th lang="en" style="text-align:center">INSTALL</th> 2071 <th lang="en" style="text-align:center">DELETE</th> 2072 </tr> 2073 </thead> 2074 <tbody id="managePluginTable"></tbody> 2075 </table> 2076 </div> 2077 </div> 2078 </div> 2079 </div> 2080 </div> 2081 2082 `; 2083 2084 return panes; 2085} 2086function loadMarketplace(type) { 2087 marketplaceJSON(type) 2088 .success(function (data) { 2089 try { 2090 var response = JSON.parse(data); 2091 } catch (e) { 2092 organizrCatchError(e, data); 2093 } 2094 switch (type) { 2095 case "plugins": 2096 loadMarketplacePluginsItems(response); 2097 break; 2098 case "themes": 2099 loadMarketplaceThemesItems(response); 2100 break; 2101 default: 2102 } 2103 }) 2104 .fail(function (xhr) { 2105 OrganizrApiError(xhr); 2106 }); 2107} 2108function loadThemeMarketplace() { 2109 $("#manageThemeTable").html( 2110 '<td class="text-center" colspan="12"><i class="fa fa-spin fa-spinner"></i></td>' 2111 ); 2112 organizrAPI2("GET", "api/v2/themes/marketplace") 2113 .success(function (data) { 2114 try { 2115 let response = data.response; 2116 loadMarketplaceThemesItems(response.data); 2117 } catch (e) { 2118 organizrCatchError(e, data); 2119 } 2120 }) 2121 .fail(function (xhr) { 2122 OrganizrApiError(xhr, "loadThemeMarketplace Failed"); 2123 }); 2124} 2125function loadPluginMarketplace() { 2126 $("#managePluginTable").html( 2127 '<td class="text-center" colspan="12"><i class="fa fa-spin fa-spinner"></i></td>' 2128 ); 2129 organizrAPI2("GET", "api/v2/plugins/marketplace") 2130 .success(function (data) { 2131 try { 2132 let response = data.response; 2133 loadMarketplacePluginsItems(response.data); 2134 } catch (e) { 2135 organizrCatchError(e, data); 2136 } 2137 }) 2138 .fail(function (xhr) { 2139 OrganizrApiError(xhr, "loadPluginMarketplace Failed"); 2140 }); 2141} 2142function loadMarketplacePluginsItems(plugins) { 2143 var pluginList = ""; 2144 $.each(plugins, function (i, v) { 2145 if (v.icon == null || v.icon == "") { 2146 v.icon = "test.png"; 2147 } 2148 var installButton = 2149 v.status == "Update Available" ? "fa fa-download" : "fa fa-plus"; 2150 var removeButton = v.status == "Not Installed" ? "disabled" : ""; 2151 v.name = i; 2152 pluginList += 2153 ` 2154 <tr class="pluginManagement" data-name="${i}" data-version="${v.version}" data-repo="${v.repo}"> 2155 <td class="text-center el-element-overlay"> 2156 <div class="el-card-item p-0"> 2157 <div class="el-card-avatar el-overlay-1 m-0"> 2158 <img alt="user-img" src="` + 2159 v.icon + 2160 `" width="45"> 2161 </div> 2162 </div> 2163 </td> 2164 <td>` + 2165 i + 2166 ` 2167 <br><span class="text-muted">` +
2168 v.version + 2169 `</span> 2170 <br><span class="text-muted">` + 2171 v.author + 2172 `</span> 2173 </td> 2174 <td>` + 2175 v.category + 2176 `</td> 2177 <td lang="en">` + 2178 v.status + 2179 `</td> 2180 <td style="text-align:center"><button type="button" onclick='aboutPlugin(` + 2181 JSON.stringify(v) + 2182 `);' class="btn btn-success btn-outline btn-circle btn-lg popup-with-form" href="#about-plugin-form" data-effect="mfp-3d-unfold"><i class="fa fa-info"></i></button></td> 2183 <td style="text-align:center"><button type="button" onclick='installPlugin("` + 2184 cleanClass(i) + 2185 `");' class="btn btn-info btn-outline btn-circle btn-lg"><i class="` + 2186 installButton + 2187 `"></i></button></td> 2188 <td style="text-align:center"><button type="button" onclick='removePlugin("` + 2189 cleanClass(i) + 2190 `");' class="btn btn-danger btn-outline btn-circle btn-lg" ` + 2191 removeButton + 2192 `><i class="fa fa-tras
2192h"></i></button></td> 2193 </tr> 2194 `; 2195 }); 2196 $("#managePluginTable").html(pluginList); 2197} 2198 2199function getRepoUsernameAndRepoName(repo) { 2200 let parts = repo.split("/"); 2201 if (parts.length) { 2202 return parts[parts.length - 2] + "/" + parts[parts.length - 1]; 2203 } else { 2204 return repo; 2205 } 2206} 2207 2208function loadMarketplaceThemesItems(themes) { 2209 var themeList = ""; 2210 $.each(themes, function (i, v) { 2211 if (v.icon == null || v.icon == "") { 2212 v.icon = "test.png"; 2213 } 2214 //v.status = themeStatus(i,v.version); 2215 var installButton = 2216 v.status == "Update Available" ? "fa fa-download" : "fa fa-plus"; 2217 var removeButton = v.status == "Not Installed" ? "disabled" : ""; 2218 let category = 2219 v.repo == "https://github.com/Organizr/Organizr-Themes" 2220 ? "Official" 2221 : "3rd Party"; 2222 let categoryTooltip = getRepoUsernameAndRepoName(v.repo); 2223 v.name = i; 2224 let cleanName = i.replace(/_/gi, " "); 2225 themeList += ` 2226 <tr class="themeManagement" data-name="${i}" data-version="${ 2227 v.version 2228 }"> 2229 <td class="text-center el-element-overlay"> 2230 <div class="el-card-item p-0"> 2231 <div class="el-card-avatar el-overlay-1 m-0"> 2232 <img alt="user-img" src="${v.icon}" width="45"> 2233 </div> 2234 </div> 2235 </td> 2236 <td>${cleanName} 2237 <br><span class="text-muted">${v.version}</span> 2238 <br><span class="text-muted">${v.author}</span> 2239 </td> 2240 <td><span data-toggle="tooltip" title="${categoryTooltip}" data-placement="bottom">${category}</span></td> 2241 <td lang="en">${v.status}</td> 2242 <td style="text-align:center"><button type="button" onclick='aboutTheme(${JSON.stringify( 2243 v 2244 )});' class="btn btn-success btn-outline btn-circle btn-lg popup-with-form" href="#about-theme-form" data-effect="mfp-3d-unfold"><i class="fa fa-info"></i></button></td> 2245 <td style="text-align:center"><button type="button" onclick='installTheme("${cleanClass( 2246 i 2247 )}");themeAnalytics("${ 2248 v.name 2249 }");' class="btn btn-info btn-outline btn-circle btn-lg"><i class="${installButton}"></i></button></td> 2250 <td style="text-align:center"><button type="button" onclick='removeTheme("${cleanClass( 2251 i 2252 )}");' class="btn btn-danger btn-outline btn-circle btn-lg" ${removeButton}><i class="fa fa-trash"></i></button></td> 2253 </tr> 2254 `; 2255 }); 2256 $("#manageThemeTable").html(themeList); 2257} 2258function aboutPluginImages(images) { 2259 var imageList = ""; 2260 if (Object.keys(images).length !== 0) { 2261 var imageCount = 0; 2262 $.each(images, function (i, v) { 2263 imageCount++; 2264 var active = imageCount == 1 ? "active" : ""; 2265 imageList += 2266 ` 2267 <div class="` + 2268 active + 2269 ` item"> 2270 <div class="overlaybg"><img src="` + 2271 v + 2272 `" /></div> 2273 <div class="news-content"><span class="label label-info label-rounded">` + 2274 i + 2275 `</span></div> 2276 </div> 2277 `; 2278 }); 2279 } else { 2280 imageList += ` 2281 <div class="active item"> 2282 <div class="overlaybg"><img src="https://via.placeholder.com/350x150" /></div> 2283 </div> 2284 `; 2285 } 2286 return imageList; 2287} 2288function aboutPluginFiles(fileList) { 2289 var files = []; 2290 $.each(fileList, function (i, v) { 2291 var splitFiles = v.split("|"); 2292 var formattedSplit = []; 2293 $.each(splitFiles, function (i, v) { 2294 var arrayFilePush = { 2295 text: v, 2296 }; 2297 formattedSplit.push(arrayFilePush); 2298 }); 2299 var arrayPush = { 2300 text: i, 2301 nodes: formattedSplit, 2302 }; 2303 files.push(arrayPush); 2304 }); 2305 return files; 2306} 2307function pluginFileList(fileList, folder, type) { 2308 var files = []; 2309 $.each(fileList, function (i, v) { 2310 var splitFiles = v.split("|"); 2311 var formattedSplit = [];
2312 var prePath = i.length !== 1 ? i + "/" : i; 2313 $.each(splitFiles, function (i, v) { 2314 var arrayPush = { 2315 fileName: v, 2316 path: prePath, 2317 githubPath: 2318 "https://raw.githubusercontent.com/causefx/Organizr/v2-" + 2319 type + 2320 "/" + 2321 folder + 2322 prePath + 2323 v, 2324 }; 2325 files.push(arrayPush); 2326 }); 2327 }); 2328 return files; 2329} 2330function aboutTheme(theme) { 2331 var files = aboutPluginFiles(theme.files); 2332 var imageList = aboutPluginImages(theme.images); 2333 var homepageLink = 2334 theme.website !== "" || theme.website !== null 2335 ? "onclick=\"window.open('" + theme.website + "','_blank');\"" 2336 : " "; 2337 2338 var infoBox = 2339 ` 2340 <div class="row"> 2341 <div class="col-lg-6 col-sm-12 col-xs-12"> 2342 <div class="row"> 2343 <div class="col-lg-12 col-sm-12 col-xs-12"> 2344 <div class="white-box p-10" id="aboutThemeScroll"> 2345 ` + 2346 theme.description + 2347 ` 2348 </div> 2349 </div> 2350 <div class="clearfix"> </div> 2351 <div class="col-lg-4 col-sm-4 col-xs-12"> 2352 <div class="white-box mouse"> 2353 <ul class="list-inline two-part text-center m-b-0"> 2354 <li><i class="icon-envelope-open text-info"></i></li> 2355 </ul> 2356 </div> 2357 </div> 2358 <div class="col-lg-4 col-sm-4 col-xs-12"> 2359 <div class="white-box mouse" ` + 2360 homepageLink + 2361 `> 2362 <ul class="list-inline two-part text-center m-b-0"> 2363 <li><i class="icon-home text-danger"></i></li> 2364 </ul> 2365 </div> 2366 </div> 2367 <div class="col-lg-4 col-sm-4 col-xs-12"> 2368 <div class="white-box mouse" onclick="$('.themeFileList').toggleClass('hidden');"> 2369 <ul class="list-inline two-part text-center m-b-0"> 2370 <li><i class="icon-folder text-purple"></i></li> 2371 </ul> 2372 </div> 2373 </div> 2374 <div class="col-sm-12 col-xs-12 themeFileList hidden"> 2375 <div id="treeviewTheme" class=""></div> 2376 </div> 2377 </div> 2378 </div> 2379 <div class="col-lg-6 col-sm-12 col-xs-12"> 2380 <div class="news-slide m-b-15"> 2381 <div class="vcarousel slide"> 2382 <!-- Carousel items --> 2383 <div class="carousel-inner"> 2384 ` + 2385 imageList + 2386 ` 2387 </div> 2388 </div> 2389 </div> 2390 </div> 2391 </div>`; 2392 $("#about-theme-title").html( 2393 theme.name + " <small>" + theme.version + "</small>" 2394 ); 2395 $("#about-theme-body").html(infoBox); 2396 $(".vcarousel").carousel({ 2397 interval: 3000, 2398 }); 2399 $("#treeviewTheme").treeview({ 2400 levels: 1, 2401 expandIcon: "ti-angle-right", 2402 onhoverColor: "rgba(0, 0, 0, 0.05)", 2403 selectedBackColor: "#03a9f3", 2404 collapseIcon: "ti-angle-down", 2405 data: JSON.stringify(files), 2406 }); 2407 $("#aboutThemeScroll").slimScroll({ 2408 height: "225px", 2409 }); 2410} 2411function aboutPlugin(plugin) { 2412 var files = aboutPluginFiles(plugin.files); 2413 var imageList = aboutPluginImages(plugin.images); 2414 var homepageLink = 2415 plugin.website !== "" || plugin.website !== null 2416 ? "onclick=\"window.open('" + plugin.website + "','_blank');\"" 2417 : " "; 2418 2419 var infoBox = 2420 ` 2421 <div class="row"> 2422 <div class="col-lg-6 col-sm-12 col-xs-12"> 2423 <div class="row"> 2424 <div class="col-lg-12 col-sm-12 col-xs-12"> 2425 <div class="white-box p-10" id="aboutPluginScroll"> 2426 ` + 2427 plugin.description + 2428 ` 2429 </div> 2430 </div> 2431 <div class="clearfix"> </div> 2432 <div class="col-lg-4 col-sm-4 col-xs-12"> 2433 <div class="white-box mouse"> 2434 <ul class="list-inline two-part text-center m-b-0"> 2435 <li><i class="icon-envelope-open text-info"></i></li> 2436 </ul> 2437 </div> 2438 </div> 2439 <div class="col-lg-4 col-sm-4 col-xs-12"> 2440 <div class="white-box mouse" ` + 2441 homepageLink + 2442 `> 2443 <ul class="list-inline two-part text-center m-b-0"> 2444 <li><i class="icon-home text-danger"></i></li> 2445 </ul> 2446 </div> 2447 </div> 2448 <div class="col-lg-4 col-sm-4 col-xs-12"> 2449 <div class="white-box mouse" onclick="$('.pluginFileList').toggleClass('hidden');"> 2450 <ul class="list-inline two-part text-center m-b-0"> 2451 <li><i class="icon-folder text-purple"></i></li> 2452 </ul> 2453 </div> 2454 </div> 2455 <div class="col-sm-12 col-xs-12 pluginFileList hidden"> 2456 <div id="treeview5" class=""></div> 2457 </div> 2458 </div> 2459 </div> 2460 <div class="col-lg-6 col-sm-12 col-xs-12">
2461 <div class="news-slide m-b-15"> 2462 <div class="vcarousel slide"> 2463 <!-- Carousel items --> 2464 <div class="carousel-inner"> 2465 ` + 2466 imageList + 2467 ` 2468 </div> 2469 </div> 2470 </div> 2471 </div> 2472 </div>`; 2473 $("#about-plugin-title").html( 2474 plugin.name + " <small>" + plugin.version + "</small>" 2475 ); 2476 $("#about-plugin-body").html(infoBox); 2477 $(".vcarousel").carousel({ 2478 interval: 3000, 2479 }); 2480 $("#treeview5").treeview({ 2481 levels: 1, 2482 expandIcon: "ti-angle-right", 2483 onhoverColor: "rgba(0, 0, 0, 0.05)", 2484 selectedBackColor: "#03a9f3", 2485 collapseIcon: "ti-angle-down", 2486 data: JSON.stringify(files), 2487 }); 2488 $("#aboutPluginScroll").slimScroll({ 2489 height: "225px", 2490 }); 2491} 2492function removePlugin(plugin = null) { 2493 if (plugin == null) { 2494 return false; 2495 } 2496 message( 2497 "Removing Plugin", 2498 plugin, 2499 activeInfo.settings.notifications.position, 2500 "#FFF", 2501 "success", 2502 "5000" 2503 ); 2504 organizrAPI2("DELETE", "api/v2/plugins/manage/" + plugin, {}) 2505 .success(function (data) { 2506 try { 2507 let html = data.response; 2508 loadPluginMarketplace(); 2509 message( 2510 plugin + " Removed", 2511 "", 2512 activeInfo.settings.notifications.position, 2513 "#FFF", 2514 "success", 2515 "5000" 2516 ); 2517 } catch (e) { 2518 organizrCatchError(e, data); 2519 } 2520 }) 2521 .fail(function (xhr) { 2522 OrganizrApiError(xhr, "Removal Failed"); 2523 }); 2524} 2525function removeTheme(theme = null) { 2526 if (theme == null) { 2527 return false; 2528 } 2529 message( 2530 "Removing Theme", 2531 theme, 2532 activeInfo.settings.notifications.position, 2533 "#FFF", 2534 "success", 2535 "5000" 2536 ); 2537 organizrAPI2("DELETE", "api/v2/themes/manage/" + theme, {}) 2538 .success(function (data) { 2539 try { 2540 let html = data.response; 2541 loadThemeMarketplace(); 2542 message( 2543 theme + " Removed", 2544 "", 2545 activeInfo.settings.notifications.position, 2546 "#FFF", 2547 "success", 2548 "5000" 2549 ); 2550 } catch (e) { 2551 organizrCatchError(e, data); 2552 } 2553 }) 2554 .fail(function (xhr) { 2555 OrganizrApiError(xhr, "Removal Failed"); 2556 }); 2557} 2558function installPlugin(plugin = null) { 2559 if (plugin == null) { 2560 return false; 2561 } 2562 message( 2563 "Installing Plugin", 2564 plugin, 2565 activeInfo.settings.notifications.position, 2566 "#FFF", 2567 "success", 2568 "5000" 2569 ); 2570 organizrAPI2("POST", "api/v2/plugins/manage/" + plugin, {}) 2571 .success(function (data) { 2572 try { 2573 var html = data.response; 2574 loadPluginMarketplace(); 2575 message( 2576 plugin + " Installed", 2577 "", 2578 activeInfo.settings.notifications.position, 2579 "#FFF", 2580 "success", 2581 "5000" 2582 ); 2583 } catch (e) { 2584 organizrCatchError(e, data); 2585 } 2586 }) 2587 .fail(function (xhr) { 2588 OrganizrApiError(xhr, "Install Failed"); 2589 }); 2590} 2591function installTheme(theme = null) { 2592 if (theme == null) { 2593 return false; 2594 } 2595 message( 2596 "Installing Theme", 2597 theme, 2598 activeInfo.settings.notifications.position, 2599 "#FFF", 2600 "success", 2601 "5000" 2602 ); 2603 organizrAPI2("POST", "api/v2/themes/manage/" + theme, {}) 2604 .success(function (data) { 2605 try { 2606 var html = data.response; 2607 loadThemeMarketplace(); 2608 message( 2609 theme + " Installed", 2610 "", 2611 activeInfo.settings.notifications.position, 2612 "#FFF", 2613 "success", 2614 "5000" 2615 ); 2616 } catch (e) { 2617 organizrCatchError(e, data); 2618 } 2619 }) 2620 .fail(function (xhr) { 2621 OrganizrApiError(xhr, "Install Failed"); 2622 }); 2623} 2624function pluginStatus(name = null, version = null) { 2625 var installedPlugins = []; 2626 var installedPluginsList = []; 2627 if (activeInfo.settings.misc.installedPlugins !== "") { 2628 installedPlugins = activeInfo.settings.misc.installedPlugins.split("|"); 2629 $.each(installedPlugins, function (i, v) { 2630 var plugin = v.split(":"); 2631 installedPluginsList[plugin[0]] = plugin[1]; 2632 }); 2633 if (typeof installedPluginsList[name] !== "undefined") { 2634 if (version !== installedPluginsList[name]) { 2635 return "Update Available"; 2636 } else { 2637 return "Up to date"; 2638 } 2639 } else { 2640 return "Not Installed"; 2641 } 2642 } else { 2643 return "Not Installed"; 2644 } 2645} 2646function themeStatus(name = null, version = null) { 2647 var installedThemes = []; 2648 var installedThemesList = []; 2649 if (activeInfo.settings.misc.installedThemes !== "") { 2650 installedThemes = activeInfo.settings.misc.installedThemes.split("|"); 2651 $.each(installedThemes, function (i, v) { 2652 var theme = v.split(":"); 2653 installedThemesList[theme[0]] = theme[1]; 2654 }); 2655 if (typeof installedThemesList[name] !== "undefined") { 2656 if (version !== installedThemesList[name]) { 2657 return "Update Available"; 2658 } else { 2659 return "Up to date"; 2660 } 2661 } else { 2662 return "Not Installed"; 2663 } 2664 } else { 2665 return "Not Installed"; 2666 } 2667} 2668function copyHomepageJSON(item) { 2669 organizrAPI2("GET", "api/v2/settings/homepage/" + item + "/debug") 2670 .success(function (data) {
2671 try { 2672 let response = data.response; 2673 let debug = response.data; 2674 clipboard(true, JSON.stringify(debug, null, "\t")); 2675 message( 2676 "", 2677 window.lang.translate("Copied JSON to clipboard"), 2678 activeInfo.settings.notifications.position, 2679 "#FFF", 2680 "success", 2681 "5000" 2682 ); 2683 } catch (e) { 2684 organizrCatchError(e, data); 2685 } 2686 }) 2687 .fail(function (xhr) { 2688 OrganizrApiError(xhr, "Copy JSON Failed"); 2689 }); 2690} 2691function homepageItemFormHTML(v) { 2692 let docs = 2693 typeof v.docs == "undefined" 2694 ? "" 2695 : `<small class="pull-right m-r-5"><a data-toggle="tooltip" title="Go to Support Doc" data-placement="bottom" class="btn btn-circle btn-primary waves-effect waves-light" href="${v.docs}" target="_blank"> <i class="fa-fw fa fa-question-circle"></i></a></small>`; 2696 let debug = typeof v.debug == "undefined" ? false : true; 2697 debug = debug === true ? v.debug : false; 2698 debug = 2699 debug === true 2700 ? `<small class="pull-right m-r-5"><a data-toggle="tooltip" title="Copy JSON Settings" data-placement="bottom" href="javascript:copyHomepageJSON('${v.name}')" class="btn btn-circle btn-info waves-effect waves-light copyHomepageJSON"> <i class="fa-fw ti-clipboard"></i></a></small>` 2701 : ""; 2702 return ( 2703 ` 2704 <a id="editHomepageItemCall" href="#editHomepageItemDiv" class="hidden">homepage item</a> 2705 <form id="homepage-` + 2706 v.name + 2707 `-form" class="white-popup mfp-with-anim homepageForm addFormTick"> 2708 <fieldset style="border:0;" class="col-md-10 col-md-offset-1"> 2709 <div class="panel bg-org panel-info"> 2710 <div class="panel-heading"> 2711 <span class="" lang="en">` + 2712 v.name + 2713 `</span> 2714 <button data-toggle="tooltip" title="Close" data-placement="bottom" type="button" class="btn btn-default btn-circle close-popup pull-right close-editHomepageItemDiv"><i class="fa fa-times"></i> </button> 2715 ${docs}${debug} 2716 <button data-toggle="tooltip" title="Reset" data-placement="bottom" id="homepage-` + 2717 v.name + 2718 `-form-reset" onclick="editHomepageItem('` + 2719 v.name + 2720 `', true)" class="btn btn-inverse btn-circle waves-effect waves-light pull-right hidden m-r-5" type="button"><span class=""><i class="fa fa-undo"></i></span></button> 2721 <button data-toggle="tooltip" title="Save" data-placement="bottom" id="homepage-` + 2722 v.name + 2723 `-form-save" onclick="submitSettingsForm('homepage-` + 2724 v.name + 2725 `-form', true)" class="btn btn-success btn-circle waves-effect waves-light pull-right hidden animated loop-animation rubberBand m-r-5" type="button"><span class=""><i class="fa fa-save"></i></span></button> 2726 </div> 2727 <div class="panel-wrapper collapse in" aria-expanded="true"> 2728 <div class="bg-org"> 2729 ` + 2730 buildFormGroup(v.settings) + 2731 ` 2732 </div> 2733 </div> 2734 </div> 2735 </fieldset> 2736 <div class="clearfix"></div> 2737 </form> 2738 ` 2739 ); 2740} 2741function clearHomepageOriginal() { 2742 $("#editHomepageItem").html(""); 2743} 2744function completeHomepageLoad(item, data) { 2745 /* 2746 if(item == 'CustomHTML'){ 2747 let iteration = 0; 2748 $.each(data.settings, function(i,customItem) { 2749 let iterationString = (parseInt(iteration, 10) + 101).toString().substr(1); 2750 let customEditor = 'customHTML'+iterationString+'Editor'; 2751 let customTextarea = 'customHTML'+iterationString+'Textarea'; 2752 let HTMLMode = ace.require("ace/mode/html").Mode; 2753 customHTMLEditorObject[iterationString] = ace.edit(customEditor); 2754 customHTMLEditorObject[iterationString].session.setMode(new HTMLMode()); 2755 customHTMLEditorObject[iterationString].setTheme("ace/theme/idle_fingers"); 2756 customHTMLEditorObject[iterationString].setShowPrintMargin(false); 2757 customHTMLEditorObject[iterationString].session.on('change', function(delta) { 2758 $('.' + customTextarea).val(customHTMLEditorObject[iterationString].getValue()); 2759 //$('#homepage-CustomHTML-form-save').removeClass('hidden'); 2760 }); 2761 iteration++; 2762 }); 2763 } 2764 */ 2765 pageLoad(); 2766} 2767function editHomepageItem(item, reload = false) { 2768 ajaxloader(".editHomepageItemBox-" + item, "in"); 2769 organizrAPI2("GET", "api/v2/settings/homepage/" + item) 2770 .success(function (data) {
2771 try { 2772 let response = data.response; 2773 let html = homepageItemFormHTML(response.data); 2774 $("#editHomepageItem").html(html); 2775 if (reload) { 2776 ajaxloader(".editHomepageItemBox-" + item); 2777 return false; 2778 } 2779 /*$("#editHomepageItemCall").animatedModal({ 2780 top: '40px', 2781 left: '0px', 2782 color: '#000000eb', 2783 animatedIn: 'bounceInUp', 2784 animatedOut: 'bounceOutDown', 2785 position: 'fixed', 2786 afterClose: function() { 2787 $('body, html').css({'overflow':'hidden'}); 2788 } 2789 });*/ 2790 new Custombox.modal({ 2791 content: { 2792 effect: "slidetogether", 2793 animateFrom: "bottom", 2794 animateTo: "bottom", 2795 target: "#editHomepageItemDiv", 2796 width: "100%", 2797 delay: 0, 2798 fullscreen: true, 2799 clone: false, 2800 onComplete: completeHomepageLoad(item, response.data), 2801 onClose: clearHomepageOriginal, 2802 }, 2803 loader: { active: true }, 2804 }).open(); 2805 //$('#editHomepageItemCall').click(); 2806 } catch (e) { 2807 organizrCatchError(e, data); 2808 } 2809 ajaxloader(".editHomepageItemBox-" + item); 2810 }) 2811 .fail(function (xhr) { 2812 OrganizrApiError(xhr, "Edit Homepage Failed"); 2813 ajaxloader(".editHomepageItemBox-" + item); 2814 }); 2815} 2816function buildHomepageItem(array) { 2817 var listing = ""; 2818 if (Array.isArray(array)) { 2819 $.each(array, function (i, v) { 2820 if (v.enabled) { 2821 listing += 2822 ` 2823 <div class="col-lg-2 col-md-2 col-sm-6 col-xs-6"> 2824 <div class="white-box bg-org m-0"> 2825 <div class="el-card-item p-0 editHomepageItemBox-` + 2826 v.name + 2827 `"> 2828 <div class="el-card-avatar el-overlay-1"> 2829 <a onclick="editHomepageItem('` + 2830 v.name + 2831 `')"><img class="lazyload tabImages mouse" data-src="` + 2832 v.image + 2833 `"></a> 2834 </div> 2835 <div class="el-card-content"> 2836 <h3 class="box-title elip">` + 2837 v.name + 2838 `</h3> 2839 <small class="elip text-uppercase elip">` + 2840 v.category + 2841 `</small><br> 2842 </div> 2843 </div> 2844 </div> 2845 </div> 2846 `; 2847 } 2848 }); 2849 } 2850 return listing; 2851} 2852function buildPluginsOLD() { 2853 organizrAPI2("GET", "api/v2/plugins") 2854 .success(function (data) { 2855 try { 2856 var response = data.response; 2857 } catch (e) { 2858 organizrCatchError(e, data); 2859 } 2860 $("#main-plugin-area").html(buildPluginsItemOLD(response.data)); 2861 }) 2862 .fail(function (xhr) { 2863 OrganizrApiError(xhr); 2864 }); 2865} 2866function buildPlugins(status = "enabled") { 2867 organizrAPI2("GET", "api/v2/plugins/" + status) 2868 .success(function (data) { 2869 try { 2870 var response = data.response; 2871 } catch (e) { 2872 organizrCatchError(e, data); 2873 } 2874 $("#" + status + "-plugin-area").html( 2875 buildPluginsItem(response.data, status) 2876 ); 2877 }) 2878 .fail(function (xhr) { 2879 OrganizrApiError(xhr); 2880 }); 2881} 2882function buildHomepage() { 2883 organizrAPI2("GET", "api/v2/settings/homepage") 2884 .success(function (data) { 2885 try { 2886 var response = data.response; 2887 } catch (e) { 2888 organizrCatchError(e, data); 2889 } 2890 $("#settings-homepage-list").html(buildHomepageItem(response.data)); 2891 }) 2892 .fail(function (xhr) { 2893 OrganizrApiError(xhr); 2894 }); 2895} 2896function buildFormGroup(array) { 2897 var mainCount = 0; 2898 var group = '<div class="tab-content w-100">'; 2899 var uList = 2900 '<div class="vtabs customvtab"><ul class="nav tabs-vertical" role="tablist">'; 2901 $.each(array, function (i, v) { 2902 mainCount++; 2903 var count = 0; 2904 var total = v.length; 2905 var active = mainCount == 1 ? "active" : ""; 2906 var customID = createRandomString(10); 2907 if (i == "custom") { 2908 group += v; 2909 } else { 2910 uList += 2911 `<li role="presentation" class="` + 2912 active + 2913 `"><a href="#` + 2914 customID + 2915 cleanClass(i) + 2916 `" aria-controls="` + 2917 i + 2918 `" role="tab" data-toggle="tab" aria-expanded="false"><span lang="en">` + 2919 i + 2920 `</span></a></li>`; 2921 group += 2922 ` 2923 <!-- FORM GROUP --> 2924 <div role="tabpanel" class="tab-pane fade in ` + 2925 active + 2926 `" id="` + 2927 customID + 2928 cleanClass(i) + 2929 `"> 2930 `; 2931 $.each(v, function (i, v) { 2932 var override = "6"; 2933 if (typeof v.override !== "undefined") { 2934 override = v.override; 2935 } 2936 var arrayMultiple = false;
2937 if (typeof v.type !== "undefined") { 2938 if (v.type == "arrayMultiple") { 2939 arrayMultiple = true; 2940 } 2941 } 2942 count++; 2943 if (count % 2 !== 0) { 2944 group += '<div class="row start">'; 2945 } 2946 var helpID = "#help-info-" + v.name; 2947 var helpTip = v.help 2948 ? '<sup><a class="help-tip" data-toggle="collapse" href="' + 2949 helpID + 2950 '" aria-expanded="true"><i class="m-l-5 fa fa-question-circle text-info" title="Help" data-toggle="tooltip"></i></a></sup>' 2951 : ""; 2952 var builtItems = ""; 2953 if (arrayMultiple == true) { 2954 $.each(v.value, function (index, value) { 2955 if (typeof value === "object") { 2956 builtItems += '<div class="row m-b-40">'; 2957 $.each(value, function (number, formItem) { 2958 let clearfix = 2959 formItem.type == "blank" 2960 ? '<div class="clearfix"></div>' 2961 : ""; 2962 builtItems += ` 2963 <!-- INPUT BOX Yes Multiple --> 2964 <div class="col-md-6 p-b-10"> 2965 <div class="form-group"> 2966 <label class="control-label col-md-12"><span lang="en">${ 2967 formItem.label 2968 }</span>${helpTip}</label> 2969 <div class="col-md-12">${buildFormItem( 2970 formItem 2971 )}</div> <!-- end div --> 2972 </div> 2973 </div> 2974 ${clearfix} 2975 <!--/ INPUT BOX --> 2976 `; 2977 }); 2978 builtItems += "</div>"; 2979 } else { 2980 builtItems += buildFormItem(value); 2981 } 2982 }); 2983 } else { 2984 builtItems = 2985 ` 2986 <!-- INPUT BOX no Multiple--> 2987 <div class="col-md-` + 2988 override + 2989 ` p-b-10"> 2990 <div class="form-group"> 2991 <label class="control-label col-md-12"><span lang="en">${ 2992 v.label 2993 }</span>${helpTip}</label> 2994 <div class="col-md-12"> 2995 ${buildFormItem(v)} 2996 </div> 2997 </div> 2998 </div> 2999 <!--/ INPUT BOX --> 3000 `; 3001 } 3002 group += builtItems; 3003 if (count % 2 == 0 || count == total) { 3004 group += "</div><!--end-->"; 3005 } 3006 }); 3007 group += "</div>"; 3008 } 3009 }); 3010 return uList + "</ul>" + group + "</div>"; 3011} 3012function createImageSwal(attr) { 3013 let title = attr.attr("data-title"); 3014 let fullPath = attr.attr("data-image-path"); 3015 let clipboardText = attr.attr("data-clipboard-text"); 3016 let name = attr.attr("data-image-name"); 3017 let extension = attr.attr("data-image-name-ext"); 3018 let div = 3019 ` 3020 <div class="panel panel-default"> 3021 <div class="panel-heading"><h1><img class="center" src="` + 3022 fullPath + 3023 `" style="height: 50px; width: 50px">` + 3024 title + 3025 `</h1></div> 3026 <div class="panel-wrapper collapse in"> 3027 <div class="panel-body"> 3028 <h5 lang="en">Choose action:</h5> 3029 <div class="button-box"> 3030 <button class="btn btn-info waves-effect waves-light clipboard" type="button" data-clipboard-text="` + 3031 clipboardText + 3032 `"><span class="btn-label"><i class="ti-clipboard"></i></span><span lang="en">Copy to Clipboard</span></button> 3033 <button class="btn btn-danger waves-effect waves-light deleteImage" type="button" data-image-path="` + 3034 fullPath + 3035 `" data-image-name="` + 3036 name + 3037 `" data-image-name-ext="` + 3038 extension + 3039 `"><span class="btn-label"><i class="fa fa-trash"></i></span><span lang="en">Delete</span></button> 3040 </div> 3041 </div> 3042 </div> 3043 </div> 3044 `; 3045 swal({ 3046 content: createElementFromHTML(div),
3047 buttons: false, 3048 className: "bg-org", 3049 }); 3050} 3051function buildImageManagerViewItem(array) { 3052 var imageListing = ""; 3053 if (Array.isArray(array)) { 3054 $.each(array, function (i, v) { 3055 var filepath = v.split("/"); 3056 var name = filepath[filepath.length - 1].split("."); 3057 var clipboardText = v.replace(/ /g, "%20"); 3058 var fileAndExt = filepath[filepath.length - 1]; 3059 imageListing += 3060 ` 3061 <a class="imageManagerItem" href="javascript:void(0);" data-toggle="lightbox" data-gallery="multiimages" data-title="` + 3062 name[0] + 3063 `" data-clipboard-text="` + 3064 clipboardText + 3065 `" data-image-path="` + 3066 v + 3067 `" data-image-name="` + 3068 name[0] + 3069 `" data-image-name-ext="` + 3070 fileAndExt + 3071 `"><img data-toggle="tooltip" title="${name[0]}" data-placement="bottom" data-src="` + 3072 v + 3073 `" alt="tabImage" class="all studio lazyload" /> </a> 3074 `; 3075 }); 3076 } 3077 return imageListing; 3078} 3079function buildImageManagerView() { 3080 organizrAPI2("GET", "api/v2/image") 3081 .success(function (data) { 3082 try { 3083 let response = data.response; 3084 $(".settings-image-manager-list").html( 3085 buildImageManagerViewItem(response.data) 3086 ); 3087 $container = $("#gallery-content-center"); 3088 try { 3089 if (typeof $container.isotope == "undefined") { 3090 $container.isotope({ itemSelector: "img" }); 3091 } else { 3092 $container.isotope({ itemSelector: "img" }); 3093 } 3094 } catch (e) { 3095 $container.isotope("destroy"); 3096 $container.isotope({ itemSelector: "img" }); 3097 } 3098 } catch (e) { 3099 organizrCatchError(e, data); 3100 } 3101 }) 3102 .fail(function (xhr) { 3103 OrganizrApiError(xhr); 3104 }); 3105} 3106function buildPluginsSettings() { 3107 organizrAPI2("GET", "api/v2/settings/plugin") 3108 .success(function (data) { 3109 try { 3110 let response = data.response; 3111 $("#plugin-settings-form").html(buildFormGroup(response.data)); 3112 } catch (e) { 3113 organizrCatchError(e, data); 3114 } 3115 }) 3116 .fail(function (xhr) { 3117 OrganizrApiError(xhr); 3118 }); 3119} 3120function buildThemeSettings() { 3121 organizrAPI2("GET", "api/v2/settings/theme") 3122 .success(function (data) { 3123 try { 3124 let response = data.response; 3125 $("#theme-settings-form").html(buildFormGroup(response.data)); 3126 } catch (e) { 3127 organizrCatchError(e, data); 3128 } 3129 }) 3130 .fail(function (xhr) { 3131 OrganizrApiError(xhr); 3132 }); 3133} 3134function buildCustomizeAppearance() { 3135 organizrAPI2("GET", "api/v2/settings/appearance") 3136 .success(function (data) { 3137 try { 3138 var response = data.response; 3139 } catch (e) { 3140 organizrCatchError(e, data); 3141 } 3142 $("#customize-appearance-form").html(buildFormGroup(response.data)); 3143 $("input.pick-a-color-custom-options").ColorPickerSliders({ 3144 placement: "bottom", 3145 color: "#987654", 3146 hsvpanel: true, 3147 previewformat: "hex", 3148 }); 3149 }) 3150 .fail(function (xhr) { 3151 OrganizrApiError(xhr); 3152 }); 3153} 3154function buildSSO() { 3155 organizrAPI2("GET", "api/v2/settings/sso") 3156 .success(function (data) { 3157 try { 3158 var response = data.response; 3159 } catch (e) { 3160 organizrCatchError(e, data); 3161 } 3162 $("#sso-form").html(buildFormGroup(response.data)); 3163 }) 3164 .fail(function (xhr) { 3165 console.error("Organizr Function: API Connection Failed"); 3166 }); 3167} 3168function buildSettingsMain() { 3169 organizrAPI2("GET", "api/v2/settings/main") 3170 .success(function (data) { 3171 try { 3172 var response = data.response; 3173 } catch (e) { 3174 organizrCatchError(e, data); 3175 } 3176 $("#settings-main-form").html(buildFormGroup(response.data)); 3177 changeAuth(); 3178 }) 3179 .fail(function (xhr) { 3180 OrganizrApiError(xhr); 3181 }); 3182} 3183function buildUserManagement() { 3184 organizrAPI2("GET", "api/v2/users?includeGroups") 3185 .success(function (data) { 3186 try { 3187 var response = data.response; 3188 } catch (e) { 3189 organizrCatchError(e, data); 3190 } 3191 $("#manageUserTable").html(buildUserManagementItem(response.data)); 3192 }) 3193 .fail(function (xhr) { 3194 OrganizrApiError(xhr); 3195 }); 3196} 3197function buildGroupManagement() { 3198 organizrAPI2("GET", "api/v2/groups?includeUsers") 3199 .success(function (data) {
3200 try { 3201 var response = data.response; 3202 } catch (e) { 3203 organizrCatchError(e, data); 3204 } 3205 $("#manageGroupTable").html(buildGroupManagementItem(response.data)); 3206 }) 3207 .fail(function (xhr) { 3208 OrganizrApiError(xhr); 3209 }); 3210} 3211function buildTabEditor() { 3212 organizrAPI2("GET", "api/v2/tabs") 3213 .success(function (data) { 3214 try { 3215 var response = data.response; 3216 } catch (e) { 3217 organizrCatchError(e, data); 3218 } 3219 $("#tabEditorTable").html(buildTabEditorItem(response.data)); 3220 checkTabHomepageItems(); 3221 addTabSortable(); 3222 }) 3223 .fail(function (xhr) { 3224 OrganizrApiError(xhr); 3225 }); 3226} 3227function addTabSortable() { 3228 let el = document.getElementById("tabEditorTable"); 3229 let tabSorter = new Sortable(el, { 3230 handle: ".sort-tabs-handle", 3231 ghostClass: "sortable-ghost", 3232 multiDrag: true, 3233 selectedClass: "multi-selected", 3234 onUpdate: function (evt) { 3235 $("input.order").each(function (idx) { 3236 $(this).val(idx + 1); 3237 }); 3238 newTabsGlobal = $("#submit-tabs-form").serializeToJSON(); 3239 $(".saveTabOrderButton").removeClass("hidden"); 3240 }, 3241 }); 3242} 3243function checkTabHomepageItems() { 3244 var tabList = $(".checkTabHomepageItem"); 3245 $.each(tabList, function (i, v) { 3246 var el = $(v); 3247 var id = el.attr("id"); 3248 var name = el.attr("data-name"); 3249 var url = el.attr("data-url"); 3250 var urlLocal = el.attr("data-url-local"); 3251 checkTabHomepageItem(id, name, url, urlLocal); 3252 }); 3253} 3254function sortHomepageItemHrefs() { 3255 var hrefList = $(".popup-with-form"); 3256 window.hrefList = new Array(); 3257 $.each(hrefList, function (i, v) { 3258 var el = $(v); 3259 var href = el.attr("href"); 3260 if (href.includes("#homepage-")) { 3261 var splitHref = href.split("-"); 3262 window.hrefList[splitHref[1]] = i; 3263 } 3264 }); 3265} 3266function checkTabHomepageItemList(name, url, urlLocal, id, check, tab) { 3267 // might use this later 3268 if (name.includes(check) || url.includes(check) || urlLocal.includes(check)) { 3269 addEditHomepageItem(id, tab); 3270 } 3271} 3272function checkTabHomepageItem(id, name, url, urlLocal) { 3273 name = name.toLowerCase(); 3274 url = url.toLowerCase(); 3275 urlLocal = urlLocal.toLowerCase(); 3276 try { 3277 let urlObject = new URL(url); 3278 if (urlObject.pathname !== "/" && urlObject !== "#") { 3279 url = urlObject.pathname; 3280 } 3281 } catch { 3282 url = url; 3283 } 3284 if ( 3285 name.includes("sonarr") || 3286 url.includes("sonarr") || 3287 urlLocal.includes("sonarr") 3288 ) { 3289 addEditHomepageItem(id, "Sonarr"); 3290 } else if ( 3291 name.includes("radarr") || 3292 url.includes("radarr") || 3293 urlLocal.includes("radarr") 3294 ) { 3295 addEditHomepageItem(id, "Radarr"); 3296 } else if ( 3297 name.includes("lidarr") || 3298 url.includes("lidarr") || 3299 urlLocal.includes("lidarr") 3300 ) { 3301 addEditHomepageItem(id, "Lidarr"); 3302 } else if ( 3303 name.includes("couchpotato") || 3304 url.includes("couchpotato") || 3305 urlLocal.includes("couchpotato") 3306 ) { 3307 addEditHomepageItem(id, "CouchPotato"); 3308 } else if ( 3309 name.includes("sick") || 3310 url.includes("sick") || 3311 urlLocal.includes("sick") 3312 ) { 3313 addEditHomepageItem(id, "SickRage"); 3314 } else if ( 3315 (name.includes("plex") || 3316 url.includes("plex") || 3317 urlLocal.includes("plex")) && 3318 !name.includes("plexpy") 3319 ) { 3320 addEditHomepageItem(id, "Plex"); 3321 } else if ( 3322 name.includes("emby") || 3323 url.includes("emby") || 3324 urlLocal.includes("emby") 3325 ) { 3326 addEditHomepageItem(id, "Emby"); 3327 } else if ( 3328 name.includes("jdownloader") || 3329 url.includes("jdownloader") || 3330 urlLocal.includes("jdownloader") || 3331 name.includes("rsscrawler") || 3332 url.includes("rsscrawler") || 3333 urlLocal.includes("rsscrawler") 3334 ) { 3335 addEditHomepageItem(id, "jDownloader"); 3336 } else if ( 3337 name.includes("sab") || 3338 url.includes("sab") || 3339 urlLocal.includes("sab") 3340 ) { 3341 addEditHomepageItem(id, "SabNZBD"); 3342 } else if ( 3343 name.includes("nzbget") || 3344 url.includes("nzbget") || 3345 urlLocal.includes("nzbget") 3346 ) { 3347 addEditHomepageItem(id, "NZBGet"); 3348 } else if ( 3349 name.includes("transmission") || 3350 url.includes("transmission") || 3351 urlLocal.includes("transmission") 3352 ) { 3353 addEditHomepageItem(id, "Transmission"); 3354 } else if ( 3355 name.includes("qbit") || 3356 url.includes("qbit") || 3357 urlLocal.includes("qbit") 3358 ) { 3359 addEditHomepageItem(id, "qBittorrent"); 3360 } else if ( 3361 name.includes("rtorrent") || 3362 url.includes("rtorrent") || 3363 urlLocal.includes("rtorrent") 3364 ) { 3365 addEditHomepageItem(id, "rTorrent"); 3366 } else if ( 3367 name.includes("utorrent") || 3368 url.includes("utorrent") || 3369 urlLocal.includes("utorrent") 3370 ) { 3371 addEditHomepageItem(id, "utorrent"); 3372 } else if ( 3373 name.includes("deluge") || 3374 url.includes("deluge") || 3375 urlLocal.includes("deluge") 3376 ) { 3377 addEditHomepageItem(id, "Deluge"); 3378 } else if ( 3379 name.includes("ombi") || 3380 url.includes("ombi") || 3381 urlLocal.includes("ombi") 3382 ) { 3383 addEditHomepageItem(id, "Ombi"); 3384 } else if ( 3385 name.includes("healthcheck") || 3386 url.includes("healthcheck") || 3387 urlLocal.includes("healthcheck") 3388 ) { 3389 addEditHomepageItem(id, "HealthChecks"); 3390 } else if ( 3391 name.includes("jackett") || 3392 url.includes("jackett") || 3393 urlLocal.includes("jackett") 3394 ) { 3395 addEditHomepageItem(id, "Jackett"); 3396 } else if ( 3397 name.includes("prowlarr") || 3398 url.includes("prowlarr") || 3399 urlLocal.includes("prowlarr") 3400 ) { 3401 addEditHomepageItem(id, "Prowlarr"); 3402 } else if ( 3403 name.includes("unifi") || 3404 url.includes("unifi") || 3405 urlLocal.includes("unifi") 3406 ) { 3407 addEditHomepageItem(id, "Unifi"); 3408 } else if ( 3409 name.includes("tautulli") || 3410 url.includes("tautulli") || 3411 urlLocal.includes("tautulli") 3412 ) { 3413 addEditHomepageItem(id, "Tautulli"); 3414 } 3415} 3416function addEditHomepageItem(id, type) { 3417 let html = '<i class="ti-home"></i>'; 3418 $("#" + id).html(html); 3419 $("#" + id).attr("onclick", 'editHomepageItem("' + type + '")'); 3420 return false;
3421} 3422function buildCategoryEditor() { 3423 organizrAPI2("GET", "api/v2/tabs") 3424 .success(function (data) { 3425 try { 3426 var response = data.response; 3427 } catch (e) { 3428 organizrCatchError(e, data); 3429 } 3430 $("#categoryEditorTable").html(buildCategoryEditorItem(response.data)); 3431 }) 3432 .fail(function (xhr) { 3433 OrganizrApiError(xhr); 3434 }); 3435} 3436/* END ORGANIZR API FUNCTIONS */ 3437function buildLanguage(replace = false, newLang = null) { 3438 var languageItems = ""; 3439 var currentLanguage = getCookie("organizrLanguage") 3440 ? getCookie("organizrLanguage") 3441 : window.lang.currentLang; 3442 var newLangCode = ""; 3443 $.each(languageList, function (i, v) { 3444 if (newLang === v.language) { 3445 newLangCode = v.code; 3446 } 3447 var active = v.code == currentLanguage ? "" : ""; 3448 languageItems += 3449 ` 3450 <a onclick="window.lang.change('` + 3451 v.code + 3452 `');buildLanguage(true,'` + 3453 v.language + 3454 `')" href="javascript:void(0);" class="` + 3455 active + 3456 `"> 3457 <div class="mail-content"><h5 class="m-0">` + 3458 v.language + 3459 `</h5><span class="mail-desc" lang="en">` + 3460 active + 3461 `</span></div> 3462 </a> 3463 `; 3464 }); 3465 var lang = ` 3466 <li class="dropdown" id="languageDropdown"> 3467 <a class="dropdown-toggle waves-effect waves-light" data-toggle="dropdown" href="#" aria-expanded="false"> <i class="fa fa-language"></i><span></span></a> 3468 <ul class="dropdown-menu mailbox animated bounceInDown language-box"> 3469 <li> 3470 <div class="drop-title" lang="en">Choose Language</div> 3471 </li> 3472 <li> 3473 <div class="message-center default-scrollbar">${languageItems}</div> 3474 </li> 3475 </ul> 3476 <!-- /.dropdown-messages --> 3477 </li> 3478 `; 3479 if (replace == true) { 3480 setLangCookie(newLangCode); 3481 $("#languageDropdown").replaceWith(lang); 3482 message( 3483 "", 3484 window.lang.translate("Changed Language To") + ": " + newLang, 3485 activeInfo.settings.notifications.position, 3486 "#FFF", 3487 "success", 3488 "3500" 3489 ); 3490 } else if (replace == "wizard") { 3491 $(lang).appendTo(".navbar-right"); 3492 } else { 3493 return lang; 3494 } 3495} 3496 3497function updateUserInformation() { 3498 var passwordMatch = true; 3499 var username = $("#accountUsername").val(); 3500 var email = $("#accountEmail").val(); 3501 var password1 = $("#accountPassword1").val(); 3502 var password2 = $("#accountPassword2").val(); 3503 if (password1 != password2) { 3504 passwordMatch = false; 3505 messageSingle( 3506 "", 3507 "Passwords do not match", 3508 activeInfo.settings.notifications.position, 3509 "#FFF", 3510 "error", 3511 "5000" 3512 ); 3513 return false; 3514 } 3515 if (username !== "" && email !== "" && passwordMatch == true) { 3516 var post = { 3517 username: username, 3518 email: email, 3519 }; 3520 if (password1 !== "") { 3521 post["password"] = password1; 3522 } 3523 ajaxloader(".content-wrap", "in"); 3524 organizrAPI2("PUT", "api/v2/users/" + activeInfo.user.userID, post) 3525 .success(function (data) { 3526 try { 3527 var response = data.response; 3528 $.magnificPopup.close(); 3529 messageSingle( 3530 "", 3531 window.lang.translate("User Info Updated"), 3532 activeInfo.settings.notifications.position, 3533 "#FFF", 3534 "success", 3535 "5000" 3536 ); 3537 } catch (e) { 3538 organizrCatchError(e, data); 3539 } 3540 ajaxloader(); 3541 }) 3542 .fail(function (xhr) { 3543 OrganizrApiError(xhr, "Update User"); 3544 ajaxloader(); 3545 }); 3546 } 3547} 3548function twoFA(action, type, secret = null) { 3549 switch (action) { 3550 case "activate": 3551 organizrAPI2("POST", "api/v2/2fa/" + type, {}) 3552 .success(function (data) { 3553 try { 3554 var html = data.response; 3555 } catch (e) { 3556 organizrCatchError(e, data); 3557 } 3558 let div = 3559 ` 3560 <div class="panel panel-default"> 3561 <div class="panel-heading">Enable 2FA: ` + 3562 html.data.type + 3563 `</div> 3564 <div class="panel-wrapper collapse in"> 3565 <div class="panel-body"> 3566 <p class="twofa-modal-image"><img class="center" src="` + 3567 html.data.url + 3568 `"></p> 3569 <h5 class="twofa-modal-secret text-center">` + 3570 html.data.secret + 3571 `</h5> 3572 <div class="form-group m-t-10"> 3573 <div class="input-group" style="width: 100%;"> 3574 <div class="input-group-addon hidden-xs"><i class="ti-lock"></i></div> 3575 <input type="text" class="form-control tfa-input" id="twofa-verify" placeholder="Code" autocomplete="off" autocorrect="off" autocapitalize="off" maxlength="6" spellcheck="false" autofocus="" required=""> 3576 </div> 3577 <br> 3578 <button class="btn btn-block btn-info" onclick="twoFA('verify','google');">Verify</button> 3579 3580 </div> 3581 </div> 3582 </div> 3583 </div> 3584 `; 3585 swal({ 3586 content: createElementFromHTML(div),
3587 buttons: false, 3588 className: "bg-org", 3589 }); 3590 }) 3591 .fail(function (xhr) { 3592 OrganizrApiError(xhr, "2FA"); 3593 }); 3594 break; 3595 case "deactivate": 3596 organizrAPI2("DELETE", "api/v2/2fa") 3597 .success(function (data) { 3598 try { 3599 message( 3600 "2FA Removed", 3601 "", 3602 activeInfo.settings.notifications.position, 3603 "#FFF", 3604 "success", 3605 "5000" 3606 ); 3607 $(".2fa-list").replaceWith(buildTwoFA("internal")); 3608 } catch (e) { 3609 organizrCatchError(e, data); 3610 } 3611 }) 3612 .fail(function (xhr) { 3613 OrganizrApiError(xhr, "2FA"); 3614 }); 3615 break; 3616 case "verify": 3617 var secret = $(".twofa-modal-secret").text(); 3618 var code = $("#twofa-verify").val(); 3619 if (type !== "" && secret !== "" && code !== "") { 3620 organizrAPI2("POST", "api/v2/2fa", { 3621 type: type, 3622 secret: secret, 3623 code: code, 3624 }) 3625 .success(function (data) { 3626 try { 3627 var html = data.response; 3628 message( 3629 "2FA Success", 3630 "Input Code Validated! Saving...", 3631 activeInfo.settings.notifications.position, 3632 "#FFF", 3633 "success", 3634 "5000" 3635 ); 3636 swal.close(); 3637 twoFA("save", type, secret); 3638 } catch (e) { 3639 organizrCatchError(e, data); 3640 } 3641 }) 3642 .fail(function (xhr) { 3643 OrganizrApiError(xhr, "2FA"); 3644 }); 3645 } else { 3646 message( 3647 "2FA Failed", 3648 "Input Code", 3649 activeInfo.settings.notifications.position, 3650 "#FFF", 3651 "warning", 3652 "5000" 3653 ); 3654 } 3655 break; 3656 case "save": 3657 organizrAPI2("PUT", "api/v2/2fa", { type: type, secret: secret }) 3658 .success(function (data) { 3659 try { 3660 var html = data.response; 3661 message( 3662 "2FA Success", 3663 "2FA Saved", 3664 activeInfo.settings.notifications.position, 3665 "#FFF", 3666 "success", 3667 "5000" 3668 ); 3669 $(".2fa-list").replaceWith(buildTwoFA(type)); 3670 } catch (e) { 3671 organizrCatchError(e, data); 3672 } 3673 }) 3674 .fail(function (xhr) { 3675 OrganizrApiError(xhr, "2FA"); 3676 }); 3677 break; 3678 } 3679} 3680function buildTwoFA(current) { 3681 switch (current) { 3682 case "internal": 3683 var option = ` 3684 <div class="col-lg-3 col-sm-6 row-in-br"> 3685 <ul class="col-in"> 3686 <li> 3687 <span class="circle circle-md bg-info"><i class="mdi mdi-webpack mdi-24px"></i></span> 3688 </li> 3689 <li class="col-middle"> 3690 <h5>Organizr Authenticator</h5> 3691 <h5><span lang="en">Current</span></h5> 3692 </li> 3693 </ul> 3694 </div> 3695 <div class="col-lg-3 col-sm-6 row-in-br"> 3696 <ul class="col-in"> 3697 <li> 3698 <span class="circle circle-md bg-info"><i class="fa fa-google"></i></span> 3699 </li> 3700 <li class="col-middle"> 3701 <h5>Google Authenticator</h5> 3702 <h5><a href="javascript:void(0)" onclick="twoFA('activate','google');"><span lang="en">Activate</span></a></h5> 3703 </li> 3704 </ul> 3705 </div> 3706 `; 3707 break; 3708 case "google": 3709 var option = ` 3710 <div class="col-lg-3 col-sm-6 row-in-br"> 3711 <ul class="col-in"> 3712 <li> 3713 <span class="circle circle-md bg-info"><i class="fa fa-google"></i></span> 3714 </li> 3715 <li class="col-middle"> 3716 <h5>Google Authenticator</h5> 3717 <h5><a href="javascript:void(0)" onclick="twoFA('deactivate','google');"><span lang="en">Deactivate</span></a></h5> 3718 </li> 3719 </ul> 3720 </div> 3721 `; 3722 break; 3723 default: 3724 break; 3725 } 3726 var element = 3727 ` 3728 <div class="white-box 2fa-list"> 3729 <div class="row row-in"> 3730 ` + 3731 option + 3732 ` 3733 </div> 3734 </div> 3735 `; 3736 return element; 3737} 3738function scrapeCall() { 3739 // Define the URL to scrape [only supports GET at the moment 3740 var url = "https://api.github.com/users/causefx/repos"; 3741 // Define callbacks variable first 3742 var callbacks = $.Callbacks(); 3743 // Add functions that will deal with the data 3744 callbacks.add(scrapeFunction); 3745 // Call the API function to scrape the page you want [types = 'json' or 'html'] 3746 scrapeAPI(url, callbacks, "json"); 3747} 3748function scrapeFunction(data) { 3749 // Here you would do whatever you like 3750 if (data.data.result == "Success") { 3751 console.log("Success!!!"); 3752 } 3753 console.log("data:"); 3754 console.log(data); 3755} 3756function scrapeAPI(url, callbacks = null, type = null) { 3757 if (typeof url === "undefined") { 3758 console.log("error"); 3759 return false;
3760 } 3761 organizrAPI2("POST", "api/v2/homepage/scrape", { url: url, type: type }) 3762 .success(function (data) { 3763 try { 3764 let response = data.response; 3765 if (response) { 3766 if (callbacks) { 3767 callbacks.fire(response); 3768 } 3769 } 3770 } catch (e) { 3771 organizrCatchError(e, data); 3772 } 3773 }) 3774 .fail(function (xhr) { 3775 OrganizrApiError(xhr, "Scrape"); 3776 }); 3777} 3778function revokeToken(id) { 3779 organizrAPI2("DELETE", "api/v2/token/" + id, {}) 3780 .success(function (data) { 3781 try { 3782 $("#token-" + id).fadeOut(); 3783 message( 3784 window.lang.translate("Removed Token"), 3785 "", 3786 activeInfo.settings.notifications.position, 3787 "#FFF", 3788 "success", 3789 "3500" 3790 ); 3791 } catch (e) { 3792 organizrCatchError(e, data); 3793 } 3794 }) 3795 .fail(function (xhr) { 3796 ajaxloader(); 3797 OrganizrApiError(xhr, "Revoke Token"); 3798 }); 3799} 3800function buildActiveTokens(array) { 3801 var parser = new UAParser(); 3802 var tokens = ""; 3803 $.each(array, function (i, v) { 3804 parser.setUA(v.browser); 3805 var result = parser.getResult(); 3806 var className = 3807 activeInfo.user.token === v.token ? "bg-success text-inverse" : ""; 3808 var extraText = 3809 activeInfo.user.token === v.token 3810 ? '<span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="Current Token">...' + 3811 v.token.substr(-10, 10) + 3812 "</span>" 3813 : v.token.substr(-10, 10); 3814 if (typeof v.created == "object") { 3815 v.created = v.created.date; 3816 } 3817 if (typeof v.expires == "object") { 3818 v.expires = v.expires.date; 3819 } 3820 v.created = v.created.indexOf("Z") !== -1 ? v.created : v.created + "Z"; 3821 v.expires = v.expires.indexOf("Z") !== -1 ? v.expires : v.expires + "Z"; 3822 3823 tokens += 3824 ` 3825 <tr id="token-` + 3826 v.id + 3827 `" class="` + 3828 className + 3829 `"> 3830 <td>` + 3831 v.id + 3832 `</td> 3833 <td>` + 3834 extraText + 3835 `</td> 3836 <td>` + 3837 moment(v.created).format("LLL") + 3838 `</td> 3839 <td>` + 3840 moment(v.expires).format("LLL") + 3841 `</td> 3842 <td>` + 3843 v.ip + 3844 `</td> 3845 <td> 3846 <button class="btn btn-danger waves-effect waves-light" type="button" onclick="revokeToken('` + 3847 v.id + 3848 `');"><i class="fa fa-ban"></i></button> 3849 </td> 3850 </tr> 3851 `; 3852 }); 3853 return ( 3854 ` 3855 <div class="col-lg-12"> 3856 <div class="panel panel-info"> 3857 <div class="panel-heading"> <span lang="en">Active Tokens</span> 3858 <div class="pull-right"><a href="#" data-perform="panel-collapse"><i class="ti-plus"></i></a> </div> 3859 </div> 3860 <div class="panel-wrapper collapse" aria-expanded="true"> 3861 <div class="panel-body bg-org p-0"> 3862 <div class="table-responsive"> 3863 <table class="table color-table info-table"> 3864 <thead> 3865 <tr> 3866 <th>#</th> 3867 <th lang="en">Token</th> 3868 <th lang="en">Created</th> 3869 <th lang="en">Expires</th> 3870 <th lang="en">IP</th> 3871 <th lang="en">Action</th> 3872 </tr> 3873 </thead> 3874 <tbody> 3875 ` + 3876 tokens + 3877 ` 3878 </tbody> 3879 </table> 3880 </div> 3881 </div> 3882 </div> 3883 </div> 3884 </div> 3885 ` 3886 ); 3887} 3888function accountManager(user) { 3889 var passwordMessage = ""; 3890 switch (activeInfo.settings.misc.authBackend) { 3891 case "plex": 3892 passwordMessage = ` 3893 <div class="col-lg-12"> 3894 <div class="panel panel-info"> 3895 <div class="panel-heading"> <span lang="en">Password Notice</span> 3896 <div class="pull-right"><a href="#" data-perform="panel-collapse"><i class="ti-plus"></i></a> </div> 3897 </div> 3898 <div class="panel-wrapper collapse" aria-expanded="true"> 3899 <div class="panel-body bg-org"> 3900 <p lang="en">If you signed in with a Plex Acct... Please use the following link to change your password there:</p><br> 3901 <p><a href="https://app.plex.tv/auth#?resetPassword" target="_blank" lang="en">Change Password on Plex Website</a></p> 3902 </div> 3903 </div> 3904 </div> 3905 </div> 3906 `; 3907 break; 3908 case "emby": 3909 passwordMessage = ` 3910 <div class="col-lg-12"> 3911 <div class="panel panel-info"> 3912 <div class="panel-heading"> <span lang="en">Password Notice</span> 3913 <div class="pull-right"><a href="#" data-perform="panel-collapse"><i class="ti-minus"></i></a> <a href="#" data-perform="panel-dismiss"><i class="ti-close"></i></a> </div> 3914 </div> 3915 <div class="panel-wrapper collapse in" aria-expanded="true"> 3916 <div class="panel-body bg-org"> 3917 <p lang="en">If you signed in with a Emby Acct... Please use the following link to change your password there:</p><br> 3918 <p><a href="https://emby.media/community/index.php?app=core&module=global§ion=lostpass" target="_blank">
3918Change Password on Emby Website</a></p> 3919 </div> 3920 </div> 3921 </div> 3922 </div> 3923 `; 3924 break; 3925 default: 3926 passwordMessage = ""; 3927 break; 3928 } 3929 if (user.data.user.loggedin === true) { 3930 var twoFADisable = 3931 buildTwoFA(user.data.user.authService) == "internal" ? "" : "disabled"; 3932 var activeTokens = buildActiveTokens(user.data.user.tokenList); 3933 var accountDiv = 3934 ` 3935 <div id="account-area" class="white-popup mfp-with-anim mfp-hide"> 3936 <div class="col-md-10 col-md-offset-1"> 3937 <div class="row"> 3938 <div class="col-md-12"> 3939 <div class="panel panel-info m-0"> 3940 <div class="panel-heading"> 3941 <span lang="en">Account Information</span> 3942 <div class="btn-group pull-right"> 3943 <button class="btn btn-info waves-effect waves-light" type="button" onclick="updateUserInformation();"> 3944 <i class="fa fa-save"></i> 3945 </button> 3946 </div> 3947 </div> 3948 <div class="panel-wrapper collapse in main-email-panel" aria-expanded="true"> 3949 <div class="panel-body"> 3950 <div class="form-body"> 3951 ` + 3952 buildTwoFA(user.data.user.authService) + 3953 ` 3954 <div class="row"> 3955 <div class="col-lg-12"> 3956 <div class="panel panel-info"> 3957 <div class="panel-heading"> <span lang="en">User Information</span> 3958 <div class="pull-right"><a href="#" data-perform="panel-collapse"><i class="ti-plus"></i></a> </div> 3959 </div> 3960 <div class="panel-wrapper collapse" aria-expanded="true"> 3961 <div class="panel-body bg-org p-0 p-t-10"> 3962 <div class="col-md-6"> 3963 <div class="form-group"> 3964 <label class="control-label" lang="en">Username</label> 3965 <input ` + 3966 twoFADisable + 3967 ` type="text" id="accountUsername" class="form-control" value="` + 3968 activeInfo.user.username + 3969 `"></div> 3970 </div> 3971 <div class="col-md-6"> 3972 <div class="form-group"> 3973 <label class="control-label" lang="en">Email</label> 3974 <input ` + 3975 twoFADisable + 3976 ` type="text" id="accountEmail" class="form-control" value="` + 3977 activeInfo.user.email + 3978 `"></div> 3979 </div> 3980 <div class="col-md-6 userManagementPassword"> 3981 <div class="form-group"> 3982 <label class="control-label" lang="en">Password</label> 3983 <input type="password" id="accountPassword1" class="form-control"></div> 3984 </div> 3985 <div class="col-md-6 userManagementPassword"> 3986 <div class="form-group"> 3987 <label class="control-label" lang="en">Verify Password</label> 3988 <input type="password" id="accountPassword2" class="form-control"></div> 3989 </div> 3990 </div> 3991 </div> 3992 </div> 3993 </div> 3994 </div> 3995 <!--/row--> 3996 <div class="row"> 3997 ` + 3998 activeTokens + 3999 passwordMessage + 4000 ` 4001 </div> 4002 <!--/row--> 4003 </div> 4004 </div> 4005 </div> 4006 </div> 4007 </div>
4008 </div> 4009 </div> 4010 </div> 4011 `; 4012 $(".organizr-area").after(accountDiv); 4013 pageLoad(); 4014 } 4015} 4016function userMenu(user) { 4017 $("body").attr("data-active-user-group-name", user.data.user.group); 4018 $("body").attr("data-active-user-group-id", user.data.user.groupID); 4019 var sideMenu = ""; 4020 var menuList = 4021 '<li class="hidden-xs" onclick="toggleFullScreen();"><a class="waves-effect waves-light"> <i class="ti-fullscreen fullscreen-icon"></i></a></li>'; 4022 var showDebug = activeInfo.settings.misc.debugArea 4023 ? '<li><a href="javascript:void(0)" onclick="toggleDebug();"><i class="mdi mdi-bug fa-fw"></i> <span lang="en">Debug Area</span></a></li>' 4024 : ""; 4025 menuList += buildLanguage(); 4026 if (user.data.user.loggedin === true) { 4027 menuList += 4028 ` 4029 <li class="dropdown"> 4030 <a class="dropdown-toggle profile-pic" data-toggle="dropdown" href="javascript:void(0)"><img alt="" class="img-circle profile-image" src="` + 4031 user.data.user.image + 4032 `" width="36"><b class="hidden-xs">` + 4033 user.data.user.username + 4034 `</b><span class="caret"></span></a> 4035 <ul class="dropdown-menu dropdown-user animated flipInY"> 4036 <li> 4037 <div class="dw-user-box"> 4038 <div class="u-img"><img alt="user" src="` + 4039 user.data.user.image + 4040 `"></div> 4041 <div class="u-text"><h4>` + 4042 user.data.user.username + 4043 `</h4><p class="text-muted">` + 4044 user.data.user.email + 4045 `</p><p class="text-muted">` + 4046 user.data.user.group + 4047 `</p></div> 4048 </div> 4049 </li> 4050 <li class="divider" role="separator"></li> 4051 <li class="append-menu"><a class="inline-popups" href="#account-area" data-effect="mfp-zoom-out"><i class="ti-settings fa-fw"></i> <span lang="en">Account Settings</span></a></li> 4052 <li class="divider" role="separator"></li> 4053 <li><a href="javascript:void(0)" onclick="lock();"><i class="ti-lock fa-fw"></i> <span lang="en">Lock Screen</span></a></li> 4054 ${showDebug} 4055 <li><a href="javascript:void(0)" onclick="logout();"><i class="fa fa-sign-out fa-fw"></i> <span lang="en">Logout</span></a></li> 4056 </ul><!-- /.dropdown-user --> 4057 </li><!-- /.dropdown --> 4058 `; 4059 sideMenu += 4060 ` 4061 <li class="user-pro"> 4062 <a href="#" class="waves-effect"> 4063 <img src="` + 4064 user.data.user.image + 4065 `" alt="user-img" class="img-circle"> 4066 <span class="hide-menu">` + 4067 user.data.user.username + 4068 `<span class="fa arrow"></span></span> 4069 </a> 4070 <ul class="nav nav-second-level collapse" aria-expanded="false" style="height: 0px;"> 4071 <li class="append-menu"><a class="inline-popups" href="#account-area" data-effect="mfp-zoom-out"><i class="ti-settings fa-fw"></i> <span lang="en">Account Settings</span></a></li> 4072 <li><a href="javascript:void(0)" onclick="lock();"><i class="ti-lock fa-fw"></i> <span lang="en">Lock Screen</span></a></li> 4073 ${showDebug} 4074 <li><a href="javascript:void(0)" onclick="logout();"><i class="fa fa-sign-out fa-fw"></i> <span lang="en">Logout</span></a></li> 4075 </ul> 4076 </li> 4077 `; 4078 } else { 4079 menuList += 4080 ` 4081 <li class="dropdown"> 4082 <a class="dropdown-toggle profile-pic" data-toggle="dropdown" href="javascript:void(0)"><img alt="" class="img-circle profile-image" src="` + 4083 user.data.user.image + 4084 `" width="36"><b class="hidden-xs">` + 4085 user.data.user.username + 4086 `</b><span class="caret"></span></a> 4087 <ul class="dropdown-menu dropdown-user animated flipInY"> 4088 <li> 4089 <div class="dw-user-box"> 4090 <div class="u-img"><img alt="user" src="` + 4091 user.data.user.image + 4092 `"></div> 4093 <div class="u-text"><h4>` + 4094 user.data.user.username + 4095 `</h4></div> 4096 </div> 4097 </li> 4098 <li class="divider" role="separator"></li> 4099 <li class="append-menu"><a href="javascript:void(0)" class="show-login"><i class="fa fa-sign-in fa-fw"></i> <span lang="en">Login/Register</span></a></li> 4100 </ul><!-- /.dropdown-user --> 4101 </li><!-- /.dropdown --> 4102 `; 4103 sideMenu += 4104 ` 4105 <li class="user-pro"> 4106 <a href="#" class="waves-effect"> 4107 <img src="` +
4108 user.data.user.image + 4109 `" alt="user-img" class="img-circle"> 4110 <span class="hide-menu">` + 4111 user.data.user.username + 4112 `<span class="fa arrow"></span></span> 4113 </a> 4114 <ul class="nav nav-second-level collapse" aria-expanded="false" style="height: 0px;"> 4115 <li class="append-menu"><a href="javascript:void(0)" class="show-login"><i class="fa fa-sign-in fa-fw"></i> <span lang="en">Login/Register</span></a></li> 4116 </ul> 4117 </li> 4118 `; 4119 } 4120 $(menuList).appendTo(".navbar-right").html; 4121 //$(sideMenu).appendTo('#side-menu').html; 4122 //message("",window.lang.translate('Welcome')+" "+user.data.user.username,activeInfo.settings.notifications.position,"#FFF","success","3500"); 4123 console.info( 4124 "%c " + 4125 window.lang.translate("Welcome") + 4126 " %c ".concat(user.data.user.username, " "), 4127 "color: white; background: #AD80FD; font-weight: 700;", 4128 "color: #AD80FD; background: white; font-weight: 700;" 4129 ); 4130} 4131function menuExtraTabs() { 4132 return [ 4133 { 4134 id: 99999991, 4135 type: 2, 4136 group_id: 1, 4137 name: "Github Repo", 4138 access_url: "https://github.com/causefx/organizr", 4139 url: "https://github.com/causefx/organizr", 4140 image: "fontawesome::github", 4141 active: activeInfo.settings.menuLink.githubMenuLink, 4142 ping_url: null, 4143 }, 4144 { 4145 id: 99999992, 4146 type: 1, 4147 group_id: 1, 4148 name: "Organizr Support", 4149 access_url: "https://organizr.app/support", 4150 url: "https://organizr.app/support", 4151 image: "fontawesome::life-ring", 4152 active: activeInfo.settings.menuLink.organizrSupportMenuLink, 4153 ping_url: null, 4154 }, 4155 { 4156 id: 99999993, 4157 type: 2, 4158 group_id: 1, 4159 name: "Organizr Docs", 4160 access_url: "https://docs.organizr.app", 4161 url: "https://docs.organizr.app", 4162 image: "simpleline::docs", 4163 active: activeInfo.settings.menuLink.organizrDocsMenuLink, 4164 ping_url: null, 4165 }, 4166 { 4167 id: 99999994, 4168 type: 1, 4169 group_id: 1, 4170 name: "Feature Request", 4171 access_url: "https://feature.organizr.app", 4172 url: "https://feature.organizr.app", 4173 image: "simpleline::arrow-up-circle", 4174 active: activeInfo.settings.menuLink.organizrFeatureRequestLink, 4175 ping_url: null, 4176 }, 4177 ]; 4178} 4179function menuExtras(active) { 4180 let adminMenu = '<li class="devider"></li>'; 4181 let extraOrganizrLinks = menuExtraTabs(); 4182 activeInfo.tabs = [].concat(activeInfo.tabs, menuExtraTabs()); 4183 4184 $.each(extraOrganizrLinks, function (i, v) { 4185 tabInformation[v.id] = { 4186 id: v.id, 4187 name: cleanClass(v.name), 4188 active: false, 4189 loaded: false, 4190 increments: 0, 4191 tabInfo: v, 4192 }; 4193 if (v.type == 1) { 4194 let frame = buildFrameContainer(v.id); 4195 $(frame).appendTo($(".iFrame-listing")); 4196 } 4197 adminMenu += 4198 activeInfo.user.groupID <= v.group_id && v.active 4199 ? buildMenuList(v.id) 4200 : ""; 4201 }); 4202 if (active === true) { 4203 return activeInfo.settings.menuLink.organizrSignoutMenuLink 4204 ? ` 4205 <li class="devider"></li> 4206 <li id="sign-out"><a class="waves-effect" onclick="logout();"><i class="fa fa-sign-out fa-fw"></i> <span class="hide-menu" lang="en">Logout</span></a></li> 4207 ` + adminMenu 4208 : "" + adminMenu; 4209 } else { 4210 return activeInfo.settings.menuLink.organizrSignoutMenuLink 4211 ? ` 4212 <li class="devider"></li> 4213 <li id="menu-login"><a class="waves-effect show-login" href="javascript:void(0)"><i class="mdi mdi-login fa-fw"></i> <span class="hide-menu" lang="en">Login/Register</span></a></li> 4214 ` 4215 : ""; 4216 } 4217} 4218function categoryProcess(arrayItems) { 4219 var menuList = ""; 4220 let categoryIn = activeInfo.settings.misc.expandCategoriesByDefault 4221 ? "in" 4222 : ""; 4223 let categoryActive = activeInfo.settings.misc.expandCategoriesByDefault 4224 ? "active" 4225 : ""; 4226 let categoryExpanded = activeInfo.settings.misc.expandCategoriesByDefault 4227 ? "true" 4228 : "false"; 4229 if ( 4230 Array.isArray(arrayItems["data"]["categories"]) && 4231 Array.isArray(arrayItems["data"]["tabs"]) 4232 ) { 4233 $.each(arrayItems["data"]["categories"], function (i, v) { 4234 if (v.count !== 0 && v.category_id !== 0) { 4235 menuList += 4236 ` 4237 <li class="allGroupsList ` + 4238 categoryActive + 4239 `" data-group-name="` + 4240 cleanClass(v.category) + 4241 `"> 4242 <a class="waves-effect" href="javascript:void(0)">` + 4243 iconPrefix(v.image) + 4244 `<span class="hide-menu">` + 4245 v.category + 4246 ` <span class="fa arrow"></span> <span class="label label-rouded label-inverse pull-right">` + 4247 v.count + 4248 `</span></span><div class="menu-category-ping" data-good="0" data-bad="0"></div></a> 4249 <ul class="nav nav-second-level category-` + 4250 v.category_id + 4251 ` collapse ` + 4252 categoryIn + 4253 `" aria-expanded="` + 4254 categoryExpanded + 4255 `"></ul> 4256 </li> 4257 `; 4258 } 4259 }); 4260 $(menuList).appendTo($("#side-menu")); 4261 } 4262} 4263function buildFrame(id, split = null) { 4264 let extra = split ? "right-" : ""; 4265 let tabInfo = findTab(id); 4266 if (!tabInfo) { 4267 organizrConsole("Build Frame", "No Tab Info Found... Id: " + id, "error"); 4268 return false;
4269 } 4270 var sandbox = activeInfo.settings.misc.sandbox; 4271 sandbox = sandbox.replace(/,/gi, " "); 4272 sandbox = sandbox ? ' sandbox="' + sandbox + '"' : ""; 4273 var allow = activeInfo.settings.misc.iframeAllow; 4274 allow = allow.replace(/,/gi, "; "); 4275 allow = allow ? ' allow="' + allow + '"' : ""; 4276 return ( 4277 ` 4278 <iframe ` + 4279 allow + 4280 ` frameborder="0" id="frame-` + 4281 extra + 4282 id + 4283 `" ` + 4284 sandbox + 4285 ` scrolling="auto" src="` + 4286 tabInfo.access_url + 4287 `" class="iframe"></iframe> 4288 ` 4289 ); 4290} 4291function buildFrameContainer(id, split = null) { 4292 let extra = split ? "right-" : ""; 4293 return ( 4294 `<div id="container-` + 4295 extra + 4296 id + 4297 `" class="frame-container frame-${id} hidden" ></div>` 4298 ); 4299} 4300function buildInternalContainer(id, split = null) { 4301 let extra = split ? "right-" : ""; 4302 return ( 4303 `<div id="internal-` + 4304 extra + 4305 id + 4306 `" class="internal-container frame-${id} hidden"></div>` 4307 ); 4308} 4309function buildMenuList(id) { 4310 let tabInfo = findTab(id); 4311 if (!tabInfo) { 4312 organizrConsole( 4313 "Build Menu List", 4314 "No Tab Info Found... Id: " + id, 4315 "error" 4316 ); 4317 return false; 4318 } 4319 let name = tabInfo.name; 4320 let icon = tabInfo.image; 4321 let ping = typeof tabInfo.ping_url !== "undefined" ? tabInfo.ping_url : null; 4322 ping = 4323 ping !== null && ping !== "" 4324 ? `<small class="menu-` + 4325 cleanClass(ping) + 4326 `-ping-ms hidden-xs label label-rouded label-inverse pull-right pingTime hidden"> 4327</small><div class="menu-` + 4328 cleanClass(ping) + 4329 `-ping" data-tab-name="` + 4330 name + 4331 `" data-previous-state=""></div>` 4332 : ""; 4333 return ( 4334 `<li class="allTabsList" id="menu-${id}" data-tab-id="${id}"><a class="waves-effect" href="javascript:void(0)" onclick="tabActions(event,'${id}');" onauxclick="tabActions(event,'${id}');">` + 4335 iconPrefix(icon) + 4336 `<span class="hide-menu elip sidebar-tabName">` + 4337 name + 4338 `</span>` + 4339 ping + 4340 `</a></li>` 4341 ); 4342} 4343function tabProcess(arrayItems) { 4344 var iFrameList = ""; 4345 var internalList = ""; 4346 var defaultTabId = null; 4347 if ( 4348 Array.isArray(arrayItems["data"]["tabs"]) && 4349 arrayItems["data"]["tabs"].length > 0 4350 ) { 4351 $.each(arrayItems["data"]["tabs"], function (i, v) { 4352 if (v.enabled === 1 && v.access_url) { 4353 tabInformation[v.id] = { 4354 id: v.id, 4355 name: cleanClass(v.name), 4356 active: false, 4357 loaded: false, 4358 increments: 0, 4359 tabInfo: v, 4360 }; 4361 switch (v.timeout) { 4362 case 1: 4363 case "1": 4364 tabActionsList["close"].push({ 4365 id: v.id, 4366 tab: cleanClass(v.name), 4367 action_ms: v.timeout_ms, 4368 }); 4369 break; 4370 case 2: 4371 case "2": 4372 tabActionsList["refresh"].push({ 4373 id: v.id, 4374 tab: cleanClass(v.name), 4375 action_ms: v.timeout_ms, 4376 }); 4377 break; 4378 default: 4379 //nada 4380 } 4381 if (v.default === 1) { 4382 defaultTabId = v.id; 4383 } 4384 var menuList = buildMenuList(v.id); 4385 if (v.category_id === 0) { 4386 if (activeInfo.settings.misc.unsortedTabs === "top") { 4387 $(menuList).prependTo($("#side-menu")); 4388 } else if (activeInfo.settings.misc.unsortedTabs === "bottom") { 4389 $(menuList).appendTo($("#side-menu")); 4390 } 4391 } else { 4392 if (activeInfo.settings.misc.unsortedTabs === "top") { 4393 $(menuList).prependTo($(".category-" + v.category_id)); 4394 } else if (activeInfo.settings.misc.unsortedTabs === "bottom") { 4395 $(menuList).appendTo($(".category-" + v.category_id)); 4396 } 4397 } 4398 switch (v.type) { 4399 case 0: 4400 case "0": 4401 case "internal": 4402 internalList = buildInternalContainer(v.id); 4403 $(internalList).appendTo($(".internal-listing")); 4404 internalList = buildInternalContainer(v.id, true); 4405 $(internalList).appendTo($(".internal-listing-right")); 4406 if (v.preload) { 4407 var newTab = $("#internal-" + v.id); 4408 organizrConsole( 4409 "Tab Function", 4410 "Preloading new tab for: " + cleanClass(v.name) 4411 ); 4412 $("#menu-" + v.id + " a") 4413 .children() 4414 .addClass("tabLoaded"); 4415 newTab.addClass("loaded"); 4416 loadInternal(v.id); 4417 } 4418 break; 4419 case 1: 4420 case "1": 4421 case "iframe": 4422 iFrameList = buildFrameContainer(v.id); 4423 $(iFrameList).appendTo($(".iFrame-listing")); 4424 iFrameList = buildFrameContainer(v.id, true); 4425 $(iFrameList).appendTo($(".iFrame-listing-right")); 4426 if (v.preload) { 4427 var newTab = $("#container-" + v.id); 4428 organizrConsole( 4429 "Tab Function", 4430 "Preloading new tab for: " + cleanClass(v.name) 4431 ); 4432 $("#menu-" + v.id + " a") 4433 .children() 4434 .addClass("tabLoaded"); 4435 newTab.addClass("loaded"); 4436 $(buildFrame(v.id)).appendTo(newTab); 4437 } 4438 break; 4439 case 2: 4440 case 3: 4441 case "2": 4442 case "3": 4443 case "_blank": 4444 case "popout": 4445 break; 4446 default: 4447 organizrConsole("Tab Function", "Action not set", "error"); 4448 } 4449 } 4450 }); 4451 $("#side-menu").metisMenu({ 4452 toggle: activeInfo.settings.misc.autoCollapseCategories, 4453 }); 4454 getDefault(defaultTabId); 4455 } else { 4456 noTabs(arrayItems); 4457 } 4458 $(menuExtras(arrayItems.data.user.loggedin)).appendTo($("#side-menu")); 4459} 4460function buildLogin() { 4461 swapDisplay("login"); 4462 closeSideMenu(); 4463 removeMenuActive(); 4464 $("#menu-login a").addClass("active"); 4465 organizrAPI2("GET", "api/v2/page/login") 4466 .success(function (data) {
4467 try { 4468 var response = data.response; 4469 organizrConsole("Organizr Function", "Opening Login Page"); 4470 $(".login-area").html(response.data); 4471 setHash("OrganizrLogin"); 4472 } catch (e) { 4473 organizrCatchError(e, data); 4474 } 4475 }) 4476 .fail(function (xhr) { 4477 OrganizrApiError(xhr, "Login Error"); 4478 }); 4479 $("#preloader").fadeOut(); 4480} 4481function buildLockscreen() { 4482 $("#preloader").fadeIn(); 4483 closeSideMenu(); 4484 organizrAPI2("GET", "api/v2/page/lockscreen") 4485 .success(function (data) { 4486 try { 4487 var response = data.response; 4488 organizrConsole("Organizr Function", "Adding Lockscreen"); 4489 $(response.data).appendTo($("body")); 4490 } catch (e) { 4491 organizrCatchError(e, data); 4492 } 4493 }) 4494 .fail(function (xhr) { 4495 OrganizrApiError(xhr); 4496 }); 4497 $("#preloader").fadeOut(); 4498} 4499function buildSplashScreenItem(arrayItems) { 4500 var splashList = ""; 4501 if ( 4502 Array.isArray(arrayItems["data"]["tabs"]) && 4503 arrayItems["data"]["tabs"].length > 0 4504 ) { 4505 arrayItems["data"]["tabs"].sort( 4506 (a, b) => parseFloat(a.order) - parseFloat(b.order) 4507 ); 4508 $.each(arrayItems["data"]["tabs"], function (i, v) { 4509 if (v.enabled === 1 && v.splash === 1 && v.access_url) { 4510 var image = iconPrefixSplash(v.image); 4511 if (image.indexOf(".") !== -1) { 4512 var dataSrc = 'data-src="' + iconPrefixSplash(v.image) + '"'; 4513 var nonImage = ""; 4514 } else { 4515 var dataSrc = ""; 4516 var nonImage = 4517 '<span class="text-uppercase badge bg-org splash-badge">' + 4518 image + 4519 "</span>"; 4520 } 4521 splashList += ` 4522 <div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 col-xl-2 mouse hvr-grow m-b-20" id="menu-${cleanClass( 4523 v.name 4524 )}" type="${v.type}" data-url="${ 4525 v.access_url 4526 }" onclick="tabActions(event,'${v.id}');"> 4527 <div class="homepage-drag fc-event bg-org lazyload" ${dataSrc}> 4528 ${nonImage} 4529 <span class="homepage-text"> ${v.name}</span> 4530 </div> 4531 </div> 4532 `; 4533 } 4534 }); 4535 } 4536 return splashList !== "" ? splashList : false; 4537} 4538function buildSplashScreen(json) { 4539 let hiddenSplash = directToHash ? "hidden" : "in"; 4540 var items = buildSplashScreenItem(json); 4541 var menu = 4542 '<li ><a href="javascript:void(0)" onclick="$(\'.splash-screen\').removeClass(\'hidden\').addClass(\'in\')"><i class="ti-layout-grid2 fa-fw"></i> <span lang="en">Splash Page</span></a></li>'; 4543 if (items) { 4544 closeSideMenu(); 4545 organizrConsole("Organizr Function", "Adding Splash Screen"); 4546 var splash = 4547 ` 4548 <section id="splashScreen" class="lock-screen splash-screen default-scroller fade ${hiddenSplash}"> 4549 <div class="row p-20 flexbox">` + 4550 items + 4551 `</div> 4552 <div class="row p-20 p-t-0 flexbox"> 4553 <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mouse hvr-wobble-bottom bottom-close-splash" onclick="$('.splash-screen').addClass('hidden').removeClass('in')"> 4554 <div class="homepage-drag fc-event bg-danger lazyload" data-src=""> 4555 <span class="homepage-text"> Close Splash</span> 4556 </div> 4557 </div> 4558 </div> 4559 </section> 4560 `; 4561 $(splash).appendTo($("body")); 4562 $(".append-menu").after(menu); 4563 } 4564} 4565function buildUserGroupSelect(array, userID, groupID) { 4566 var groupSelect = ""; 4567 var selected = ""; 4568 var disabled = ""; 4569 if (groupID == 0 && userID == 1) { 4570 disabled = "disabled"; 4571 } 4572 $.each(array, function (i, v) { 4573 selected = ""; 4574 if (v.group_id == groupID) { 4575 selected = "selected"; 4576 } 4577 var selectDisable = v.group_id == 0 || v.group_id == 999 ? "disabled" : ""; 4578 groupSelect += 4579 "<option " + 4580 selected + 4581 " " + 4582 selectDisable + 4583 ' value="' + 4584 v.group_id + 4585 '">' + 4586 v.group + 4587 "</option>"; 4588 }); 4589 return ( 4590 '<td><select name="userGroupSelect" class="form-control userGroupSelect" ' + 4591 disabled + 4592 ">" + 4593 groupSelect + 4594 "</select></td>" 4595 ); 4596} 4597function buildTabGroupSelect(array, tabID, groupID, type) { 4598 var groupSelect = ""; 4599 var selected = ""; 4600 let name = type == "tabGroupSelectMax" ? "group_id_max" : "group_id"; 4601 $.each(array, function (i, v) { 4602 selected = ""; 4603 if (v.group_id == groupID) { 4604 selected = "selected"; 4605 } 4606 groupSelect += 4607 "<option " + 4608 selected + 4609 ' value="' + 4610 v.group_id + 4611 '">' + 4612 v.group + 4613 "</option>"; 4614 }); 4615 return ( 4616 '<td><select name="tab[' + 4617 tabID + 4618 "]." + 4619 name + 4620 '" class="form-control ' + 4621 type + 4622 '">' + 4623 groupSelect + 4624 "</select></td>" 4625 ); 4626} 4627function buildTabTypeSelect(tabID, typeID, disabled) { 4628 var array = [ 4629 { 4630 type_id: 0, 4631 type: "Organizr", 4632 }, 4633 { 4634 type_id: 1, 4635 type: "iFrame", 4636 }, 4637 { 4638 type_id: 2, 4639 type: "New Window", 4640 }, 4641 ]; 4642 var typeSelect = ""; 4643 var selected = ""; 4644 disabled = disabled == "disabled" && typeID !== 0 ? null : disabled; 4645 $.each(array, function (i, v) { 4646 selected = ""; 4647 if (v.type_id == typeID) { 4648 selected = "selected"; 4649 } 4650 var disabledAttr = 4651 disabled === "disabled" && v.type !== "Internal" ? "disabled" : ""; 4652 typeSelect += 4653 "<option " + 4654 selected + 4655 ' value="' + 4656 v.type_id + 4657 '" ' + 4658 disabledAttr + 4659 ">" + 4660 v.type + 4661 "</option>"; 4662 }); 4663 return ( 4664 '<td><select name="tab[' + 4665 tabID + 4666 '].type" class="form-control tabTypeSelect">' + 4667 typeSelect + 4668 "</select></td>" 4669 ); 4670} 4671function buildTabCategorySelect(array, tabID, categoryID) { 4672 var categorySelect = ""; 4673 var selected = ""; 4674 $.each(array, function (i, v) { 4675 selected = ""; 4676 if (v.category_id == categoryID) { 4677 selected = "selected"; 4678 } 4679 categorySelect += 4680 "<option " + 4681 selected + 4682 ' value="' + 4683 v.category_id + 4684 '">' + 4685 v.category + 4686 "</option>"; 4687 }); 4688 return ( 4689 '<td><select name="tab[' + 4690 tabID + 4691 '].category_id" class="form-control tabCategorySelect">' + 4692 categorySelect + 4693 "</select></td>" 4694 ); 4695} 4696function buildUserManagementItem(array) { 4697 var userList = ""; 4698 $.each(array.users, function (i, v) { 4699 var disabledDelete = 4700 v.group_id == 999 || v.group_id == 0 ? "disabled" : "deleteUser"; 4701 userList += 4702 ` 4703 <tr class="userManagement" data-id="` + 4704 v.id + 4705 `" data-username="` + 4706 v.username + 4707 `" data-group="` + 4708 v.group + 4709 `" data-email="` + 4710 v.email + 4711 `"> 4712 <td class="text-center el-element-overlay"> 4713 <div class="el-card-item p-0"> 4714 <div class="el-card-avatar el-overlay-1 m-0"> 4715 <img alt="user-img" class="img-circle" src="` + 4716 v.image + 4717 `" width="45"> 4718 <div class="el-overlay"> 4719 <ul class="el-info"> 4720 ` + 4721 v.id + 4722 ` 4723 </ul> 4724 </div> 4725 </div>
4726 </div> 4727 </td> 4728 <td>` + 4729 v.username + 4730 ` 4731 <br/><span class="text-muted">` + 4732 v.email + 4733 `</span></td> 4734 <td>` + 4735 moment(v.register_date).format("ll") + 4736 ` 4737 <br/><span class="text-muted">` + 4738 moment(v.register_date).format("LT") + 4739 `</span></td> 4740 ` + 4741 buildUserGroupSelect(array.groups, v.id, v.group_id) + 4742 ` 4743 <td><button type="button" class="btn btn-info btn-outline btn-circle btn-lg m-r-5 editUserButton popup-with-form" href="#edit-user-form" data-effect="mfp-3d-unfold"><i class="ti-pencil-alt"></i></button></td> 4744 <td><button type="button" class="btn btn-info btn-outline btn-circle btn-lg m-r-20 emailUser"><i class="ti-email"></i></button></td> 4745 <td><button type="button" class="btn btn-danger btn-outline btn-circle btn-lg m-r-5 ` + 4746 disabledDelete + 4747 `"><i class="ti-trash"></i></button></td> 4748 </tr> 4749 `; 4750 }); 4751 return userList; 4752} 4753function buildGroupManagementItem(array) { 4754 var userList = ""; 4755 $.each(array.groups, function (i, v) { 4756 var userCount = array.users.reduce(function (n, group) { 4757 return n + (group.group_id == v.group_id); 4758 }, 0); 4759 var disabledDefault = 4760 v.group_id == 0 || v.group_id == 999 ? "disabled" : ""; 4761 var disabledDelete = 4762 userCount > 0 || v.default == 1 || v.group_id == 999 || v.group_id <= 1 4763 ? "disabled" 4764 : ""; 4765 var defaultIcon = 4766 v.default == 1 ? "icon-user-following" : "icon-user-follow"; 4767 var defaultColor = v.default == 1 ? "btn-info disabled" : "btn-warning"; 4768 userList += 4769 ` 4770 <tr class="userManagement" data-id="` + 4771 v.id + 4772 `" data-group-id="` + 4773 v.group_id + 4774 `" data-group="` + 4775 v.group + 4776 `" data-default="` + 4777 tof(v.default) + 4778 `" data-image="` + 4779 v.image + 4780 `" data-user-count="` + 4781 userCount + 4782 `"> 4783 <td class="text-center el-element-overlay"> 4784 <div class="el-card-item p-0"> 4785 <div class="el-card-avatar el-overlay-1 m-0"> 4786 <div class="tabEditorIcon">` + 4787 iconPrefix(v.image) + 4788 `</div> 4789 <div class="el-overlay"> 4790 <ul class="el-info"> 4791 ` + 4792 v.group_id + 4793 ` 4794 </ul> 4795 </div> 4796 </div> 4797 </div> 4798 </td> 4799 <td>` + 4800 v.group + 4801 `</td> 4802 <td>` + 4803 userCount + 4804 `</td> 4805 <td><button type="button" class="btn ` + 4806 defaultColor + 4807 ` btn-outline btn-circle btn-lg m-r-5 changeDefaultGroup" ` + 4808 disabledDefault + 4809 `><i class="` + 4810 defaultIcon + 4811 `"></i></button></td> 4812 <td><button type="button" class="btn btn-info btn-outline btn-circle btn-lg m-r-5 editGroupButton popup-with-form" href="#edit-group-form" data-effect="mfp-3d-unfold"><i class="ti-pencil-alt"></i></button></td> 4813 <td><button type="button" class="btn btn-danger btn-outline btn-circle btn-lg m-r-5 deleteUserGroup" ` + 4814 disabledDelete + 4815 `><i class="ti-trash"></i></button></td> 4816 </tr> 4817 `; 4818 }); 4819 return userList; 4820} 4821function buildCategoryEditorItem(array) { 4822 var categoryList = ""; 4823 $.each(array.categories, function (i, v) { 4824 var tabCount = array.tabs.reduce(function (n, category) { 4825 return n + (category.category_id == v.category_id); 4826 }, 0); 4827 var disabledDefault = v.default == 1 ? "disabled" : ""; 4828 var disabledDelete = 4829 tabCount > 0 || v.default == 1 || v.category_id == 0 ? "disabled" : ""; 4830 var defaultIcon = 4831 v.default == 1 ? "icon-user-following" : "icon-user-follow"; 4832 var defaultColor = v.default == 1 ? "btn-info disabled" : "btn-warning"; 4833 categoryList += 4834 ` 4835 <tr class="categoryEditor" data-id="` + 4836 v.id + 4837 `" data-order="` + 4838 v.order + 4839 `" data-category-id="` + 4840 v.category_id + 4841 `" data-name="` + 4842 v.category + 4843 `" data-default="` + 4844 tof(v.default) + 4845 `" data-image="` + 4846 v.image + 4847 `" data-tab-count="` + 4848 tabCount + 4849 `"> 4850 <input type="hidden" class="form-control order" name="category[` + 4851 v.id + 4852 `].order" value="` + 4853 v.order + 4854 `"> 4855 <input type="hidden" class="form-control" name="category[` + 4856 v.id + 4857 `].originalOrder" value="` + 4858 v.order + 4859 `"> 4860 <input type="hidden" class="form-control" name="category[` + 4861 v.id + 4862 `].name" value="` + 4863 v.category + 4864 `"> 4865 <input type="hidden" class="form-control" name="category[` + 4866 v.id + 4867 `].id" value="` + 4868 v.id + 4869 `"> 4870 <td class="text-center el-element-overlay"> 4871 <div class="el-card-item p-0"> 4872 <div class="el-card-avatar el-overlay-1 m-0"> 4873 <div class="tabEditorIcon">` + 4874 iconPrefix(v.image) + 4875 `</div> 4876 <div class="el-overlay bg-org"> 4877 <ul class="el-info"> 4878 <i class="fa fa-bars"></i> 4879 </ul> 4880 </div> 4881 </div>
4882 </div> 4883 </td> 4884 <td>` + 4885 v.category + 4886 `</td> 4887 <td style="text-align:center">` + 4888 tabCount + 4889 `</td> 4890 <td style="text-align:center"><button type="button" class="btn ` + 4891 defaultColor + 4892 ` btn-outline btn-circle btn-lg m-r-5 changeDefaultCategory" ` + 4893 disabledDefault + 4894 `><i class="` + 4895 defaultIcon + 4896 `"></i></button></td> 4897 <td style="text-align:center"><button type="button" class="btn btn-info btn-outline btn-circle btn-lg m-r-5 editCategoryButton popup-with-form" href="#edit-category-form" data-effect="mfp-3d-unfold"><i class="ti-pencil-alt"></i></button></td> 4898 <td style="text-align:center"><button type="button" class="btn btn-danger btn-outline btn-circle btn-lg m-r-5 deleteCategory" ` + 4899 disabledDelete + 4900 `><i class="ti-trash"></i></button></td> 4901 </tr> 4902 `; 4903 }); 4904 return categoryList; 4905} 4906function buildTabEditorItem(array) { 4907 var tabList = ""; 4908 $.each(array.tabs, function (i, v) { 4909 let deleteDisabled = "deleteTab"; 4910 let buttonDisabled = ""; 4911 let typeDisabled = ""; 4912 if (v.url !== null) { 4913 deleteDisabled = 4914 v.url.indexOf("/page/settings") > 0 ? "disabled" : "deleteTab"; 4915 buttonDisabled = v.url.indexOf("/page/settings") > 0 ? "disabled" : ""; 4916 typeDisabled = v.url.indexOf("/v2/page/") > 0 ? "disabled" : ""; 4917 } 4918 tabList += 4919 ` 4920 <tr class="tabEditor" data-order="` + 4921 v.order + 4922 `" data-original-order="` + 4923 v.order + 4924 `" data-id="` + 4925 v.id + 4926 `" data-group-id="` + 4927 v.group_id + 4928 `" data-category-id="` + 4929 v.category_id + 4930 `" data-name="` + 4931 v.name + 4932 `" data-url="` + 4933 v.url + 4934 `" data-local-url="` + 4935 v.url_local + 4936 `" data-ping-url="` + 4937 v.ping_url + 4938 `" data-image="` + 4939 v.image + 4940 `" data-tab-action-type="` + 4941 v.timeout + 4942 `" data-tab-action-time="` + 4943 v.timeout_ms + 4944 `"> 4945 <input type="hidden" class="form-control" name="tab[` + 4946 v.id + 4947 `].id" value="` + 4948 v.id + 4949 `"> 4950 <input type="hidden" class="form-control order" name="tab[` + 4951 v.id + 4952 `].order" value="` + 4953 v.order + 4954 `"> 4955 <input type="hidden" class="form-control" name="tab[` + 4956 v.id + 4957 `].originalOrder" value="` + 4958 v.order + 4959 `"> 4960 <td class="mouse-grab sort-tabs-handle"> 4961 <i class="icon-options-vertical m-r-5"></i> 4962 <!-- May use later on 4963 <div class="btn-group dropside visible-xs"> 4964 <button aria-expanded="false" data-toggle="dropdown" class="btn btn-default btn-outline dropdown-toggle waves-effect waves-light" type="button"> <i class="icon-options-vertical m-r-5"></i> <span class="caret"></span></button> 4965 <ul role="menu" class="dropdown-menu"> 4966 <li><a href="#"><i class="fa fa-angle-double-up"></i></a></li> 4967 <li><a href="#"><i class="fa fa-angle-up"></i></a></li> 4968 <li><a href="#"><i class="fa fa-angle-double-down"></i></a></li> 4969 <li><a href="#"><i class="fa fa-angle-down"></i></a></li> 4970 </ul> 4971 </div> 4972 --> 4973 </td> 4974 <td style="text-align:center" class="text-center el-element-overlay"> 4975 <div class="el-card-item p-0"> 4976 <div class="el-card-avatar el-overlay-1 m-0 tooltip-info" data-toggle="tooltip" data-placement="top" title="" data-original-title="${v.id}"> 4977 <div class="tabEditorIcon">` + 4978 iconPrefix(v.image) + 4979 `</div> 4980 </div> 4981 </div> 4982 </td> 4983 <td><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 4984 v.url + 4985 `">` + 4986 v.name + 4987 `</span><span id="checkTabHomepageItem-` + 4988 v.id + 4989 `" data-url="` + 4990 v.url + 4991 `" data-url-local="` + 4992 v.url_local + 4993 `" data-name="` + 4994 v.name + 4995 `" class="checkTabHomepageItem mouse label label-rouded label-inverse pull-right"></span></td> 4996 ` + 4997 buildTabCategorySelect(array.categories, v.id, v.category_id) + 4998 ` 4999 ` + 5000 buildTabGroupSelect(array.groups, v.id, v.group_id, "tabGroupSelectMin") + 5001 ` 5002 ` + 5003 buildTabGroupSelect( 5004 array.groups, 5005 v.id, 5006 v.group_id_max, 5007 "tabGroupSelectMax" 5008 ) + 5009 ` 5010 ` + 5011 buildTabTypeSelect(v.id, v.type, typeDisabled) + 5012 ` 5013 <td style="text-align:center"><div class="radio radio-purple"><input onclick="radioLoop(this);" type="radio" class="defaultSwitch" id="tab[` + 5014 v.id + 5015 `].default" name="tab[` + 5016 v.id + 5017 `].default" value="true" ` + 5018 tof(v.default, "c") + 5019 `><label for="tab[` + 5020 v.id + 5021 `].default"></label></div></td> 5022 5023 <td style="text-align:center"><input ` + 5024 buttonDisabled + 5025 ` type="checkbox" class="js-switch enabledSwitch ` + 5026 buttonDisabled + 5027 `" data-size="small" data-color="#99d683" data-secondary-color="#f96262" name="tab[` + 5028 v.id + 5029 `].enabled" value="true" ` + 5030 tof(v.enabled, "c") + 5031 `/><input type="hidden" class="form-control" name="tab[` + 5032 v.id + 5033 `].enabled" value="false"></td> 5034 <td style="text-align:center"><input type="checkbox" class="js-switch splashSwitch" data-size="small" data-color="#99d683" data-secondary-color="#f96262" name="tab[` + 5035 v.id + 5036 `].splash" value="true" ` + 5037 tof(v.splash, "c") + 5038 `/><input type="hidden" class="form-control" name="tab[` + 5039 v.id + 5040 `].splash" value="false"></td> 5041 <td style="text-align:center"><input type="checkbox" class="js-switch pingSwitch" data-size="small" data-color="#99d683" data-secondary-color="#f96262" name="tab[` + 5042 v.id + 5043 `].ping" value="true" ` + 5044 tof(v.ping, "c") + 5045 `/><input type="hidden" class="form-control" name="tab[` + 5046 v.id + 5047 `].ping" value="false"></td> 5048 <td style="text-align:center"><input type="checkbox" class="js-switch preloadSwitch" data-size="small" data-color="#99d683" data-secondary-color="#f96262" name="tab[` + 5049 v.id + 5050 `].preload" value="true" ` + 5051 tof(v.preload, "c") + 5052 `/><input type="hidden" class="form-control" name="tab[` + 5053 v.id + 5054 `].preload" value="false"></td> 5055 <td style="text-align:center"><input type="checkbox" class="js-switch addToAdminSwitch" data-size="small" data-color="#99d683" data-secondary-color="#f96262" name="tab[` + 5056 v.id + 5057 `].add_to_admin" value="true" ` + 5058 tof(v.add_to_admin, "c") + 5059 `/><input type="hidden" class="form-control" name="tab[` + 5060 v.id + 5061 `].add_to_admin" value="false"></td> 5062 <td style="text-align:center"><button type="button" class="btn btn-info btn-outline btn-circle btn-lg m-r-5 editTabButton popup-with-form" onclick="editTabForm('` + 5063 v.id + 5064 `')" href="#edit-tab-form" data-effect="mfp-3d-unfold"><i class="ti-pencil-alt"></i></button></td> 5065 <td style="text-align:center"><button type="button" class="btn btn-danger btn-outline btn-circle btn-lg m-r-5 ` + 5066 deleteDisabled + 5067 `"><i class="ti-trash"></i></button></td> 5068 </tr> 5069 `; 5070 }); 5071 return tabList; 5072} 5073function editTabForm(id) { 5074 organizrAPI2("GET", "api/v2/tabs/" + id, true) 5075 .success(function (data) {
5076 try { 5077 let response = data.response; 5078 $(".tabIconImageList").val(null).trigger("change"); 5079 $(".tabIconIconList").val(null).trigger("change"); 5080 $("#edit-tab-form [name=name]").val(response.data.name); 5081 $("#originalTabName").html(response.data.name); 5082 $("#edit-tab-form [name=url]").val(response.data.url); 5083 $("#edit-tab-form [name=url_local]").val(response.data.url_local); 5084 $("#edit-tab-form [name=ping_url]").val(response.data.ping_url); 5085 $("#edit-tab-form [name=image]").val(response.data.image); 5086 $("#edit-tab-form [name=id]").val(response.data.id); 5087 $("#edit-tab-form [name=timeout_ms]").val( 5088 convertMsToMinutes(response.data.timeout_ms) 5089 ); 5090 $("#edit-tab-form [name=timeout]").val(response.data.timeout); 5091 if (response.data.url.indexOf("/?v") > 0) { 5092 $("#edit-tab-form [name=url]").prop("disabled", "true"); 5093 } else { 5094 $("#edit-tab-form [name=url]").prop("disabled", null); 5095 } 5096 } catch (e) { 5097 organizrCatchError(e, data); 5098 } 5099 }) 5100 .fail(function (xhr) { 5101 OrganizrApiError(xhr, "Tab Error"); 5102 }); 5103} 5104function getSubmitSettingsFormValueSingle(form, index, value) { 5105 var values = {}; 5106 if (value !== "#987654" && index.includes("disable-pwd-mgr") == false) { 5107 var input = $("#" + form + " [name='" + index + "']"); 5108 var dataType = input.attr("data-type"); 5109 switch (dataType) { 5110 case "switch": 5111 case "checkbox": 5112 var value = input.prop("checked") ? true : false; 5113 break; 5114 case "select2": 5115 var value = input.val() !== null ? input.val().toString() : ""; 5116 break; 5117 default: 5118 var value = input.val(); 5119 } 5120 values = { name: index, value: value, type: dataType }; 5121 return values; 5122 } 5123 return false; 5124} 5125function getSubmitSettingsFormValueObject(form, index, value) { 5126 var values = []; 5127 $.each(value, function (i, v) { 5128 var objectList = []; 5129 var object = []; 5130 $.each(v, function (key, val) { 5131 if (val !== "#987654" && key.includes("disable-pwd-mgr") == false) { 5132 var input = $( 5133 "#" + form + " [name='" + index + "[" + i + "]." + key + "']" 5134 ); 5135 var dataType = input.attr("data-type"); 5136 var dataLabel = input.attr("data-label"); 5137 switch (dataType) { 5138 case "switch": 5139 case "checkbox": 5140 var value = input.prop("checked") ? true : false; 5141 break; 5142 case "select2": 5143 var value = input.val() !== null ? input.val().toString() : ""; 5144 break; 5145 default: 5146 var value = input.val(); 5147 } 5148 var newKey = index + "[" + i + "]." + key; 5149 object.push({ 5150 type: dataType, 5151 name: newKey, 5152 label: dataLabel, 5153 value: value, 5154 }); 5155 } 5156 }); 5157 values.push(object); 5158 }); 5159 values = { name: index, value: values, type: "array" }; 5160 return values; 5161} 5162function submitSettingsForm(form, homepageItem = false) { 5163 var list = $("#" + form).serializeToJSON(); 5164 var size = 0; 5165 var submit = {}; 5166 $.each(list, function (i, v) { 5167 var values = false; 5168 5169 if (Object.prototype.toString.call(v) === "[object Object]") { 5170 values = getSubmitSettingsFormValueObject(form, i, v); 5171 } else { 5172 values = getSubmitSettingsFormValueSingle(form, i, v); 5173 } 5174 size++; 5175 if (values) { 5176 submit[i] = values.value; 5177 } 5178 }); 5179 var callbacks = $.Callbacks(); 5180 // Custom Callbacks 5181 switch (form) { 5182 case "customize-appearance-form": 5183 break; 5184 default: 5185 } 5186 if (size > 0) { 5187 organizrAPI2("PUT", "api/v2/config", submit, true) 5188 .success(function (data) { 5189 try { 5190 var response = data.response; 5191 } catch (e) { 5192 organizrCatchError(e, data); 5193 } 5194 if (callbacks) { 5195 callbacks.fire(); 5196 } 5197 if (homepageItem && !activeInfo.settings.misc.disableHomepageModals) { 5198 let html = ` 5199 <div class="panel panel-default"> 5200 <div class="panel-heading">${response.message}</div> 5201 <div class="panel-wrapper collapse in"> 5202 <div class="panel-body"> 5203 <div class="overlay-box"> 5204 <div class="user-content"> 5205 <h4 lang="en">Close Homepage Settings?</h4> 5206 <div class="button-box"> 5207 <button class="btn btn-info waves-effect waves-light" type="button" onclick="swal.close();Custombox.modal.close()"><span class="btn-label"><i class="ti-check"></i></span>Yes</button> 5208 <button class="btn btn-danger waves-effect waves-light" type="button" onclick="swal.close()"><span class="btn-label"><i class="ti-close"></i></span>No</button> 5209 </div> 5210 <p class="close-homepage-timer">Auto Closing in 5 seconds...</p> 5211 </div> 5212 </div> 5213 </div> 5214 </div> 5215 </div> 5216 `; 5217 swal({ 5218 content: createElementFromHTML(html),
5219 buttons: false, 5220 className: "bg-org", 5221 timer: 5000, 5222 }); 5223 textTimer( 5224 5, 5225 ".close-homepage-timer", 5226 "Seconds remaining: ", 5227 "Closing..." 5228 ); 5229 } else { 5230 message( 5231 "Updated Items", 5232 response.message, 5233 activeInfo.settings.notifications.position, 5234 "#FFF", 5235 "success", 5236 "5000" 5237 ); 5238 } 5239 }) 5240 .fail(function (xhr) { 5241 OrganizrApiError(xhr, "Update Error"); 5242 }); 5243 $("#" + form + " :input").each(function () { 5244 var input = $(this); 5245 input 5246 .closest(".form-group") 5247 .removeClass("has-success") 5248 .removeClass("has-error"); 5249 }); 5250 $("#" + form + "-save").addClass("hidden"); 5251 } else { 5252 $("#" + form + " :input").each(function () { 5253 var input = $(this); 5254 input 5255 .closest(".form-group") 5256 .removeClass("has-success") 5257 .addClass("has-error"); 5258 }); 5259 } 5260} 5261function textTimer(seconds, el, preText, postText) { 5262 var seconds_left = seconds; 5263 var interval = setInterval(function () { 5264 $(el).html(preText + " " + --seconds_left); 5265 if (seconds_left <= 0) { 5266 $(el).html(postText); 5267 clearInterval(interval); 5268 } 5269 }, 1000); 5270} 5271function submitHomepageOrder() { 5272 var list = $("#homepage-values").serializeToJSON(); 5273 var size = 0; 5274 var submit = {}; 5275 $.each(list, function (i, v) { 5276 if (v !== "") { 5277 size++; 5278 submit[i] = v; 5279 } 5280 }); 5281 var callbacks = $.Callbacks(); 5282 if (size > 0) { 5283 organizrAPI2("PUT", "api/v2/config", submit, true) 5284 .success(function (data) { 5285 try { 5286 var response = data.response; 5287 $("#submitHomepageOrder-save").addClass("hidden"); 5288 } catch (e) { 5289 organizrCatchError(e, data); 5290 } 5291 message( 5292 "Updated Homepage Order", 5293 response.message, 5294 activeInfo.settings.notifications.position, 5295 "#FFF", 5296 "success", 5297 "5000" 5298 ); 5299 if (callbacks) { 5300 callbacks.fire(); 5301 } 5302 }) 5303 .fail(function (xhr) { 5304 OrganizrApiError(xhr, "Update Error"); 5305 }); 5306 } else { 5307 console.log("add error"); 5308 } 5309} 5310function submitTabOrder(newTabs) { 5311 var data = []; 5312 var process = false; 5313 $.each(newTabs.tab, function (i, v) { 5314 if (v.originalOrder == v.order) { 5315 delete newTabs.tab[i]; 5316 } else { 5317 let temp = { 5318 order: v.order, 5319 id: v.id, 5320 }; 5321 data.push(temp); 5322 process = true; 5323 } 5324 }); 5325 if (!process) { 5326 message( 5327 "Tab Order Warning", 5328 "Order was not changed - Submission not needed", 5329 activeInfo.settings.notifications.position, 5330 "#FFF", 5331 "warning", 5332 "5000" 5333 ); 5334 $(".saveTabOrderButton").addClass("hidden"); 5335 return false; 5336 } 5337 var callbacks = $.Callbacks(); 5338 callbacks.add(buildTabEditor); 5339 organizrAPI2("PUT", "api/v2/tabs", data, true) 5340 .success(function (data) { 5341 try { 5342 var response = data.response; 5343 } catch (e) { 5344 organizrCatchError(e, data); 5345 } 5346 message( 5347 "Tab Order Updated", 5348 response.message, 5349 activeInfo.settings.notifications.position, 5350 "#FFF", 5351 "success", 5352 "5000" 5353 ); 5354 if (callbacks) { 5355 callbacks.fire(); 5356 } 5357 $(".saveTabOrderButton").addClass("hidden"); 5358 }) 5359 .fail(function (xhr) { 5360 OrganizrApiError(xhr, "Update Error"); 5361 }); 5362} 5363function submitCategoryOrder() { 5364 var data = []; 5365 var categories = $("#submit-categories-form").serializeToJSON(); 5366 var callbacks = $.Callbacks(); 5367 callbacks.add(buildCategoryEditor); 5368 $.each(categories.category, function (i, v) { 5369 if (v.originalOrder == v.order) { 5370 delete categories.category[i]; 5371 } else { 5372 let temp = { 5373 order: v.order, 5374 id: v.id, 5375 }; 5376 data.push(temp); 5377 } 5378 }); 5379 organizrAPI2("PUT", "api/v2/categories", data, true) 5380 .success(function (data) { 5381 try { 5382 var response = data.response; 5383 } catch (e) { 5384 organizrCatchError(e, data); 5385 } 5386 message( 5387 "Category Order Updated", 5388 response.message, 5389 activeInfo.settings.notifications.position, 5390 "#FFF", 5391 "success", 5392 "5000" 5393 ); 5394 if (callbacks) { 5395 callbacks.fire(); 5396 } 5397 $(".saveTabOrderButton").addClass("hidden"); 5398 }) 5399 .fail(function (xhr) { 5400 OrganizrApiError(xhr, "Update Error"); 5401 }); 5402} 5403function buildTR(array, type, badge) { 5404 var listing = ""; 5405 var arrayItems = array.split("|"); 5406 if (hasValue(arrayItems) === true) { 5407 $.each(arrayItems, function (i, v) { 5408 listing += 5409 ` 5410 <tr> 5411 <td width="70"><span class="label label-` + 5412 badge + 5413 `"><span lang="en">` + 5414 type + 5415 `</span></span></td> 5416 <td class="text-capitalize">` + 5417 updateIssueLink(v) + 5418 `</td> 5419 </tr> 5420 `; 5421 }); 5422 return listing; 5423 } 5424 return " "; 5425} 5426function buildVersion(array) { 5427 var x = 0; 5428 var versions = 5429 '<div class="col-md-3 col-sm-4 col-xs-6 m-b-10 pull-right"><button onclick="manualUpdateCheck()" class="btn btn-sm btn-primary btn-rounded waves-effect waves-light pull-right row b-none buttonManualUpdateCheck" type="button"><span class="btn-label"><i class="fa fa-globe"></i></span><span lang="en">Check For Updates</span></button></div><div class="clearfix"></div>'; 5430 var listing = ""; 5431 var currentV = currentVersion; 5432 var installed = ""; 5433 var spanClass = ""; 5434 var button = ""; 5435 $.each(array, function (i, v) { 5436 listing += buildTR(v.new, "NEW", "info"); 5437 listing += buildTR(v.fixed, "FIXED", "success"); 5438 listing += buildTR(v.notes, "NOTE", "warning"); 5439 if (currentV === i) { 5440 button = 5441 '<button class="btn btn-sm btn-success btn-rounded waves-effect waves-light disabled pull-right row b-none" type="button"><span class="btn-label"><i class="fa fa-check"></i></span><span lang="en">Installed</span></button>'; 5442 } else if (x === 0) { 5443 button = 5444 '<button class="btn btn-sm btn-info btn-rounded waves-effect waves-light pull-right row b-none" type="button" onclick="updateNow();"><span class="btn-label"><i class="fa fa-download"></i></span><span lang="en">Install Update</span></button>'; 5445 } 5446 let tableClass = x == 0 ? "" : "hidden"; 5447 let divClassPadding = x == 0 ? "" : "p-b-0"; 5448 let divClassMargin = x == 0 ? "" : "m-b-0"; 5449 let toggleButtonText = x == 0 ? "Less" : "More"; 5450 let toggleButtonIcon = x == 0 ? "up" : "down";
5451 let divStatus = x == 0 ? "opened" : "closed"; 5452 versions += 5453 ` 5454 <div class="white-box bg-org ${divClassPadding} update-main-div-${x}" data-status="${divStatus}"> 5455 <div class="col-md-3 col-sm-4 col-xs-6 pull-right">` + 5456 button + 5457 `</div> 5458 <h3 class="box-title ${divClassMargin} update-box-title-${x}">` + 5459 i + 5460 `</h3> 5461 <div class="row sales-report"> 5462 <div class="col-md-12 col-sm-12 col-xs-12"> 5463 <div class="pull-left"> 5464 <span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 5465 moment(v.date).format("LL") + 5466 `">` + 5467 moment.utc(v.date, "YYYY-MM-DD hh:mm[Z]").local().fromNow() + 5468 `</span> 5469 <p class="text-info p-0">` + 5470 v.title + 5471 `</p> 5472 </div> 5473 <button class="btn btn-sm btn-primary btn-rounded waves-effect waves-light pull-right" onclick="toggleGithubVersion(${x})" type="button"><span class="btn-label"><i class="fa fa-long-arrow-${toggleButtonIcon} toggleButtonIcon-${x}"></i></span><span lang="en" class="toggleButton-${x}">${toggleButtonText}</span></button> 5474 </div> 5475 </div> 5476 <div class="table-responsive ${tableClass} update-table-${x}"> 5477 <table class="table inverse-bordered-table"> 5478 <tbody> 5479 ` + 5480 listing + 5481 ` 5482 </tbody> 5483 </table> 5484 </div> 5485 </div> 5486 `; 5487 listing = ""; 5488 button = ""; 5489 x++; 5490 }); 5491 return versions; 5492} 5493function toggleGithubVersion(id) { 5494 let status = $(".update-main-div-" + id).attr("data-status"); 5495 if (status == "opened") { 5496 $(".update-main-div-" + id).attr("data-status", "closed"); 5497 $(".update-main-div-" + id).addClass("p-b-0"); 5498 $(".update-box-title-" + id).addClass("m-b-0"); 5499 $(".update-table-" + id).addClass("hidden"); 5500 $(".toggleButton-" + id).text("More"); 5501 $(".toggleButtonIcon-" + id) 5502 .removeClass("fa-long-arrow-up") 5503 .addClass("fa-long-arrow-down"); 5504 } else { 5505 $(".update-main-div-" + id).attr("data-status", "opened"); 5506 $(".update-main-div-" + id).removeClass("p-b-0"); 5507 $(".update-box-title-" + id).removeClass("m-b-0"); 5508 $(".update-table-" + id).removeClass("hidden"); 5509 $(".toggleButton-" + id).text("Less"); 5510 $(".toggleButtonIcon-" + id) 5511 .addClass("fa-long-arrow-up") 5512 .removeClass("fa-long-arrow-down"); 5513 } 5514} 5515function manualUpdateCheck() { 5516 $(".buttonManualUpdateCheck").addClass("disabled"); 5517 $(".buttonManualUpdateCheck i") 5518 .removeClass("fa-globe") 5519 .addClass("fa-refresh fa-spin"); 5520 setTimeout(function () { 5521 updateCheck(); 5522 checkCommitLoad(); 5523 }, 1000); 5524 setTimeout(function () { 5525 $(".buttonManualUpdateCheck").removeClass("disabled"); 5526 $(".buttonManualUpdateCheck i") 5527 .removeClass("fa-refresh fa-spin fa-globe") 5528 .addClass("fa-check"); 5529 }, 1500); 5530 return true; 5531} 5532function updateCheck() { 5533 githubVersions() 5534 .success(function (data) { 5535 try { 5536 var response = JSON.parse(data); 5537 } catch (e) { 5538 organizrCatchError(e, data); 5539 } 5540 for (var a in reverseObject(response)) { 5541 var latest = a; 5542 break; 5543 } 5544 if (latest !== currentVersion) { 5545 organizrConsole( 5546 "Update Function", 5547 "Update to " + latest + " is available", 5548 "warning" 5549 ); 5550 if (activeInfo.settings.misc.docker === false) { 5551 let tabInfo = findTab("api/v2/page/settings", "access_url"); 5552 if (tabInfo) { 5553 messageSingle( 5554 window.lang.translate("Update Available"), 5555 latest + 5556 " " + 5557 window.lang.translate("is available, goto") + 5558 ' <a href="javascript:void(0)" onclick="tabActions(event,\'' + 5559 tabInfo.id + 5560 "');clickPath('update')\"><span lang=\"en\">Update Tab</span></a>", 5561 activeInfo.settings.notifications.position, 5562 "#FFF", 5563 "update", 5564 "60000" 5565 ); 5566 } 5567 } 5568 } else { 5569 organizrConsole( 5570 "Update Function", 5571 "Already running latest version: " + latest, 5572 "info" 5573 ); 5574 } 5575 $("#githubVersions").html(buildVersion(reverseObject(response))); 5576 }) 5577 .fail(function (xhr) { 5578 OrganizrApiError(xhr); 5579 }); 5580} 5581function ignoreNewsId(id) { 5582 organizrAPI2("POST", "api/v2/news/" + id, {}) 5583 .success(function (data) {
5584 try { 5585 let response = data.response; 5586 message( 5587 "News Item", 5588 "Item now ignored", 5589 activeInfo.settings.notifications.position, 5590 "#FFF", 5591 "success", 5592 "5000" 5593 ); 5594 $(".newsItem-" + id).remove(); 5595 $(".newsHeart-" + id).remove(); 5596 } catch (e) { 5597 organizrCatchError(e, data); 5598 } 5599 }) 5600 .fail(function (xhr) { 5601 OrganizrApiError(xhr, "News"); 5602 }); 5603} 5604function newsLoad() { 5605 newsJSON() 5606 .success(function (data) { 5607 try { 5608 var response = JSON.parse(data); 5609 var items = []; 5610 var limit = 5; 5611 var count = 0; 5612 organizrAPI2("get", "api/v2/news") 5613 .success(function (data) { 5614 try { 5615 let ignoredIds = data.response.data; 5616 ignoredIds = ignoredIds == null ? [] : ignoredIds; 5617 $.each(response, function (i, v) { 5618 count++; 5619 let ignore = ignoredIds.includes(v.id); 5620 let alertDefined = 5621 typeof v.important !== "undefined" && v.important !== false; 5622 let alert = 5623 alertDefined && ignore == false 5624 ? `<span class="animated loop-animation flash text-danger mouse newsItem-${v.id}" onclick="ignoreNewsId('${v.id}')"> <i class="ti-alert"></i> Important Message - Click me to Ignore</span>` 5625 : ""; 5626 let heartBeat = 5627 alertDefined && ignore == false 5628 ? `<div class="notify pull-left newsHeart-${v.id}"><span class="heartbit"></span><span class="point"></span></div>` 5629 : ""; 5630 let newBody = 5631 ` 5632 <h5 class="pull-left"><i class="ti-calendar"></i> ` + 5633 moment(v.date).format("LLL") + 5634 alert + 5635 `</h5> 5636 <h5 class="pull-right">` + 5637 v.author + 5638 `</h5> 5639 <div class="clearfix"></div> 5640 ` + 5641 (v.subTitle ? "<h5>" + v.subTitle + "</h5>" : "") + 5642 ` 5643 <p>` + 5644 v.body + 5645 `</p> 5646 `; 5647 if (count <= limit) { 5648 items[i] = { 5649 title: v.title + heartBeat, 5650 body: newBody, 5651 }; 5652 } 5653 }); 5654 var body = buildAccordion(items, true); 5655 $("#organizrNewsPanel").html(body); 5656 } catch (e) { 5657 organizrCatchError(e, data); 5658 } 5659 }) 5660 .fail(function (xhr) { 5661 OrganizrApiError(xhr, "News"); 5662 }); 5663 } catch (e) { 5664 organizrCatchError(e, data); 5665 } 5666 }) 5667 .fail(function (xhr) { 5668 OrganizrApiError(xhr); 5669 }); 5670} 5671function checkPluginUpdates() { 5672 if (!activeInfo.user.loggedin || activeInfo.user.groupID > 1) { 5673 return false; 5674 } 5675 organizrAPI2("get", "api/v2/plugins/marketplace") 5676 .success(function (data) { 5677 try { 5678 let update = false; 5679 let pluginsNeedingUpdate = []; 5680 let plugins = data.response.data; 5681 $.each(plugins, function (i, v) { 5682 if (v.needs_update) { 5683 update = true; 5684 pluginsNeedingUpdate.push(i); 5685 } 5686 }); 5687 if (update) { 5688 pluginsNeedingUpdate = "[" + pluginsNeedingUpdate.join(", ") + "]"; 5689 messageSingle( 5690 window.lang.translate("Update Available"), 5691 '<a href="javascript:void(0)" onclick="shortcut(\'plugin-marketplace\');"><span lang="en">The following plugin(s) need updates</span></a>: ' + 5692 pluginsNeedingUpdate, 5693 activeInfo.settings.notifications.position, 5694 "#FFF", 5695 "update", 5696 "600000" 5697 ); 5698 } 5699 } catch (e) { 5700 organizrCatchError(e, data); 5701 } 5702 }) 5703 .fail(function (xhr) { 5704 OrganizrApiError(xhr, "Marketplace"); 5705 }); 5706} 5707function checkCommitLoad() { 5708 if ( 5709 activeInfo.settings.misc.docker && 5710 activeInfo.settings.misc.githubCommit !== "n/a" && 5711 activeInfo.settings.misc.githubCommit !== null 5712 ) { 5713 if (checkCommitLoadStatus == false) { 5714 checkCommitLoadStatus = true; 5715 getLatestCommitJSON() 5716 .success(function (data) { 5717 try { 5718 var latest = data.sha.toString().trim(); 5719 var current = activeInfo.settings.misc.githubCommit 5720 .toString() 5721 .trim(); 5722 var link = 5723 "https://github.com/causefx/Organizr/compare/" + 5724 current + 5725 "..." + 5726 latest; 5727 if (latest !== current) { 5728 messageSingle( 5729 window.lang.translate("Update Available"), 5730 ' <a href="' + 5731 link + 5732 '" target="_blank"><span lang="en">Compare Difference</span></a> <span lang="en">or</span> <a href="javascript:void(0)" onclick="updateNow()"><span lang="en">
5732Update Now</span></a>', 5733 activeInfo.settings.notifications.position, 5734 "#FFF", 5735 "update", 5736 "600000" 5737 ); 5738 } else { 5739 organizrConsole( 5740 "Update Function", 5741 "Organizr Docker - Up to date" 5742 ); 5743 } 5744 } catch (e) { 5745 organizrCatchError(e, data); 5746 } 5747 checkCommitLoadStatus = false; 5748 }) 5749 .fail(function (xhr) { 5750 console.error("Organizr Function: Github Connection Failed"); 5751 checkCommitLoadStatus = false; 5752 }); 5753 } 5754 } 5755} 5756function sponsorLoad() { 5757 sponsorsJSON() 5758 .success(function (data) { 5759 try { 5760 var response = JSON.parse(data); 5761 } catch (e) { 5762 organizrCatchError(e, data); 5763 } 5764 $("#sponsorList").html(buildSponsor(response)); 5765 $("#sponsorListModals").html(buildSponsorModal(response)); 5766 $(".sponsor-items").owlCarousel({ 5767 nav: false, 5768 autoplay: true, 5769 dots: false, 5770 margin: 10, 5771 autoWidth: true, 5772 items: 4, 5773 }); 5774 }) 5775 .fail(function (xhr) { 5776 OrganizrApiError(xhr); 5777 }); 5778} 5779function backersLoad() { 5780 organizrAPI2("GET", "api/v2/sponsors/all") 5781 .success(function (data) { 5782 try { 5783 let json = data.response; 5784 $("#backersList").html(buildBackers(json.data)); 5785 $(".backers-items").owlCarousel({ 5786 nav: false, 5787 autoplay: true, 5788 dots: false, 5789 margin: 10, 5790 autoWidth: true, 5791 items: 4, 5792 }); 5793 } catch (e) { 5794 organizrCatchError(e, data); 5795 } 5796 }) 5797 .fail(function (xhr) { 5798 OrganizrApiError(xhr); 5799 }); 5800} 5801function buildBackers(array) { 5802 let backers = ""; 5803 $.each(array, function (i, v) { 5804 if (v.type == "USER" && v.role == "BACKER" && v.isActive) { 5805 v.name = v.name ? v.name : "User"; 5806 v.image = v.image ? v.image : "plugins/images/default_user.png"; 5807 backers += ` 5808 <!-- /.usercard --> 5809 <div class="item lazyload recent-sponsor imageSource" data-src="${v.image}"> 5810 <span class="elip recent-title">${v.name}</span> 5811 </div> 5812 <!-- /.usercard--> 5813 `; 5814 } 5815 }); 5816 backers += ` 5817 <!-- /.usercard --> 5818 <div class="item lazyload recent-sponsor mouse imageSource mouse" onclick="window.open('https://opencollective.com/organizr', '_blank')" data-src="plugins/images/sponsor-open-collective.png"> 5819 <span class="elip recent-title" lang="en">You</span> 5820 </div> 5821 <!-- /.usercard--> 5822 `; 5823 return backers; 5824} 5825function sponsorDetails(id) { 5826 sponsorsJSON() 5827 .success(function (data) { 5828 try { 5829 let response = JSON.parse(data); 5830 let coupon = response[id].coupon == null ? false : true; 5831 let couponAbout = response[id].coupon_about == null ? false : true; 5832 let extraInfo = 5833 coupon && couponAbout 5834 ? ` 5835 <hr/> 5836 <h3>Coupon Code:</h3> 5837 <p><span class="label label-rouded label-info pull-right">${response[id].coupon}</span> 5838 <span class=" pull-left">${response[id].coupon_about}</span></p> 5839 ` 5840 : ""; 5841 if (typeof response[id].logo_dark !== "undefined") { 5842 if (activeInfo.style == "dark") { 5843 response[id].logo = response[id].logo_dark; 5844 } 5845 } 5846 let html = ` 5847 <div class="panel panel-default"> 5848 <div class="panel-heading">${response[id].company_name}</div> 5849 <div class="panel-wrapper collapse in"> 5850 <div class="panel-body"> 5851 <div class="overlay-box"> 5852 <div class="user-content"> 5853 <a href="javascript:void(0)"><img src="${response[id].logo}" class="thumb-lg img-circle" alt="img"></a> 5854 <h4 class="text-white">${response[id].company_name}</h4> 5855 <h5 class="text-white"><a href="${response[id].website}" target="_blank">Website</a></h5> 5856 </div> 5857 </div> 5858 <hr/> 5859 <div class="text-left">${response[id].about} ${extraInfo}</div> 5860 </div> 5861 </div> 5862 </div> 5863 `; 5864 swal({ 5865 content: createElementFromHTML(html),
5866 buttons: false, 5867 className: "bg-org", 5868 }); 5869 } catch (e) { 5870 organizrCatchError(e, data); 5871 } 5872 }) 5873 .fail(function (xhr) { 5874 OrganizrApiError(xhr); 5875 }); 5876} 5877function sponsorAbout(id, array) { 5878 var coupon = array.coupon != null; 5879 var couponAbout = array.coupon_about != null; 5880 var extraInfo = 5881 coupon && couponAbout 5882 ? ` 5883 <h3>Coupon Code:</h3> 5884 <p><span class="label label-rouded label-info pull-right">` + 5885 array.coupon + 5886 `</span> 5887 <span class=" pull-left">` + 5888 array.coupon_about + 5889 `</span></p> 5890 ` 5891 : ""; 5892 if (typeof array.logo_dark !== "undefined") { 5893 if (activeInfo.style == "dark") { 5894 array.logo = array.logo_dark; 5895 } 5896 } 5897 return ( 5898 ` 5899 <!-- modal content --> 5900 <div id="sponsor-` + 5901 id + 5902 `-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel-` + 5903 id + 5904 `" aria-hidden="true" style="display: none;"> 5905 <div class="modal-dialog"> 5906 <div class="modal-content"> 5907 <div class="modal-header"> 5908 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> 5909 <h4 class="modal-title" id="mySmallModalLabel-` + 5910 id + 5911 `">` + 5912 array.company_name + 5913 `</h4> </div> 5914 <div class="modal-body"> 5915 <div class="row"> 5916 <div class="col-md-12"> 5917 <div class="comment-center p-t-10"> 5918 <div class="comment-body b-none"> 5919 <div class="user-img"> <img src="` + 5920 array.logo + 5921 `" alt="user" class="img-circle"> </div> 5922 <div class="mail-content"> 5923 <h5><a href="` + 5924 array.website + 5925 `" target="_blank">` + 5926 array.company_name + 5927 `</a></h5> 5928 ` + 5929 array.about + 5930 extraInfo + 5931 ` 5932 </div> 5933 </div> 5934 </div> 5935 </div> 5936 </div> 5937 </div> 5938 </div> 5939 <!-- /.modal-content --> 5940 </div> 5941 <!-- /.modal-dialog --> 5942 </div> 5943 <!-- /.modal --> 5944 ` 5945 ); 5946} 5947function buildSponsor(array) { 5948 var sponsors = ""; 5949 $.each(array, function (i, v) { 5950 var hasCoupon = ""; 5951 if (v.about) { 5952 if (v.coupon) { 5953 hasCoupon = ` 5954 <span class="text-center has-coupon-text">Has Coupon</span> 5955 <span class="text-center has-coupon"><i class="fa fa-ticket" aria-hidden="true"></i></span> 5956 `; 5957 } 5958 } 5959 var sponsorAboutModal = v.about 5960 ? "onclick=\"sponsorDetails('" + 5961 i + 5962 "');sponsorAnalytics('" + 5963 v.company_name + 5964 "');\"" 5965 : "onclick=\"window.open('" + 5966 v.website + 5967 "', '_blank');sponsorAnalytics('" + 5968 v.company_name + 5969 "');\""; 5970 if (typeof v.logo_dark !== "undefined") { 5971 if (activeInfo.style == "dark") { 5972 v.logo = v.logo_dark; 5973 } 5974 } 5975 sponsors += ` 5976 <!-- /.usercard --> 5977 <div class="item lazyload recent-sponsor mouse imageSource mouse" ${sponsorAboutModal} data-src="${v.logo}" data-id="${i}"> 5978 <span class="elip recent-title">${v.company_name}</span> 5979 ${hasCoupon} 5980 </div> 5981 <!-- /.usercard--> 5982 `; 5983 }); 5984 sponsors += ` 5985 <!-- /.usercard --> 5986 <div class="item lazyload recent-sponsor mouse imageSource mouse" onclick="window.open('https://www.patreon.com/bePatron?c=1320444&rid=2874514', '_blank')" data-src="plugins/images/sponsor-patreon.png"> 5987 <span class="elip recent-title" lang="en">Patreon Sponsor</span> 5988 </div> 5989 <div class="item lazyload recent-sponsor mouse imageSource mouse" onclick="window.open('https://opencollective.com/organizr', '_blank')" data-src="plugins/images/sponsor-open-collective.png">
5990 <span class="elip recent-title" lang="en">OpenCollective Sponsor</span> 5991 </div> 5992 <!-- /.usercard--> 5993 `; 5994 return sponsors; 5995} 5996function buildSponsorModal(array) { 5997 var sponsors = ""; 5998 $.each(array, function (i, v) { 5999 var sponsorAboutModal = v.about ? sponsorAbout(i, v) : ""; 6000 sponsors += sponsorAboutModal; 6001 }); 6002 return sponsors; 6003} 6004function sponsorAnalytics(sponsor_name) { 6005 var uuid = activeInfo.settings.misc.uuid; 6006 $.ajax({ 6007 type: "POST", 6008 url: "https://api.organizr.app/", 6009 data: { 6010 sponsor_name: sponsor_name, 6011 user_uuid: uuid, 6012 cmd: "sponsor", 6013 }, 6014 cache: false, 6015 async: true, 6016 complete: function (xhr, status) { 6017 if (xhr.status === 200) { 6018 let result = $.parseJSON(xhr.responseText); 6019 } 6020 }, 6021 }); 6022} 6023function themeAnalytics(theme_name) { 6024 var uuid = activeInfo.settings.misc.uuid; 6025 $.ajax({ 6026 type: "POST", 6027 url: "https://api.organizr.app/", 6028 data: { 6029 theme_name: theme_name, 6030 user_uuid: uuid, 6031 cmd: "theme", 6032 }, 6033 cache: false, 6034 async: true, 6035 complete: function (xhr, status) { 6036 if (xhr.status === 200) { 6037 let result = $.parseJSON(xhr.responseText); 6038 } 6039 }, 6040 }); 6041} 6042function getOrganizrBackups() { 6043 organizrAPI2("GET", "api/v2/backup") 6044 .success(function (data) { 6045 try { 6046 let json = data.response; 6047 $("#backup-file-list").html(buildOrganizrBackups(json.data)); 6048 } catch (e) { 6049 organizrCatchError(e, data); 6050 } 6051 }) 6052 .fail(function (xhr) { 6053 OrganizrApiError(xhr); 6054 }); 6055} 6056function createOrganizrBackup() { 6057 $("#settings-settings-backup").block({ 6058 message: 6059 '<p style="margin:0;padding:8px;font-size:24px;" lang="en">Backing up...</p>', 6060 css: { 6061 color: "#fff", 6062 border: "1px solid #5761a9", 6063 backgroundColor: "#707cd2", 6064 }, 6065 }); 6066 organizrAPI2("POST", "api/v2/backup", {}) 6067 .success(function (data) { 6068 try { 6069 let response = data.response; 6070 if (response) { 6071 getOrganizrBackups(); 6072 } 6073 } catch (e) { 6074 organizrCatchError(e, data); 6075 } 6076 $("#settings-settings-backup").unblock(); 6077 }) 6078 .fail(function (xhr) { 6079 $("#settings-settings-backup").unblock(); 6080 OrganizrApiError(xhr, "Backup Error"); 6081 }); 6082} 6083function buildOrganizrBackups(array) { 6084 let list = ""; 6085 if (array.total_files > 0) { 6086 $.each(array.files, function (i, v) { 6087 i++; 6088 let pattern = /\[[^\]]*\]/gm; 6089 let version = 6090 typeof v.name.match(pattern)[1] !== "undefined" 6091 ? v.name.match(pattern)[1] 6092 : "N/A"; 6093 list += ` 6094 <tr> 6095 <td>${i}</td> 6096 <td class="txt-oflo">${v.name}</td> 6097 <td><span class="label label-primary label-rouded">${version}</span> </td> 6098 <td class="txt-oflo">${v.size}</td> 6099 <td><span class="text-info tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="${moment( 6100 v.date 6101 ).format("LLL")}">${moment 6102 .utc(v.date, "YYYY-MM-DD hh:mm[Z]") 6103 .local() 6104 .fromNow()}</span></td> 6105 <td><span class="text-primary"><a href="api/v2/backup/${ 6106 v.name 6107 }"><i class="fa fa-download download-backup" data-file="${ 6108 v.name 6109 }"></i></a> | <a href="javascript:void(0)"><i class="fa fa-trash-o delete-backup" data-file="${ 6110 v.name 6111 }"></i></a></span></td> 6112 </tr> 6113 `; 6114 }); 6115 } else { 6116 list = 6117 '<tr><td class="text-center" colspan="6">No Backups made yet</td></tr>'; 6118 } 6119 $("#backup-total-files").html(array.total_files); 6120 $("#backup-total-size").html(array.total_size); 6121 return list; 6122} 6123function updateBar() { 6124 return ` 6125 <div class="white-box m-0"> 6126 <div class="row"> 6127 <div class="col-lg-12"> 6128 <h3 id="update-title" class="box-title pull-left"></h3><h3 id="update-time" class="box-title pull-right hidden"><span id="update-seconds"></span> <span lang="en">Seconds</span></h3> 6129 <div class="clearfix"></div> 6130 <div class="progress progress-lg"> 6131 <div id="update-bar" class="progress-bar progress-bar-primary progress-bar-striped active" style="width: 0%;" role="progressbar">0%</div> 6132 </div> 6133 </div> 6134 <h6>If error occurs - Use Esc key to close modal</h6> 6135 </div> 6136 </div> 6137 `; 6138} 6139function showUpdateBar() { 6140 swal({ 6141 content: createElementFromHTML(updateBar()),
6142 buttons: false, 6143 className: "bg-org", 6144 closeOnClickOutside: false, 6145 }); 6146} 6147function updateUpdateBar(title, percent, update = false) { 6148 $("#update-title").text(title); 6149 $("#update-bar").text(percent); 6150 $("#update-bar").css("width", percent); 6151 if (update) { 6152 $("#update-time").removeClass("hidden"); 6153 countdown(10); 6154 } 6155} 6156function countdown(remaining) { 6157 if (remaining === 0) { 6158 local("set", "message", "Organizr Update|Update Successful|update"); 6159 location.reload(true); 6160 } 6161 $("#update-seconds").text(remaining); 6162 setTimeout(function () { 6163 countdown(remaining - 1); 6164 }, 1000); 6165} 6166function dockerUpdate() { 6167 if (activeInfo.settings.misc.docker) { 6168 showUpdateBar(); 6169 updateUpdateBar("Starting Download", "20%"); 6170 messageSingle( 6171 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6172 window.lang.translate("Starting Update Process"), 6173 activeInfo.settings.notifications.position, 6174 "#FFF", 6175 "success", 6176 "60000" 6177 ); 6178 organizrAPI2("GET", "api/v2/update/docker") 6179 .success(function (data) { 6180 updateUpdateBar("Restarting Organizr in", "100%", true); 6181 messageSingle( 6182 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6183 "Update complete", 6184 activeInfo.settings.notifications.position, 6185 "#FFF", 6186 "success", 6187 "60000" 6188 ); 6189 }) 6190 .fail(function (xhr) { 6191 OrganizrApiError(xhr, "Update Error"); 6192 }); 6193 } 6194} 6195function windowsUpdate() { 6196 if (activeInfo.serverOS == "win") { 6197 showUpdateBar(); 6198 updateUpdateBar("Starting Download", "20%"); 6199 messageSingle( 6200 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6201 window.lang.translate("Starting Update Process"), 6202 activeInfo.settings.notifications.position, 6203 "#FFF", 6204 "success", 6205 "60000" 6206 ); 6207 organizrAPI2("GET", "api/v2/update/windows") 6208 .success(function (data) { 6209 updateUpdateBar("Restarting Organizr in", "100%", true); 6210 messageSingle( 6211 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6212 "Update complete", 6213 activeInfo.settings.notifications.position, 6214 "#FFF", 6215 "success", 6216 "60000" 6217 ); 6218 }) 6219 .fail(function (xhr) { 6220 OrganizrApiError(xhr, "Update Error"); 6221 }); 6222 } 6223} 6224function linuxUpdate() { 6225 if (activeInfo.serverOS !== "win" && !activeInfo.settings.misc.docker) { 6226 showUpdateBar(); 6227 updateUpdateBar("Starting Download", "20%"); 6228 messageSingle( 6229 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6230 window.lang.translate("Starting Update Process"), 6231 activeInfo.settings.notifications.position, 6232 "#FFF", 6233 "success", 6234 "60000" 6235 ); 6236 organizrAPI2("GET", "api/v2/update/linux") 6237 .success(function (data) { 6238 updateUpdateBar("Restarting Organizr in", "100%", true); 6239 messageSingle( 6240 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6241 "Update complete", 6242 activeInfo.settings.notifications.position, 6243 "#FFF", 6244 "success", 6245 "60000" 6246 ); 6247 }) 6248 .fail(function (xhr) { 6249 OrganizrApiError(xhr, "Update Error"); 6250 }); 6251 } 6252} 6253function updateNow() { 6254 clearAJAX(); 6255 if (activeInfo.settings.misc.docker) { 6256 dockerUpdate(); 6257 return false; 6258 } 6259 if (activeInfo.serverOS === "win") { 6260 windowsUpdate(); 6261 return false; 6262 } 6263 if (activeInfo.serverOS !== "win" && !activeInfo.settings.misc.docker) { 6264 linuxUpdate(); 6265 return false; 6266 } 6267 organizrConsole("Update Function", "Starting Update Process"); 6268 showUpdateBar(); 6269 updateUpdateBar("Starting Download", "5%"); 6270 messageSingle( 6271 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6272 window.lang.translate("Starting Update Process"), 6273 activeInfo.settings.notifications.position, 6274 "#FFF", 6275 "success", 6276 "60000" 6277 ); 6278 organizrAPI2("GET", "api/v2/update/download/" + activeInfo.branch) 6279 .success(function (data) { 6280 updateUpdateBar("Starting Unzip", "50%"); 6281 messageSingle( 6282 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6283 window.lang.translate("Update File Downloaded"), 6284 activeInfo.settings.notifications.position, 6285 "#FFF", 6286 "success", 6287 "60000" 6288 ); 6289 organizrAPI2("GET", "api/v2/update/unzip/" + activeInfo.branch) 6290 .success(function (data) { 6291 updateUpdateBar("Starting Copy", "70%"); 6292 messageSingle( 6293 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6294 window.lang.translate("Update File Unzipped"), 6295 activeInfo.settings.notifications.position, 6296 "#FFF", 6297 "success", 6298 "60000" 6299 ); 6300 organizrAPI2("GET", "api/v2/update/move/" + activeInfo.branch) 6301 .success(function (data) { 6302 updateUpdateBar("Starting Cleanup", "90%"); 6303 messageSingle( 6304 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6305 window.lang.translate("Update Files Copied"), 6306 activeInfo.settings.notifications.position, 6307 "#FFF", 6308 "success", 6309 "60000" 6310 ); 6311 organizrAPI2("GET", "api/v2/update/cleanup/" + activeInfo.branch) 6312 .success(function (data) { 6313 updateUpdateBar("Restarting Organizr in", "100%", true); 6314 messageSingle( 6315 window.lang.translate("[DO NOT CLOSE WINDOW]"), 6316 window.lang.translate("Update Cleanup Finished"), 6317 activeInfo.settings.notifications.position, 6318 "#FFF", 6319 "success", 6320 "60000" 6321 ); 6322 }) 6323 .fail(function (xhr) { 6324 OrganizrApiError(xhr, "Update Error"); 6325 }); 6326 }) 6327 .fail(function (xhr) { 6328 OrganizrApiError(xhr, "Update Error"); 6329 }); 6330 }) 6331 .fail(function (xhr) { 6332 OrganizrApiError(xhr, "Update Error"); 6333 }); 6334 }) 6335 .fail(function (xhr) { 6336 OrganizrApiError(xhr, "Update Error"); 6337 }); 6338} 6339function settingsAPI2(post, callbacks = null, asyncValue = true) { 6340 organizrAPI2("POST", post.api, post.data, asyncValue) 6341 .success(function (data) {
6342 try { 6343 var response = JSON.parse(data); 6344 } catch (e) { 6345 organizrCatchError(e, data); 6346 } 6347 message( 6348 post.messageTitle, 6349 post.messageBody, 6350 activeInfo.settings.notifications.position, 6351 "#FFF", 6352 "success", 6353 "5000" 6354 ); 6355 if (callbacks) { 6356 callbacks.fire(); 6357 } 6358 }) 6359 .fail(function (xhr) { 6360 console.error(post.error); 6361 }); 6362} 6363$.xhrPool.abortAll = function (url) { 6364 $(this).each(function (i, jqXHR) { 6365 // cycle through list of recorded connection 6366 if (!url || url === jqXHR.requestURL) { 6367 organizrConsole("Organizr API Abort", jqXHR.requestURL, "info"); 6368 jqXHR.abort(); // aborts connection 6369 $.xhrPool.splice(i, 1); // removes from list by index 6370 } 6371 }); 6372}; 6373$.ajaxPrefilter(function (options, originalOptions, jqXHR) { 6374 //organizrConsole('Organizr API Function',options.url,'info'); 6375 jqXHR.requestURL = options.url; 6376}); 6377function organizrAPI2(type, path, data = null, asyncValue = true) { 6378 $.xhrPool.abortAll(path); 6379 var timeout = 10000; 6380 switch (path) { 6381 case "api/v2/update/windows": 6382 case "api/v2/update/docker": 6383 case "api/v2/login": 6384 timeout = 240000; 6385 break; 6386 default: 6387 timeout = 60000; 6388 } 6389 switch (type) { 6390 case "get": 6391 case "GET": 6392 case "g": 6393 return $.ajax({ 6394 url: path, 6395 method: "GET", 6396 beforeSend: function (request) { 6397 request.setRequestHeader("Token", activeInfo.token); 6398 request.setRequestHeader("formKey", local("g", "formKey")); 6399 $.xhrPool.push(request); 6400 }, 6401 complete: function (jqXHR) { 6402 var i = $.xhrPool.indexOf(jqXHR); // get index for current connection completed 6403 if (i > -1) $.xhrPool.splice(i, 1); // removes from list by index 6404 }, 6405 timeout: timeout, 6406 }); 6407 case "delete": 6408 case "DELETE": 6409 case "d": 6410 return $.ajax({ 6411 url: path, 6412 method: "DELETE", 6413 beforeSend: function (request) { 6414 request.setRequestHeader("Token", activeInfo.token); 6415 request.setRequestHeader("formKey", local("g", "formKey")); 6416 $.xhrPool.push(request); 6417 }, 6418 complete: function (jqXHR) { 6419 var i = $.xhrPool.indexOf(jqXHR); // get index for current connection completed 6420 if (i > -1) $.xhrPool.splice(i, 1); // removes from list by index 6421 }, 6422 timeout: timeout, 6423 }); 6424 case "post": 6425 case "POST": 6426 case "p": 6427 data.formKey = local("g", "formKey"); 6428 return $.ajax({ 6429 url: path, 6430 method: "POST", 6431 async: asyncValue, 6432 beforeSend: function (request) { 6433 request.setRequestHeader("Token", activeInfo.token); 6434 request.setRequestHeader("formKey", local("g", "formKey")); 6435 $.xhrPool.push(request); 6436 }, 6437 complete: function (jqXHR) { 6438 var i = $.xhrPool.indexOf(jqXHR); // get index for current connection completed 6439 if (i > -1) $.xhrPool.splice(i, 1); // removes from list by index 6440 }, 6441 data: data, 6442 }); 6443 case "put": 6444 case "PUT": 6445 data.formKey = local("g", "formKey"); 6446 return $.ajax({ 6447 url: path, 6448 method: "PUT", 6449 async: asyncValue, 6450 beforeSend: function (request) { 6451 request.setRequestHeader("Token", activeInfo.token); 6452 request.setRequestHeader("formKey", local("g", "formKey")); 6453 $.xhrPool.push(request); 6454 }, 6455 complete: function (jqXHR) { 6456 var i = $.xhrPool.indexOf(jqXHR); // get index for current connection completed 6457 if (i > -1) $.xhrPool.splice(i, 1); // removes from list by index 6458 }, 6459 data: JSON.stringify(data), 6460 contentType: "application/json", 6461 }); 6462 default: 6463 console.warn("Organizr API: Method Not Supported"); 6464 } 6465} 6466function loadSettingsPage2(api, element, organizrFn) { 6467 $(element).html( 6468 '<h2 class="col-lg-12 m-t-0 text-center well bg-org"><i class="fa fa-spin fa-refresh"></i><br> <span lang="en">Loading</span></h2><div class="clearfix"></div>' 6469 ); 6470 organizrAPI2("get", api) 6471 .success(function (data) {
6472 try { 6473 var response = data.response; 6474 } catch (e) { 6475 organizrCatchError(e, data); 6476 } 6477 organizrConsole("Organizr Function", "Loading " + organizrFn); 6478 $(element).html(response.data); 6479 }) 6480 .fail(function (xhr) { 6481 OrganizrApiError(xhr); 6482 }); 6483} 6484function loadInternal(id, split = null) { 6485 let extra = split ? "right-" : ""; 6486 let tabInfo = findTab(id); 6487 if (!tabInfo) { 6488 organizrConsole("Load Internal", "No Tab Info Found... Id: " + id, "error"); 6489 return false; 6490 } 6491 let url = tabInfo.access_url; 6492 organizrAPI2("get", url) 6493 .success(function (data) { 6494 try { 6495 var html = data.response; 6496 $("#internal-" + extra + id).html(html.data); 6497 } catch (e) { 6498 organizrCatchError(e, data); 6499 } 6500 }) 6501 .fail(function (xhr) { 6502 OrganizrApiError(xhr); 6503 }); 6504} 6505function loadInternalOriginal(url, tabName) { 6506 organizrAPI("get", url) 6507 .success(function (data) { 6508 try { 6509 var html = JSON.parse(data); 6510 } catch (e) { 6511 organizrCatchError(e, data); 6512 } 6513 $("#internal-" + tabName).html(html.data); 6514 }) 6515 .fail(function (xhr) { 6516 OrganizrApiError(xhr); 6517 }); 6518} 6519function loadSettingsPage(api, element, organizrFn) { 6520 organizrAPI("get", api) 6521 .success(function (data) { 6522 try { 6523 var response = JSON.parse(data); 6524 } catch (e) { 6525 organizrCatchError(e, data); 6526 } 6527 organizrConsole("Organizr Function", "Loading " + organizrFn); 6528 $(element).html(response.data); 6529 }) 6530 .fail(function (xhr) { 6531 OrganizrApiError(xhr); 6532 }); 6533} 6534function settingsAPI(post, callbacks = null, asyncValue = true) { 6535 organizrAPI("POST", post.api, post, asyncValue) 6536 .success(function (data) { 6537 try { 6538 var response = JSON.parse(data); 6539 } catch (e) { 6540 organizrCatchError(e, data); 6541 } 6542 message( 6543 post.messageTitle, 6544 post.messageBody, 6545 activeInfo.settings.notifications.position, 6546 "#FFF", 6547 "success", 6548 "5000" 6549 ); 6550 if (callbacks) { 6551 callbacks.fire(); 6552 } 6553 }) 6554 .fail(function (xhr) { 6555 console.error(post.error); 6556 }); 6557} 6558function organizrAPI(type, path, data = null, asyncValue = true) { 6559 var timeout = 10000; 6560 switch (path) { 6561 case "api/?v1/windows/update": 6562 case "api/?v1/docker/update": 6563 timeout = 120000; 6564 break; 6565 default: 6566 timeout = 60000; 6567 } 6568 switch (type) { 6569 case "get": 6570 case "GET": 6571 case "g": 6572 return $.ajax({ 6573 url: path, 6574 method: "GET", 6575 beforeSend: function (request) { 6576 request.setRequestHeader("Token", activeInfo.token); 6577 request.setRequestHeader("formKey", local("g", "formKey")); 6578 }, 6579 timeout: timeout, 6580 }); 6581 case "post": 6582 case "POST": 6583 case "p": 6584 data.formKey = local("g", "formKey"); 6585 return $.ajax({ 6586 url: path, 6587 method: "POST", 6588 async: asyncValue, 6589 beforeSend: function (request) { 6590 request.setRequestHeader("Token", activeInfo.token); 6591 request.setRequestHeader("formKey", local("g", "formKey")); 6592 }, 6593 data: { 6594 data: data, 6595 }, 6596 }); 6597 default: 6598 console.warn("Organizr API: Method Not Supported"); 6599 } 6600} 6601function githubVersions() { 6602 return $.ajax({ 6603 url: 6604 "https://raw.githubusercontent.com/causefx/Organizr/" + 6605 activeInfo.branch + 6606 "/js/version.json", 6607 }); 6608} 6609function sponsorsJSON() { 6610 return $.ajax({ 6611 url: "https://raw.githubusercontent.com/causefx/Organizr/v2-develop/js/sponsors.json", 6612 }); 6613} 6614function newsJSON() { 6615 return $.ajax({ 6616 url: "https://raw.githubusercontent.com/causefx/Organizr/v2-develop/js/news.json", 6617 }); 6618} 6619function getLatestCommitJSON() { 6620 return $.ajax({ 6621 url: 6622 "https://api.github.com/repos/causefx/Organizr/commits/" + 6623 activeInfo.branch, 6624 }); 6625} 6626function marketplaceJSON(type) { 6627 return $.ajax({ 6628 url: 6629 "https://raw.githubusercontent.com/causefx/Organizr/v2-" + 6630 type + 6631 "/" + 6632 type + 6633 ".json", 6634 }); 6635} 6636function allIcons() { 6637 return $.ajax({ 6638 url: "js/icons.json", 6639 }); 6640} 6641function organizrConnect(path) { 6642 return $.ajax({ 6643 url: path, 6644 }); 6645} 6646function changeSettingsMenu(path) { 6647 var menuItems = path.split("::"); 6648 var menu = ""; 6649 if (Array.isArray(menuItems)) { 6650 $.each(menuItems, function (i, v) { 6651 menu += '<li><a lang="en">' + v + "</a></li>"; 6652 }); 6653 } 6654 $("#settingsBreadcrumb").html(menu); 6655} 6656function buildWizard() { 6657 organizrAPI2("GET", "api/v2/page/wizard") 6658 .success(function (data) {
6659 try { 6660 var json = data.response; 6661 } catch (e) { 6662 organizrCatchError(e, data); 6663 } 6664 organizrConsole("Organizr Function", "Starting Install Wizard"); 6665 $(json.data).appendTo($(".organizr-area")); 6666 $(".organizr-area").removeClass("hidden"); 6667 }) 6668 .fail(function (xhr) { 6669 OrganizrApiError(xhr, "Wiizard Error"); 6670 }); 6671 $("#preloader").fadeOut(); 6672} 6673function buildDependencyCheck(orgdata) { 6674 organizrAPI2("GET", "api/v2/page/dependencies") 6675 .success(function (data) { 6676 try { 6677 var json = data.response; 6678 } catch (e) { 6679 organizrCatchError(e, data); 6680 } 6681 organizrConsole("Organizr Function", "Starting Dependencies Check"); 6682 $(json.data).appendTo($(".organizr-area")); 6683 $(".organizr-area").removeClass("hidden"); 6684 $(buildBrowserInfo()).appendTo($("#browser-info")); 6685 $("#web-folder").html(buildWebFolder(orgdata)); 6686 $("#php-version-check").html(buildPHPCheck(orgdata)); 6687 $(buildDependencyInfo(orgdata)).appendTo($("#depenency-info")); 6688 }) 6689 .fail(function (xhr) { 6690 OrganizrApiError(xhr, "Dependency Error"); 6691 }); 6692 $("#preloader").fadeOut(); 6693} 6694function buildDependencyInfo(arrayItems) { 6695 let listing = ""; 6696 $.each(arrayItems.data.status.dependenciesActive, function (i, v) { 6697 listing += 6698 '<li class="depenency-item" data-name="' + 6699 v + 6700 '"><a href="javascript:void(0)"><i class="fa fa-check text-success"></i> ' + 6701 v + 6702 "</a></li>"; 6703 }); 6704 $.each(arrayItems.data.status.dependenciesInactive, function (i, v) { 6705 listing += 6706 '<li class="depenency-item" data-name="' + 6707 v + 6708 '"><a href="javascript:void(0)"><i class="fa fa-close text-danger"><div class="notify"><span class="heartbit depend-heartbit"></span></div></i> ' + 6709 v + 6710 "</a></li>"; 6711 }); 6712 6713 let className = 6714 arrayItems.data.status.dependenciesInactive.length !== 0 6715 ? "bg-danger text-warning" 6716 : "bg-primary"; 6717 let icon = 6718 arrayItems.data.status.dependenciesInactive.length !== 0 6719 ? "fa fa-exclamation-triangle" 6720 : "fa fa-check-circle"; //dependency-dependencies-check-listing-header 6721 let header = 6722 arrayItems.data.status.dependenciesInactive.length !== 0 6723 ? "panel-danger" 6724 : "panel-info"; 6725 let listingIcon = 6726 arrayItems.data.status.dependenciesInactive.length !== 0 6727 ? "ti-alert" 6728 : "ti-check-box"; 6729 let listingText = 6730 arrayItems.data.status.dependenciesInactive.length !== 0 6731 ? "Dependencies Missing" 6732 : "Dependencies OK"; 6733 6734 $(".dependency-dependencies-check-listing-header") 6735 .removeClass("panel-danger") 6736 .addClass(header); 6737 $(".dependency-dependencies-check-listing i") 6738 .first() 6739 .removeClass("ti-alert") 6740 .addClass(listingIcon); 6741 $(".dependency-dependencies-check-listing span").text(listingText); 6742 $(".dependency-dependencies-check") 6743 .removeClass("bg-warning") 6744 .addClass(className); 6745 $(".dependency-dependencies-check i") 6746 .removeClass("fa fa-spin fa-spinner") 6747 .addClass(icon); 6748 return listing; 6749} 6750function buildWebFolder(arrayItems) { 6751 let writable = "Not Writable - Please fix permissions"; 6752 let className = "bg-danger text-warning"; 6753 let icon = "fa fa-exclamation-triangle"; 6754 if (arrayItems.data.status.writable == "yes") { 6755 writable = "Writable - All Good"; 6756 className = "bg-primary"; 6757 icon = "fa fa-check-circle"; 6758 } 6759 $(".dependency-permissions-check") 6760 .removeClass("bg-warning") 6761 .addClass(className); 6762 $(".dependency-permissions-check i") 6763 .removeClass("fa fa-spin fa-spinner") 6764 .addClass(icon); 6765 $("#web-folder").addClass(className); 6766 return writable; 6767} 6768function buildPHPCheck(arrayItems) { 6769 let phpTest = "Upgrade PHP Version to 7.2+"; 6770 let className = "bg-danger text-warning"; 6771 let icon = "fa fa-exclamation-triangle"; 6772 if (arrayItems.data.status.minVersion == "yes") { 6773 phpTest = "PHP Version Approved"; 6774 className = "bg-primary"; 6775 icon = "fa fa-check-circle"; 6776 } 6777 $(".dependency-phpversion-check") 6778 .removeClass("bg-warning") 6779 .addClass(className); 6780 $(".dependency-phpversion-check i") 6781 .removeClass("fa fa-spin fa-spinner") 6782 .addClass(icon); 6783 $("#php-version-check").addClass(className); 6784 $("#php-version-check-user").html( 6785 '<span lang="en">
6785Webserver User</span>: ' + arrayItems.data.status.php_user 6786 ); 6787 return phpTest; 6788} 6789function buildBrowserInfo() { 6790 var listing = ""; 6791 $.each(activeInfo, function (i, v) { 6792 listing += 6793 ` 6794 <tr> 6795 <td>` + 6796 i + 6797 `</td> 6798 <td>` + 6799 tof(v) + 6800 `</td> 6801 </tr> 6802 `; 6803 }); 6804 return ( 6805 ` 6806 <table class="table table-hover"> 6807 <tbody> 6808 ` + 6809 listing + 6810 ` 6811 </tbody> 6812 </table> 6813 ` 6814 ); 6815} 6816function tof(string, type) { 6817 var result; 6818 if ( 6819 typeof string == "undefined" || 6820 string == "false" || 6821 string == false || 6822 string == null || 6823 string == 0 || 6824 string == "off" || 6825 string == "no" 6826 ) { 6827 result = "0"; 6828 } else if ( 6829 string == "true" || 6830 string == true || 6831 string == 1 || 6832 string == "on" || 6833 string == "yes" 6834 ) { 6835 result = "1"; 6836 } 6837 switch (type) { 6838 case "bool": 6839 case "b": 6840 return result == "0" ? false : result == "1" ? true : string; 6841 case "switch": 6842 case "s": 6843 return result == "0" ? "off" : result == "1" ? "on" : string; 6844 case "checkbox": 6845 case "c": 6846 return result == "0" ? "" : result == "1" ? "checked" : string; 6847 case "integer": 6848 case "number": 6849 case "i": 6850 case "n": 6851 return result == "0" ? 0 : result == "1" ? 1 : string; 6852 case "question": 6853 case "q": 6854 return result == "0" ? "yes" : result == "1" ? "no" : string; 6855 case "string": 6856 return string.toString(); 6857 default: 6858 return result == "0" ? "false" : result == "1" ? "true" : string; 6859 } 6860} 6861function createRandomString(length) { 6862 var str = ""; 6863 for (; str.length < length; str += Math.random().toString(36).substr(2)); 6864 return str.substr(0, length); 6865} 6866function generateAPI() { 6867 var string = createRandomString(20); 6868 $("#form-api").focus(); 6869 $("#form-api").val(string); 6870 $("#form-api").focusout(); 6871 $("#verify-api").text(string); 6872 $("#form-username").focus(); 6873} 6874function getCookie(cname) { 6875 var name = cname + "="; 6876 var decodedCookie = decodeURIComponent(document.cookie); 6877 var ca = decodedCookie.split(";"); 6878 for (var i = 0; i < ca.length; i++) { 6879 var c = ca[i]; 6880 while (c.charAt(0) == " ") { 6881 c = c.substring(1); 6882 } 6883 if (c.indexOf(name) == 0) { 6884 return c.substring(name.length, c.length); 6885 } 6886 } 6887 return ""; 6888} 6889function localStorageSupport() { 6890 return "localStorage" in window && window["localStorage"] !== null; 6891} 6892function local(type, key, value = null) { 6893 if (localStorageSupport) { 6894 switch (type) { 6895 case "set": 6896 case "s": 6897 localStorage.setItem(key, value); 6898 break; 6899 case "get": 6900 case "g": 6901 return localStorage.getItem(key); 6902 case "remove": 6903 case "r": 6904 localStorage.removeItem(key); 6905 break; 6906 default: 6907 console.warn("Organizr Function: localStorage action not defined"); 6908 } 6909 } 6910} 6911function language(language) { 6912 var language = language.split("-"); 6913 return language[0]; 6914} 6915function logIcon(type, label = false) { 6916 type = type.toLowerCase(); 6917 let info = { color: "info", icon: "fa fa-check" }; 6918 switch (type) { 6919 case "success": 6920 info.color = "info"; 6921 info.icon = "fa fa-check"; 6922 break; 6923 case "info": 6924 info.color = "info"; 6925 info.icon = "mdi mdi-information"; 6926 break; 6927 case "notice": 6928 info.color = "inverse"; 6929 info.icon = "mdi mdi-information-variant"; 6930 break; 6931 case "debug": 6932 info.color = "primary"; 6933 info.icon = "mdi mdi-code-tags-check"; 6934 break; 6935 case "warning": 6936 info.color = "warning"; 6937 info.icon = "mdi mdi-alert-box"; 6938 break; 6939 case "error": 6940 info.color = "danger"; 6941 info.icon = "mdi mdi-alert-outline"; 6942 break; 6943 case "critical": 6944 info.color = "danger"; 6945 info.icon = "mdi mdi-alert"; 6946 break; 6947 case "alert": 6948 info.color = "danger"; 6949 info.icon = "mdi mdi-alert-octagon"; 6950 break; 6951 case "emergency": 6952 info.color = "danger"; 6953 info.icon = "mdi mdi-alert-octagram"; 6954 break; 6955 default: 6956 info = { color: "info", icon: "fa fa-check" }; 6957 break; 6958 } 6959 if (label) { 6960 return ( 6961 '<span class="label label-' + 6962 info.color + 6963 ' log-label"> <i class="fa ' + 6964 info.icon + 6965 ' m-l-5 fa-fw"></i> <span lang="en" class="text-uppercase">' + 6966 type + 6967 "</span></span>" 6968 ); 6969 } else { 6970 return ( 6971 '<button class="btn btn-xs btn-' + 6972 info.color + 6973 ' log-label no-mouse" type="button"><span class="btn-label pull-left"><i class="' + 6974 info.icon + 6975 ' fa-fw"></i></span><span class="text-uppercase" lang="en">' + 6976 type + 6977 "</span></button>" 6978 ); 6979 } 6980} 6981function toggleKillOrganizrLiveUpdate(interval = 5000) { 6982 if ($(".organizr-log-live-update").hasClass("kill-organizr-log")) { 6983 clearTimeout(timeouts["organizr-log"]); 6984 $(".organizr-log-live-update i").toggleClass( 6985 "fa-dot-circle-o animated loop-animation swing" 6986 ); 6987 $(".organizr-log-live-update").toggleClass("kill-organizr-log"); 6988 } else { 6989 $(".organizr-log-live-update").toggleClass("kill-organizr-log"); 6990 organizrLogLiveUpdate(interval); 6991 } 6992} 6993function organizrLogLiveUpdate(interval = 5000) { 6994 var timeout = interval; 6995 let timeoutTitle = "organizr-log"; 6996 $(".organizr-log-live-update i").toggleClass( 6997 "fa-dot-circle-o animated loop-animation swing" 6998 ); 6999 organizrLogTable.ajax.reload(null, false); 7000 setTimeout(function () { 7001 if ($(".organizr-log-live-update").hasClass("kill-organizr-log")) { 7002 $(".organizr-log-live-update i").toggleClass( 7003 "fa-dot-circle-o animated loop-animation swing" 7004 ); 7005 } 7006 }, interval - 500); 7007 if (typeof timeouts[timeoutTitle] !== "undefined") { 7008 clearTimeout(timeouts[timeoutTitle]); 7009 } 7010 timeouts[timeoutTitle] = setTimeout(function () { 7011 organizrLogLiveUpdate(timeout); 7012 }, timeout); 7013 delete timeout; 7014} 7015function radioLoop(element) {
7016 $('[type=radio][id!="' + element.id + '"]').each(function () { 7017 this.checked = false; 7018 }); 7019} 7020function loadAppearance(appearance) { 7021 var cssSettings = ""; 7022 document.title = appearance.title; 7023 if (appearance.useLogo === false) { 7024 $("#main-logo").html(appearance.title); 7025 $("#side-logo").html(appearance.title); 7026 } else { 7027 $("#main-logo").html( 7028 '<img alt="home" class="dark-logo" src="' + appearance.logo + '">' 7029 ); 7030 $("#side-logo").html( 7031 '<img alt="home" class="dark-logo-side" src="' + appearance.logo + '">' 7032 ); 7033 } 7034 if (appearance.headerColor !== "") { 7035 cssSettings += 7036 ` 7037 .navbar-header{ 7038 background: ` + 7039 appearance.headerColor + 7040 `; 7041 } 7042 `; 7043 } 7044 if (appearance.headerTextColor !== "") { 7045 cssSettings += 7046 ` 7047 .navbar-top-links > li > a { 7048 color: ` + 7049 appearance.headerTextColor + 7050 `; 7051 } 7052 `; 7053 } 7054 if (appearance.sidebarColor !== "") { 7055 cssSettings += 7056 ` 7057 .sidebar, .sidebar .sidebar-head{ 7058 background: ` + 7059 appearance.sidebarColor + 7060 `; 7061 } 7062 `; 7063 } 7064 if (appearance.sidebarTextColor !== "") { 7065 cssSettings += 7066 ` 7067 #side-menu li a, 7068 .sidebar .sidebar-head h3, 7069 #side-menu > li > a.active, #side-menu > li > ul > li > a.active 7070 { 7071 color: ` + 7072 appearance.sidebarTextColor + 7073 `; 7074 } 7075 `; 7076 } 7077 if (appearance.accentColor !== "") { 7078 cssSettings += 7079 ` 7080 .bg-info, 7081 .fc-toolbar, 7082 .progress-bar-info, 7083 .label-info, 7084 .tabs-style-iconbox nav ul li.tab-current a, 7085 .swapLog.active { 7086 background-color: ` + 7087 appearance.accentColor + 7088 ` !important; 7089 } 7090 .panel-blue .panel-heading, .panel-info .panel-heading { 7091 border-color: ` + 7092 appearance.accentColor + 7093 `; 7094 } 7095 .tabs-style-iconbox nav ul li.tab-current a::after { 7096 border-top-color: ` + 7097 appearance.accentColor + 7098 `; 7099 } 7100 .customvtab .tabs-vertical li.active a, 7101 .customvtab .tabs-vertical li.active a:focus, 7102 .customvtab .tabs-vertical li.active a:hover { 7103 border-right: 2px solid ` + 7104 appearance.accentColor + 7105 `; 7106 } 7107 .text-info, 7108 .btn-link, a { 7109 color: ` + 7110 appearance.accentColor + 7111 `; 7112 } 7113 `; 7114 } 7115 if (appearance.accentTextColor !== "") { 7116 cssSettings += 7117 ` 7118 .bg-info, 7119 .progress-bar, 7120 .panel-default .panel-heading, 7121 .mailbox-widget .customtab li.active a, .mailbox-widget .customtab li.active, .mailbox-widget .customtab li.active a:focus, 7122 .mailbox-widget .customtab li a, 7123 .tabs-style-iconbox nav ul li.tab-current a 7124 .swapLog.active { 7125 color: ` + 7126 appearance.accentTextColor + 7127 `; 7128 } 7129 `; 7130 } 7131 if (appearance.buttonColor !== "") { 7132 cssSettings += 7133 ` 7134 .btn-info, .btn-info.disabled, 7135 .btn, 7136 .paginate_button.current, 7137 .paginate_button:hover { 7138 background: ` + 7139 appearance.buttonColor + 7140 ` !important; 7141 border: 1px solid ` + 7142 appearance.buttonColor + 7143 ` !important; 7144 } 7145 `; 7146 } 7147 if (appearance.buttonTextColor !== "") { 7148 cssSettings += 7149 ` 7150 .btn-info, .btn-info.disabled, 7151 .btn 7152 .paginate_button.current 7153 .paginate_button:hover { 7154 color: ` + 7155 appearance.buttonTextColor + 7156 ` !important; 7157 } 7158 `; 7159 } 7160 if (appearance.loginWallpaper !== "" || appearance.randomMediaImage) { 7161 if (appearance.randomMediaImage) { 7162 appearance.loginWallpaper = appearance.randomMediaImage; 7163 } 7164 cssSettings += 7165 ` 7166 .login-register { 7167 background: url(` + 7168 randomCSV(appearance.loginWallpaper) + 7169 `) center center/cover no-repeat!important; 7170 height: 100%; 7171 position: fixed; 7172 } 7173 .lock-screen { 7174 background: url(` + 7175 randomCSV(appearance.loginWallpaper) + 7176 `) center center/cover no-repeat!important; 7177 height: 100%; 7178 position: fixed; 7179 z-index: 1001; 7180 top: 0; 7181 width: 100%; 7182 -webkit-user-select: none; 7183 -moz-user-select: none; 7184 -ms-user-select: none; 7185 -o-user-select: none; 7186 user-select: none; 7187 } 7188 `; 7189 } 7190 if (activeInfo["settings"]["misc"]["autoExpandNavBar"] == false) { 7191 cssSettings += ` 7192 @media only screen and (min-width: 768px) { 7193 .sidebar:hover .hide-menu { 7194 display: none; 7195 }
7196 .sidebar:hover .sidebar-head, 7197 .sidebar:hover { 7198 width: 60px; 7199 } 7200 .sidebar:hover .nav-second-level li a { 7201 padding-left: 15px; 7202 } 7203 } 7204 `; 7205 } 7206 if (cssSettings !== "") { 7207 $("#user-appearance").html(cssSettings); 7208 } 7209 if (appearance.customThemeCss !== "") { 7210 $("#custom-theme-css").html(appearance.customThemeCss); 7211 } 7212 if (appearance.customCss !== "") { 7213 $("#custom-css").html(appearance.customCss); 7214 } 7215} 7216function resetCustomColors() { 7217 let colors = [ 7218 "headerColor", 7219 "headerTextColor", 7220 "sidebarColor", 7221 "sidebarTextColor", 7222 "accentColor", 7223 "accentTextColor", 7224 "buttonColor", 7225 "buttonTextColor", 7226 ]; 7227 $.each(colors, function (i, v) { 7228 $("#customize-appearance-form [name=" + v + "]") 7229 .val("") 7230 .trigger("change"); 7231 }); 7232 messageSingle( 7233 window.lang.translate("Colors Reverted"), 7234 window.lang.translate("Please Save"), 7235 activeInfo.settings.notifications.position, 7236 "#FFF", 7237 "success", 7238 "10000" 7239 ); 7240} 7241function randomCSV(values) { 7242 if (typeof values == "string") { 7243 if (values.includes(",")) { 7244 var csv = values.split(","); 7245 var luckyNumber = Math.floor(Math.random() * csv.length); 7246 return csv[luckyNumber]; 7247 } else { 7248 return values; 7249 } 7250 } 7251 return false; 7252} 7253function loadCustomJava(appearance) { 7254 if (appearance.customThemeJava !== "") { 7255 $("#custom-theme-javascript").html(appearance.customThemeJava); 7256 } 7257 if (appearance.customJava !== "") { 7258 $("#custom-javascript").html(appearance.customJava); 7259 } 7260} 7261function clearForm(form) { 7262 $(form + " input[type=text]").each(function () { 7263 $(this).val(""); 7264 }); 7265 $(form + " input[type=password]").each(function () { 7266 $(this).val(""); 7267 }); 7268} 7269function checkMessage() { 7270 var check = local("get", "message") ? local("get", "message") : false; 7271 if (check) { 7272 local("remove", "message"); 7273 var message = check.split("|"); 7274 messageSingle( 7275 window.lang.translate(message[0]), 7276 window.lang.translate(message[1]), 7277 activeInfo.settings.notifications.position, 7278 "#FFF", 7279 message[2], 7280 "10000" 7281 ); 7282 } 7283} 7284function setError(error) { 7285 local("set", "error", error); 7286 var url = window.location.href.split("?")[0]; 7287 url = url.split("#")[0]; 7288 window.location.href = url + "?error"; 7289} 7290function buildErrorPage(error) { 7291 var description = ""; 7292 var message = ""; 7293 var color = ""; 7294 switch (error) { 7295 case "401": 7296 description = "Unauthorized"; 7297 message = "Look, you dont belong here"; 7298 color = "danger"; 7299 break; 7300 case "404": 7301 description = "Not Found"; 7302 message = "I think I lost it..."; 7303 color = "primary"; 7304 break; 7305 default: 7306 description = "Something happened"; 7307 message = "But I dont know what"; 7308 color = "muted"; 7309 } 7310 return ( 7311 ` 7312 <div class="error-box"> 7313 <div class="error-body text-center"> 7314 <h1 class="text-` + 7315 color + 7316 `">` + 7317 error + 7318 `</h1> 7319 <h3 class="text-uppercase">` + 7320 description + 7321 `</h3> 7322 <p class="text-muted m-t-30 m-b-30" lang="en">` + 7323 message + 7324 `</p> 7325 <a href="javascript:void(0);" class="btn btn-` + 7326 color + 7327 ` btn-rounded waves-effect waves-light m-b-40 closeErrorPage animated tada loop-animation" lang="en">OK</a> 7328 </div> 7329 </div> 7330 ` 7331 ); 7332} 7333$.urlParam = function (name) { 7334 var results = new RegExp("[?&]" + name + "=([^&#]*)").exec( 7335 window.location.href 7336 ); 7337 if (results == null) { 7338 return null; 7339 } else { 7340 return decodeURI(results[1]) || 0; 7341 } 7342}; 7343function errorPage(error = null, uri = null) { 7344 if (error) { 7345 local("set", "error", error); 7346 } 7347 if (uri) { 7348 local("set", "uri", uri); 7349 } 7350 //var urlParams = new URLSearchParams(window.location.search); 7351 7352 if ($.urlParam("error") !== null && !isNaN(Number($.urlParam("error")))) { 7353 local("set", "error", $.urlParam("error")); 7354 } 7355 if ($.urlParam("return") !== null && activeInfo.user.loggedin !== true) { 7356 local("set", "uri", $.urlParam("return")); 7357 } 7358 if (window.location !== window.parent.location) { 7359 var count = 0; 7360 for (var k in window.parent.location) { 7361 if (window.parent.location.hasOwnProperty(k)) { 7362 ++count; 7363 } 7364 } 7365 if (count == 0 || count == "undefined") { 7366 return false;
7367 } 7368 var iframeError = local("get", "error"); 7369 parent.errorPage(iframeError); 7370 local("remove", "uri"); 7371 $("html").html(""); 7372 return false; 7373 } 7374 if (local("get", "error")) { 7375 //show error page 7376 $(".error-page").html(buildErrorPage(local("get", "error"))); 7377 $(".error-page").fadeIn(); 7378 local("remove", "error"); 7379 window.history.pushState({}, document.title, "./"); 7380 } 7381} 7382function uriRedirect(uri = null) { 7383 if (uri) { 7384 local("set", "uri", uri); 7385 } 7386 if (activeInfo.user.loggedin === true && activeInfo.user.locked !== 1) { 7387 var redirect = local("get", "uri"); 7388 local("remove", "uri"); 7389 if (redirect !== null) { 7390 window.location.href = decodeURIComponent(decodeURI(redirect)); 7391 } 7392 } 7393} 7394function changeTheme(theme) { 7395 //$("#preloader").fadeIn(); 7396 $("#theme").attr({ 7397 href: theme + ".css?v=" + activeInfo.version, 7398 }); 7399 //$("#preloader").fadeOut(); 7400 console.info( 7401 "%c Theme %c ".concat(theme, " "), 7402 "color: white; background: #AD80FD; font-weight: 700;", 7403 "color: #AD80FD; background: white; font-weight: 700;" 7404 ); 7405} 7406function changeStyle(style) { 7407 //$("#preloader").fadeIn(); 7408 $("#style").attr({ 7409 href: "css/" + style + ".min.css?v=" + activeInfo.version, 7410 }); 7411 //$("#preloader").fadeOut(); 7412 console.info( 7413 "%c Style %c ".concat(style, " "), 7414 "color: white; background: #AD80FD; font-weight: 700;", 7415 "color: #AD80FD; background: white; font-weight: 700;" 7416 ); 7417} 7418function setSSO() { 7419 $.each(activeInfo.sso, function (i, v) { 7420 if (v !== false) { 7421 local("set", i, v); 7422 } else { 7423 local("r", i); 7424 } 7425 }); 7426 // other items to remove 7427 $.each(localStorage, function (i, v) { 7428 if (typeof v == "string") { 7429 if (i.startsWith("user-")) { 7430 if (typeof activeInfo.sso[i] == "undefined") { 7431 local("r", i); 7432 } 7433 } 7434 } 7435 }); 7436} 7437function buildStreamItem(array, source) { 7438 var cards = ""; 7439 var count = 0; 7440 var total = array.length; 7441 var sourceIcon = source === "jellyfin" ? "fish" : source; 7442 var streamDetails = { 7443 direct: 0, 7444 transcode: 0, 7445 }; 7446 var bandwidthDetails = { 7447 wan: 0, 7448 lan: 0, 7449 }; 7450 cards += '<div class="flexbox">'; 7451 $.each(array, function (i, v) { 7452 var icon = ""; 7453 var width = 100; 7454 var bg = ""; 7455 count++; 7456 v.nowPlayingImageURL = v.useImage ? v.useImage : v.nowPlayingImageURL; 7457 switch (v.type) { 7458 case "music": 7459 icon = "icon-music-tone-alt"; 7460 width = 7461 v.nowPlayingImageURL !== "plugins/images/homepage/no-np.png" 7462 ? 56 7463 : 100; 7464 bg = 7465 v.nowPlayingImageURL !== "plugins/images/homepage/no-np.png" 7466 ? ` 7467 <img class="imageSource imageSourceLeft" src="` + 7468 v.nowPlayingImageURL + 7469 `"> 7470 <img class="imageSource imageSourceRight" src="` + 7471 v.nowPlayingImageURL + 7472 `"> 7473 ` 7474 : ""; 7475 break; 7476 case "movie": 7477 icon = "icon-film"; 7478 break; 7479 case "tv": 7480 icon = "icon-screen-desktop"; 7481 break; 7482 case "video": 7483 icon = "icon-screen-film"; 7484 break; 7485 default: 7486 } 7487 var userThumb = v.userThumb 7488 ? '<img src="' + v.userThumb + '" class="nowPlayingUserThumb" alt="User">' 7489 : ""; 7490 if (v.sessionType == "Direct Playing") { 7491 var userStream = "Direct Play"; 7492 var userVideo = "Direct Play"; 7493 var userAudio = "Direct Play"; 7494 streamDetails["direct"] = streamDetails["direct"] + 1; 7495 } else { 7496 var userStream = v.userStream.stream; 7497 var userVideo = 7498 v.userStream.videoDecision + 7499 " (" + 7500 v.userStream.sourceVideoCodec + 7501 ' <i class="mdi mdi-ray-start-arrow"></i> ' + 7502 v.userStream.videoCodec + 7503 " " +
7504 v.userStream.videoResolution + 7505 ")"; 7506 var userAudio = 7507 v.userStream.audioDecision + 7508 " (" + 7509 v.userStream.sourceAudioCodec + 7510 ' <i class="mdi mdi-ray-start-arrow"></i> ' + 7511 v.userStream.audioCodec + 7512 ")"; 7513 streamDetails["transcode"] = streamDetails["transcode"] + 1; 7514 } 7515 var streamInfo = ""; 7516 streamInfo += 7517 `<div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-play-circle-outline"></i> Stream: ` + 7518 userStream + 7519 `</span></div>`; 7520 streamInfo += v.userStream.videoResolution 7521 ? `<div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-video"></i> Video: ` + 7522 userVideo + 7523 `</span></div>` 7524 : ""; 7525 streamInfo += 7526 `<div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-speaker"></i> Audio: ` + 7527 userAudio + 7528 `</span></div>`; 7529 v.session = v.session.replace(/[\W_]+/g, "-"); 7530 bandwidthDetails[v.bandwidthType] = 7531 bandwidthDetails[v.bandwidthType] + parseFloat(v.bandwidth); 7532 cards += 7533 ` 7534 <div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-xs-12 nowPlayingItem"> 7535 <div class="white-box"> 7536 <div class="el-card-item p-b-10"> 7537 <div class="el-card-avatar el-overlay-1 m-b-0">` + 7538 bg + 7539 `<img class="imageSource" style="width:` + 7540 width + 7541 `%;margin-left: auto;margin-right: auto;" src="` + 7542 v.nowPlayingImageURL + 7543 `"> 7544 <div class="el-overlay"> 7545 <ul class="el-info p-t-20 m-t-20"> 7546 <li><a class="btn b-none inline-popups" href="#` + 7547 v.session + 7548 `" data-effect="mfp-zoom-out"><i class="mdi mdi-server-network mdi-24px"></i></a></li> 7549 <li><a class="btn b-none metadata-get" data-source="` + 7550 source + 7551 `" data-key="` + 7552 v.metadataKey + 7553 `" data-uid="` + 7554 v.uid + 7555 `"><i class="mdi mdi-information mdi-24px"></i></a></li> 7556 <li><a class="btn b-none openTab" data-tab-name="` + 7557 v.tabName + 7558 `" data-type="` + 7559 v.type + 7560 `" data-open-tab="` + 7561 v.openTab + 7562 `" data-url="` + 7563 v.address + 7564 `" href="javascript:void(0);"><i class=" mdi mdi-` + 7565 sourceIcon + 7566 ` mdi-24px"></i></a></li> 7567 <li><a class="btn b-none refreshImage" data-type="nowPlaying" data-image="` + 7568 v.nowPlayingOriginalImage + 7569 `" href="javascript:void(0);"><i class="mdi mdi-refresh mdi-24px"></i></a></li> 7570 <a class="inline-popups ` + 7571 v.uid + 7572 ` hidden" href="#` + 7573 v.uid + 7574 `-metadata-div" data-effect="mfp-zoom-out"></a> 7575 </ul> 7576 </div> 7577 </div> 7578 <div class="el-card-content"> 7579 <div class="progress"> 7580 <div class="progress-bar progress-bar-info" style="width: ` + 7581 v.watched + 7582 `%;" role="progressbar"><span class="hidden">` + 7583 v.watched + 7584 `%</span></div> 7585 <div class="progress-bar progress-bar-inverse" style="width: ` + 7586 v.transcoded + 7587 `%;" role="progressbar"></div> 7588 </div> 7589 <h3 class="box-title pull-left p-l-10 elip" style="width:90%">` + 7590 v.nowPlayingTitle + 7591 `</h3> 7592 <h3 class="box-title pull-right vertical-middle" style="width:10%"><i class="icon-control-` + 7593 v.state + 7594 ` fa-fw text-info" style=""></i></h3> 7595 <div class="clearfix"></div> 7596 <small class="pull-left p-l-10 w-50 elip"><span class="pull-left"><i class="` + 7597 icon + 7598 ` fa-fw text-info"></i>` + 7599 v.nowPlayingBottom + 7600 `</span></small> 7601 <small class="pull-right p-r-10 w-50"><span class="pull-right"><span class="">` + 7602 v.user + 7603 ` <i class="icon-user"></i></span></span></small> 7604 <br> 7605 </div> 7606 </div> 7607 </div> 7608 </div> 7609 <div id="` + 7610 v.session + 7611 `" class="white-popup mfp-with-anim mfp-hide"> 7612 <div class="col-md-6 col-md-offset-3"> 7613 <div class="white-box m-b-0 bg-info"> 7614 <h3 class="text-white box-title m-b-0">` + 7615 v.sessionType + 7616 `<span class="pull-right"><i class="mdi mdi-network-upload"></i> ` + 7617 v.bandwidth + 7618 ` kbps <button type="button" class="btn bg-org btn-circle close-popup m-l-10"><i class="fa fa-times"></i> </button></span></h3>
7619 </div> 7620 <div class="white-box"> 7621 <div class="row"> 7622 <div class="p-l-20 p-r-20"> 7623 <div class="pull-left"> 7624 <span class="text-uppercase"><i class="mdi mdi-` + 7625 v.bandwidthType + 7626 `"></i> ` + 7627 v.bandwidthType + 7628 `</span> 7629 <span class="text-uppercase"><i class="mdi mdi-account-network"></i> ` + 7630 v.userAddress + 7631 `</span> 7632 ` + 7633 streamInfo + 7634 ` 7635 <div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-` + 7636 source + 7637 `"></i> Product: ` + 7638 v.userStream.product + 7639 `</span></div> 7640 <div class="text-muted m-t-20 text-uppercase"><span class="text-uppercase"><i class="mdi mdi-laptop-mac"></i> Device: ` + 7641 v.userStream.device + 7642 `</span></div> 7643 </div> 7644 <div data-label="` + 7645 v.watched + 7646 `%" class="css-bar css-bar-` + 7647 Math.ceil(v.watched / 5) * 5 + 7648 ` css-bar-lg m-b-0 css-bar-info pull-right">` + 7649 userThumb + 7650 `</div> 7651 </div> 7652 </div> 7653 </div> 7654 </div> 7655 </div> 7656 <div id="` + 7657 v.uid + 7658 `-metadata-div" class="white-popup mfp-with-anim mfp-hide"> 7659 <div class="col-md-8 col-md-offset-2 ` + 7660 v.uid + 7661 `-metadata-info"></div>
7662 </div> 7663 `; 7664 }); 7665 cards += "</div><!--end-->"; 7666 cards += buildStreamTooltip(bandwidthDetails, streamDetails, source); 7667 return cards; 7668} 7669function buildStreamTooltip(bandwidth, streams, type) { 7670 var html = ""; 7671 var streamText = "Streams: "; 7672 var bandwidthText = " | Bandwidth: "; 7673 var bandwidthTotal = 7674 parseFloat(bandwidth["wan"]) + parseFloat(bandwidth["lan"]); 7675 if (type !== "plex") { 7676 bandwidthText += (parseFloat(bandwidth["wan"]) / 1000).toFixed(1) + " Mbps"; 7677 } else { 7678 bandwidthText += (parseFloat(bandwidthTotal) / 1000).toFixed(1) + " Mbps"; 7679 if (bandwidth["wan"] !== 0) { 7680 bandwidthText += 7681 " | WAN: " + (parseFloat(bandwidth["wan"]) / 1000).toFixed(1) + " Mbps"; 7682 } 7683 if (bandwidth["lan"] !== 0) { 7684 bandwidthText += 7685 " | LAN: " + (parseFloat(bandwidth["lan"]) / 1000).toFixed(1) + " Mbps"; 7686 } 7687 } 7688 var spacer = ""; 7689 if (streams["direct"] !== 0) { 7690 streamText += streams["direct"] + " Direct Play(s)"; 7691 spacer = " & "; 7692 } 7693 if (streams["transcode"] !== 0) { 7694 streamText += spacer + streams["transcode"] + " Transcode(s)"; 7695 } 7696 html += 7697 '<span class="label label-info m-l-20 mouse" title="" data-toggle="tooltip" data-original-title="' + 7698 streamText + 7699 bandwidthText + 7700 '" data-placement="bottom"><i class="fa fa-info"></i></span>'; 7701 return ( 7702 ` 7703 <script>$('.streamDetails-` + 7704 type + 7705 `').html('` + 7706 html + 7707 `');$('[data-toggle="tooltip"]').tooltip();</script> 7708 ` 7709 ); 7710} 7711function buildRecentItem(array, type, extra = null) { 7712 var items = ""; 7713 $.each(array, function (i, v) { 7714 if (extra == null) { 7715 var className = ""; 7716 var extraImg = ""; 7717 switch (v.type) { 7718 case "music": 7719 className = "recent-cover recent-item recent-music"; 7720 extraImg = 7721 '<img src="' + 7722 v.imageURL + 7723 '" class="imageSourceAlt imageSourceTop recent-cover"><img src="' + 7724 v.imageURL + 7725 '" class="imageSourceAlt imageSourceBottom recent-cover">'; 7726 break; 7727 case "movie": 7728 className = "recent-poster recent-item recent-movie"; 7729 break; 7730 case "tv": 7731 className = "recent-poster recent-item recent-tv"; 7732 break; 7733 case "video": 7734 className = "recent-poster recent-item recent-video"; 7735 break; 7736 default: 7737 } 7738 items += 7739 ` 7740 <div class="item lazyload ` + 7741 className + 7742 ` metadata-get mouse imageSource" data-source="` + 7743 type + 7744 `" data-key="` + 7745 v.metadataKey + 7746 `" data-uid="` + 7747 v.uid + 7748 `" data-src="` + 7749 v.imageURL + 7750 `"> 7751 ` + 7752 extraImg + 7753 ` 7754 <div class="hover-homepage-item"> 7755 <span class="elip request-title-movie"> 7756 <a class="text-white refreshImage" data-type="recent-item" data-image="` + 7757 v.originalImage + 7758 `" href="javascript:void(0);"><i class="mdi mdi-refresh mdi-24px"></i></a> 7759 </span> 7760 </div> 7761 <span class="elip recent-title">` + 7762 v.title + 7763 `<br/>` + 7764 v.secondaryTitle + 7765 `</span> 7766 <div id="` + 7767 v.uid + 7768 `-metadata-div" class="white-popup mfp-with-anim mfp-hide"> 7769 <div class="col-md-8 col-md-offset-2 ` + 7770 v.uid + 7771 `-metadata-info"></div> 7772 </div> 7773 </div> 7774 `; 7775 } else { 7776 items += 7777 ` 7778 <a class="inline-popups ` + 7779 v.uid + 7780 ` hidden" href="#` + 7781 v.uid + 7782 `-metadata-div" data-effect="mfp-zoom-out"></a> 7783 `; 7784 } 7785 }); 7786 return items; 7787} 7788function buildPlaylistItem(array, type, extra = null) { 7789 var items = ""; 7790 $.each(array, function (i, v) { 7791 if (i !== "title") { 7792 if (extra == null) { 7793 items += 7794 ` 7795 <div class="item lazyload recent-poster metadata-get mouse imageSource" data-source="` + 7796 type + 7797 `" data-key="` + 7798 v.metadataKey + 7799 `" data-uid="` + 7800 v.uid + 7801 `" data-src="` + 7802 v.imageURL + 7803 `"> 7804 <div class="hover-homepage-item">
7805 <span class="elip request-title-movie"> 7806 <a class="text-white refreshImage" data-type="recent-item" data-image="` + 7807 v.originalImage + 7808 `" href="javascript:void(0);"><i class="mdi mdi-refresh mdi-24px"></i></a> 7809 </span> 7810 </div> 7811 <span class="elip recent-title">` + 7812 v.title + 7813 `</span> 7814 <div id="` + 7815 v.uid + 7816 `-metadata-div" class="white-popup mfp-with-anim mfp-hide"> 7817 <div class="col-md-8 col-md-offset-2 ` + 7818 v.uid + 7819 `-metadata-info"></div> 7820 </div> 7821 </div> 7822 `; 7823 } else { 7824 items += 7825 ` 7826 <a class="inline-popups ` + 7827 v.uid + 7828 ` hidden" href="#` + 7829 v.uid + 7830 `-metadata-div" data-effect="mfp-zoom-out"></a> 7831 `; 7832 } 7833 } 7834 }); 7835 return items; 7836} 7837function buildRequestAdminMenuItem(value, category, id, type) { 7838 var action = ""; 7839 var text = ""; 7840 var extra = ""; 7841 switch (category) { 7842 case "approved": 7843 if (value) { 7844 //nada 7845 } else { 7846 action = "approve"; 7847 text = "Approve"; 7848 extra = 7849 `<li><a class="mouse" onclick="requestActions('` + 7850 id + 7851 `', 'deny', '` + 7852 type + 7853 `');" lang="en">Deny</a></li>`; 7854 } 7855 break; 7856 case "available": 7857 if (value) { 7858 action = "unavailable"; 7859 text = "Mark as Unavailable"; 7860 } else { 7861 action = "available"; 7862 text = "Mark as Available"; 7863 } 7864 break; 7865 default: 7866 } 7867 return action 7868 ? `<li><a class="mouse" onclick="requestActions('` + 7869 id + 7870 `', '` + 7871 action + 7872 `', '` + 7873 type + 7874 `');" lang="en">` + 7875 text + 7876 `</a></li>` + 7877 extra 7878 : ""; 7879} 7880function buildRequestItem(array, extra = null) { 7881 var items = ""; 7882 let service = activeInfo.settings.homepage.requests.service; 7883 $.each(array, function (i, v) { 7884 if (extra == null) { 7885 var approveID = 7886 v.type == "tv" && service === "ombi" ? v.id : v.request_id; 7887 var iconType = v.type == "tv" ? "fa-tv " : "fa-film"; 7888 var badge = ""; 7889 var badge2 = ""; 7890 var bg = v.background.includes(".") 7891 ? v.background 7892 : "plugins/images/homepage/no-np.png"; 7893 v.user = 7894 (activeInfo.settings.homepage.ombi.alias && service === "ombi") || 7895 (activeInfo.settings.homepage.overseerr.enabled && 7896 service === "overseerr") 7897 ? v.userAlias 7898 : v.user; 7899 //Set Status 7900 var status = v.approved 7901 ? '<span class="badge bg-org m-r-10" lang="en">Approved</span>' 7902 : '<span class="badge bg-danger m-r-10" lang="en">Unapproved</span>'; 7903 status += v.available 7904 ? '<span class="badge bg-org m-r-10" lang="en">Available</span>' 7905 : '<span class="badge bg-danger m-r-10" lang="en">Unavailable</span>'; 7906 status += v.denied 7907 ? '<span class="badge bg-danger m-r-10" lang="en">Denied</span>' 7908 : ""; 7909 //Set Class 7910 var className = v.approved ? "request-approved" : "request-unapproved"; 7911 className += v.available ? " request-available" : " request-unavailable"; 7912 className += v.denied ? " request-denied" : " request-notdenied"; 7913 //Set badge 7914 badge = v.approved ? "bg-info" : "bg-warning"; 7915 badge = v.denied ? "bg-danger" : badge; 7916 badge2 = v.available ? "bg-success" : "bg-danger"; 7917 //Is Admin? 7918 var adminFunctions = 7919 `<div class="btn-group m-r-10"> 7920 <button aria-expanded="false" data-toggle="dropdown" class="btn btn-info btn-outline dropdown-toggle waves-effect waves-light" type="button"> <i class="fa fa-ellipsis-v m-r-5"></i> <span class="caret"></span></button> 7921 <ul role="menu" class="dropdown-menu"> 7922 <li><h5 class="text-center" lang="en">Request Options</h5></li> 7923 <li class="divider"></li> 7924 ` + 7925 buildRequestAdminMenuItem(v.approved, "approved", approveID, v.type) + 7926 ` 7927 ` + 7928 buildRequestAdminMenuItem(v.available, "available", approveID, v.type) + 7929 ` 7930 <li><a class="mouse" onclick="requestActions('` + 7931 v.request_id + 7932 `', 'delete', '` + 7933 v.type + 7934 `');" lang="en">Delete</a></li> 7935 </ul> 7936 </div>`; 7937 adminFunctions = activeInfo.user.groupID <= 1 ? adminFunctions : ""; 7938 var user = 7939 activeInfo.user.groupID <= 1 7940 ? '<span lang="en">Requested By:</span> ' + v.user 7941 : ""; 7942 var user2 = activeInfo.user.groupID <= 1 ? "<br>" + v.user : ""; 7943 var divId = v.type == "movie" ? v.request_id : v.id; 7944 items += 7945 ` 7946 <div class="item lazyload recent-poster request-item request-` + 7947 v.type + 7948 ` ` + 7949 className + 7950 ` request-` + 7951 divId + 7952 `-div mouse" data-target="request-` + 7953 v.id + 7954 `" data-src="` + 7955 v.poster + 7956 `"> 7957 <div class="outside-request-div"> 7958 <div class="inside-over-request-div ` + 7959 badge2 + 7960 `"></div> 7961 <div class="inside-request-div ` + 7962 badge + 7963 `"></div> 7964 </div> 7965 <div class="hover-homepage-item"></div> 7966 <span class="elip request-title-` + 7967 v.type + 7968 `"><i class="fa ` + 7969 iconType + 7970 `"></i></span> 7971 <span class="elip recent-title">` + 7972 v.title + 7973 user2 + 7974 `</span> 7975 <div id="request-` + 7976 v.id + 7977 `" class="white-popup mfp-with-anim mfp-hide"> 7978 <div class="col-md-8 col-md-offset-2"> 7979 <div class="white-box m-b-0"> 7980 <div class="user-bg lazyload" data-src="` + 7981 bg + 7982 `"> 7983 <div class="col-xs-2 p-10">` + 7984 adminFunctions + 7985 `</div> 7986 <div class="col-xs-10"> 7987 <h2 class="m-b-0 font-medium pull-right text-right"> 7988 ` + 7989 v.title + 7990 `<button type="button" class="btn bg-org btn-circle close-popup m-l-10"><i class="fa fa-times"></i> </button><br> 7991 <small class="m-t-0 text-white">` + 7992 user + 7993 `</small><br> 7994 ` + 7995 buildYoutubeLink(v.title + " " + v.type) + 7996 ` 7997 </h2> 7998 </div> 7999 <div class="genre-list p-10">` + 8000 status + 8001 `</div> 8002 </div> 8003 </div> 8004 <div class="panel panel-info p-b-0 p-t-0"> 8005 <div class="panel-body p-b-0 p-t-0 m-b-0"> 8006 <div class="p-20 text-center"> 8007 <p class="">` + 8008 v.overview + 8009 `</p> 8010 </div> 8011 <div class="row"> 8012 <div class="col-lg-12"> 8013 <div class="owl-carousel owl-theme metadata-actors p-b-10"></div> 8014 </div> 8015 </div> 8016 </div> 8017 </div> 8018 </div> 8019 </div>
8020 </div> 8021 `; 8022 } else { 8023 items += 8024 ` 8025 <a class="inline-popups hidden" id="link-request-` + 8026 v.id + 8027 `" href="#request-` + 8028 v.id + 8029 `" data-effect="mfp-zoom-out" ></a> 8030 `; 8031 } 8032 }); 8033 return items !== "" || extra == null 8034 ? items 8035 : '<h2 class="text-center">No items</h2>'; 8036} 8037function buildStream(array, type) { 8038 var streams = 8039 typeof array.content !== "undefined" ? array.content.length : false; 8040 var originalType = type; 8041 //type = (type === 'emby' && activeInfo.settings.homepage.media.jellyfin) ? 'jellyfin' : type; 8042 return streams 8043 ? ` 8044 <div id="` + 8045 type + 8046 `Streams"> 8047 <div class="el-element-overlay row"> 8048 <div class="col-md-12"> 8049 <h4 class="pull-left homepage-element-title"><span lang="en">Active</span> ` + 8050 toUpper(type) + 8051 ` <span lang="en">Streams</span> : </h4><h4 class="pull-left"> <span class="label label-info m-l-20 checkbox-circle mouse" onclick="homepageStream('` + 8052 originalType + 8053 `')">` + 8054 streams + 8055 `</span><span class="streamDetails-` + 8056 type + 8057 `"></span></h4> 8058 <hr class="hidden-xs"> 8059 </div> 8060 <div class="clearfix"></div> 8061 <!-- .cards --> 8062 ` + 8063 buildStreamItem(array.content, type) + 8064 ` 8065 <!-- /.cards--> 8066 </div> 8067 </div> 8068 <div class="clearfix"></div> 8069 ` 8070 : ""; 8071} 8072function buildRecent(array, type) { 8073 var recent = typeof array.content !== "undefined" ? true : false; 8074 array.content = recent ? Object.values(array.content) : false; 8075 var movie = recent 8076 ? array.content.filter((p) => p.type == "movie").length > 0 8077 ? true 8078 : false 8079 : false; 8080 var tv = recent 8081 ? array.content.filter((p) => p.type == "tv").length > 0 8082 ? true 8083 : false 8084 : false; 8085 var video = recent 8086 ? array.content.filter((p) => p.type == "video").length > 0 8087 ? true 8088 : false 8089 : false; 8090 var music = recent 8091 ? array.content.filter((p) => p.type == "music").length > 0 8092 ? true 8093 : false 8094 : false; 8095 var dropdown = ""; 8096 var header = ""; 8097 var headerAlt = ""; 8098 var refreshType = type; 8099 //type = (type === 'emby' && activeInfo.settings.homepage.media.jellyfin) ? 'jellyfin' : type; 8100 dropdown += 8101 recent && movie 8102 ? `<li><a data-filter="recent-movie" server-filter="` + 8103 type + 8104 `" href="javascript:void(0);">Movies</a></li>` 8105 : ""; 8106 dropdown += 8107 recent && tv 8108 ? `<li><a data-filter="recent-tv" server-filter="` + 8109 type + 8110 `" href="javascript:void(0);">Shows</a></li>` 8111 : ""; 8112 dropdown += 8113 recent && video 8114 ? `<li><a data-filter="recent-video" server-filter="` + 8115 type + 8116 `" href="javascript:void(0);">Videos</a></li>` 8117 : ""; 8118 dropdown += 8119 recent && music 8120 ? `<li><a data-filter="recent-music" server-filter="` + 8121 type + 8122 `" href="javascript:void(0);">Music</a></li>` 8123 : ""; 8124 var dropdownMenu = 8125 ` 8126 <div class="btn-group pull-right"> 8127 <button type="button" class="btn btn-info waves-effect hidden-xs" onclick="owlChange('` + 8128 type + 8129 `-recent','previous');"><i class="fa fa-chevron-left"></i></button> 8130 <button type="button" class="btn btn-info waves-effect hidden-xs" onclick="owlChange('` + 8131 type + 8132 `-recent','next');"><i class="fa fa-chevron-right"></i></button> 8133 <button aria-expanded="false" data-toggle="dropdown" class="btn btn-info dropdown-toggle waves-effect waves-light" type="button"> 8134 <i class="fa fa-filter m-r-5"></i><span class="caret"></span> 8135 </button> 8136 <ul role="menu" class="dropdown-menu recent-filter"> 8137 <li><a data-filter="all" server-filter="` + 8138 type + 8139 `" href="javascript:void(0);">All</a></li> 8140 <li class="divider"></li> 8141 ` + 8142 dropdown + 8143 ` 8144 </ul> 8145 </div>`; 8146 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 8147 var headerAlt = 8148 ` 8149 <div class="col-md-12"> 8150 <h4 class="pull-left homepage-element-title"><span class="mouse" onclick="homepageRecent('` + 8151 type + 8152 `')" lang="en">Recently Added</span> : </h4><h4 class="pull-left"> </h4> 8153 ` + 8154 dropdownMenu + 8155 ` 8156 <hr class="hidden-xs"><div class="clearfix"></div> 8157 </div> 8158 <div class="clearfix"></div> 8159 `; 8160 } else { 8161 var header = 8162 ` 8163 <div class="panel-heading bg-info p-t-10 p-b-10"> 8164 <span onclick="homepageRecent('` + 8165 type + 8166 `')" class="pull-left m-t-5 mouse"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/` + 8167 type + 8168 `.png"> <span lang="en">Recently Added</span></span> 8169 ` + 8170 dropdownMenu + 8171 ` 8172 <div class="clearfix"></div> 8173 </div> 8174 `; 8175 } 8176 return recent 8177 ? ` 8178 <div id="` + 8179 type + 8180 `Recent" class="row"> 8181 ` + 8182 headerAlt + 8183 ` 8184 <div class="col-lg-12"> 8185 <div class="panel panel-default"> 8186 ` + 8187 header + 8188 ` 8189 <div class="panel-wrapper p-b-0 collapse in"> 8190 <div class="` + 8191 type + 8192 `-recent-hidden hidden"></div> 8193 <div class="owl-carousel owl-theme recent-items ` + 8194 type + 8195 `-recent"> 8196 ` + 8197 buildRecentItem(array.content, type) + 8198 ` 8199 </div> 8200 ` + 8201 buildRecentItem(array.content, type, true) + 8202 ` 8203 </div> 8204 </div> 8205 </div> 8206 </div> 8207 ` 8208 : ""; 8209} 8210function owlChange(elm, action) { 8211 switch (action) { 8212 case "next": 8213 $("." + elm).trigger("next.owl"); 8214 break; 8215 case "previous": 8216 $("." + elm).trigger("prev.owl"); 8217 break; 8218 default: 8219 return false;
8220 } 8221 return false; 8222} 8223function cleanPlaylistTitle(string) { 8224 var test = string.split("."); 8225 if (test.length > 1) { 8226 if (!isNaN(test[0])) { 8227 return test[1]; 8228 } 8229 } 8230 return string; 8231} 8232function buildPlaylist(array, type) { 8233 var playlist = 8234 typeof array.content !== "undefined" 8235 ? Object.keys(array.content).length 8236 : false; 8237 var dropdown = ""; 8238 var first = ""; 8239 var firstButton = ""; 8240 var hidden = ""; 8241 var count = 0; 8242 var items = ""; 8243 var header = ""; 8244 var headerAlt = ""; 8245 if (playlist) { 8246 $.each(array.content, function (i, v) { 8247 v.title = cleanPlaylistTitle(v.title); 8248 count++; 8249 first = count == 1 ? v.title : first; 8250 firstButton = count == 1 ? i + "-playlist" : firstButton; 8251 hidden = count == 1 ? "" : " owl-hidden hidden"; 8252 dropdown += 8253 `<li><a data-filter="` + 8254 i + 8255 `" server-filter="` + 8256 type + 8257 `" data-title="` + 8258 encodeURI(v.title) + 8259 `" href="javascript:void(0);">` + 8260 v.title + 8261 `</a></li>`; 8262 8263 items += 8264 ` 8265 <div class="owl-carousel owl-theme playlist-items ` + 8266 type + 8267 `-playlist ` + 8268 hidden + 8269 ` ` + 8270 i + 8271 `-playlist"> 8272 ` + 8273 buildPlaylistItem(v, type) + 8274 ` 8275 </div> 8276 ` + 8277 buildPlaylistItem(v, type, true) + 8278 ` 8279 `; 8280 }); 8281 var builtDropdown = 8282 ` 8283 <button type="button" class="btn btn-info waves-effect hidden-xs playlist-previous" onclick="owlChange('` + 8284 firstButton + 8285 `','previous');"><i class="fa fa-chevron-left"></i></button> 8286 <button type="button" class="btn btn-info waves-effect hidden-xs playlist-next" onclick="owlChange('` + 8287 firstButton + 8288 `','next');"><i class="fa fa-chevron-right"></i></button> 8289 <button aria-expanded="false" data-toggle="dropdown" class="btn btn-info dropdown-toggle waves-effect waves-light" type="button"> 8290 <i class="mdi mdi-playlist-play m-r-5 fa-lg"></i><span class="caret"></span> 8291 </button> 8292 <ul role="menu" class="dropdown-menu playlist-filter"> 8293 ` + 8294 dropdown + 8295 ` 8296 </ul> 8297 `; 8298 } 8299 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 8300 var headerAlt = 8301 ` 8302 <div class="col-md-12"> 8303 <h4 class="pull-left homepage-element-title"><span onclick="homepagePlaylist('` + 8304 type + 8305 `')" class="` + 8306 type + 8307 `-playlistTitle mouse">` + 8308 first + 8309 `</span> : </h4><h4 class="pull-left"> </h4> 8310 <div class="btn-group pull-right"> 8311 ` + 8312 builtDropdown + 8313 ` 8314 </div> 8315 <hr class="hidden-xs"><div class="clearfix"></div> 8316 </div> 8317 <div class="clearfix"></div> 8318 `; 8319 } else { 8320 var header = 8321 ` 8322 <div class="panel-heading bg-info p-t-10 p-b-10"> 8323 <span class="pull-left m-t-5 mouse homepage-element-title" onclick="homepagePlaylist('` + 8324 type + 8325 `')"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/` + 8326 type + 8327 `.png"> <span class="` + 8328 type + 8329 `-playlistTitle">` + 8330 first + 8331 `</span></span> 8332 <div class="btn-group pull-right"> 8333 ` + 8334 builtDropdown + 8335 ` 8336 </div> 8337 <div class="clearfix"></div> 8338 </div> 8339 `; 8340 } 8341 return playlist 8342 ? ` 8343 <div id="` + 8344 type + 8345 `Playlist" class="row"> 8346 ` + 8347 headerAlt + 8348 ` 8349 <div class="col-lg-12"> 8350 <div class="panel panel-default"> 8351 ` + 8352 header + 8353 ` 8354 <div class="panel-wrapper p-b-0 collapse in"> 8355 ` + 8356 items + 8357 ` 8358 </div> 8359 </div> 8360 </div> 8361 </div> 8362 ` 8363 : ""; 8364} 8365function buildRequest(service, div, array) { 8366 var requests = typeof array.content !== "undefined"; 8367 var dropdown = ""; 8368 var headerAlt = ""; 8369 var header = ""; 8370 var requestButton = 8371 activeInfo["settings"]["homepage"][service]["enabled"] === true 8372 ? `<button href="#new-request" id="newRequestButton" class="btn btn-info waves-effect waves-light inline-popups" data-effect="mfp-zoom-out"><i class="fa fa-search m-l-5"></i></button>` 8373 : ""; 8374 if (requests) { 8375 var builtDropdown = 8376 ` 8377 <button type="button" class="btn btn-info waves-effect hidden-xs" onclick="owlChange('request-items-${service}','previous');"><i class="fa fa-chevron-left"></i></button> 8378 <button type="button" class="btn btn-info waves-effect hidden-xs" onclick="owlChange('request-items-${service}','next');"><i class="fa fa-chevron-right"></i></button> 8379 <button aria-expanded="false" data-toggle="dropdown" class="btn btn-info dropdown-toggle waves-effect waves-light" type="button"> 8380 <i class="fa fa-filter m-r-5"></i><span class="caret"></span> 8381 </button> 8382 ` + 8383 requestButton + 8384 ` 8385 <div role="menu" class="dropdown-menu request-filter"> 8386 <div class="checkbox checkbox-success m-l-20 checkbox-circle"> 8387 <input id="request-filter-available-${service}" data-filter="request-available" class="filter-request-input" type="checkbox" checked=""> 8388 <label for="request-filter-available-${service}"> <span lang="en">Available</span> </label> 8389 </div> 8390 <div class="checkbox checkbox-danger m-l-20 checkbox-circle"> 8391 <input id="request-filter-unavailable-${service}" data-filter="request-unavailable" class="filter-request-input" type="checkbox" checked=""> 8392 <label for="request-filter-unavailable-${service}"> <span lang="en">Unavailable</span> </label> 8393 </div> 8394 <div class="checkbox checkbox-info m-l-20 checkbox-circle"> 8395 <input id="request-filter-approved-${service}" data-filter="request-approved" class="filter-request-input" type="checkbox" checked=""> 8396 <label for="request-filter-approved-${service}"> <span lang="en">Approved</span> </label> 8397 </div> 8398 <div class="checkbox checkbox-warning m-l-20 checkbox-circle"> 8399 <input id="request-filter-unapproved-${service}" data-filter="request-unapproved" class="filter-request-input" type="checkbox" checked=""> 8400 <label for="request-filter-unapproved-${service}"> <span lang="en">Unapproved</span> </label> 8401 </div> 8402 <div class="checkbox checkbox-purple m-l-20 checkbox-circle"> 8403 <input id="request-filter-denied-${service}" data-filter="request-denied" class="filter-request-input" type="checkbox" checked=""> 8404 <label for="request-filter-denied-${service}"> <span lang="en">Denied</span> </label> 8405 </div> 8406 <div class="checkbox checkbox-inverse m-l-20 checkbox-circle"> 8407 <input id="request-filter-movie-${service}" data-filter="request-movie" class="filter-request-input" type="checkbox" checked=""> 8408 <label for="request-filter-movie-${service}"> <span lang="en">Movie</span> </label> 8409 </div> 8410 <div class="checkbox checkbox-inverse m-l-20 checkbox-circle"> 8411 <input id="request-filter-tv-${service}" data-filter="request-tv" class="filter-request-input" type="checkbox" checked=""> 8412 <label for="request-filter-tv-${service}"> <span lang="en">TV</span> </label> 8413 </div> 8414 </div> 8415 8416 `; 8417 } 8418 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 8419 var headerAlt = 8420 ` 8421 <div class="col-md-12"> 8422 <h4 class="pull-left homepage-element-title"><span class="mouse" onclick="homepageRequests('${service}')" lang="en">Requests</span> : </h4><h4 class="pull-left"> </h4> 8423 <div class="btn-group pull-right"> 8424 ` + 8425 builtDropdown + 8426 ` 8427 </div> 8428 <hr class="hidden-xs"><div class="clearfix"></div> 8429 </div> 8430 <div class="clearfix"></div> 8431 `; 8432 } else { 8433 var header = 8434 ` 8435 <div class="panel-heading bg-info p-t-10 p-b-10"> 8436 <span class="pull-left m-t-5 mouse homepage-element-title" onclick="homepageRequests('${service}')"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/` + 8437 service + 8438 `.png"> <span lang="en">Requests</span></span> 8439 <div class="btn-group pull-right"> 8440 ` + 8441 builtDropdown + 8442 ` 8443 </div> 8444 <div class="clearfix"></div> 8445 </div> 8446 `; 8447 } 8448 return requests 8449 ? ` 8450 <div id="${service}-requests" class="row"> 8451 ` + 8452 headerAlt + 8453 ` 8454 <div class="col-lg-12"> 8455 <div class="panel panel-default"> 8456 ` + 8457 header + 8458 ` 8459 <div class="panel-wrapper p-b-0 collapse in"> 8460 <div class="owl-carousel owl-theme request-items-` + 8461 service + 8462 `"> 8463 ` + 8464 buildRequestItem(array.content) + 8465 ` 8466 </div> 8467 ` + 8468 buildRequestItem(array.content, true) + 8469 ` 8470 </div> 8471 </div> 8472 </div> 8473 </div>
8474 <div id="new-request" class="white-popup mfp-with-anim mfp-hide"> 8475 <div class="col-md-8 col-md-offset-2"> 8476 <div class="white-box m-b-0 search-div resultBox-outside"> 8477 <div class="form-group m-b-0"> 8478 <div id="request-input-div" class="input-group"> 8479 <input id="request-input" lang="en" placeholder="Request a Show or Movie" type="text" class="form-control inline-focus"> 8480 <input id="request-page" type="hidden" class="form-control"> 8481 <div class="input-group-btn"> 8482 <button type="button" class="btn waves-effect waves-light btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span lang="en">Suggestions</span> <span class="caret"></span></button> 8483 <ul class="dropdown-menu dropdown-menu-right"> 8484 <li><a onclick="requestList('org-mod', 'movie');" href="javascript:void(0)" lang="en">Organizr Mod Picks</a></li> 8485 <li><a onclick="requestList('theatre-movie', 'movie');" href="javascript:void(0)" lang="en">In Theatres</a></li> 8486 <li><a onclick="requestList('top-movie', 'movie');" href="javascript:void(0)" lang="en">Top Movies</a></li> 8487 <li><a onclick="requestList('pop-movie', 'movie');" href="javascript:void(0)" lang="en">Popular Movies</a></li> 8488 <li><a onclick="requestList('up-movie', 'movie');" href="javascript:void(0)" lang="en">Upcoming Movies</a></li> 8489 <li><a onclick="requestList('top-tv', 'tv');" href="javascript:void(0)" lang="en">Top TV</a></li> 8490 <li><a onclick="requestList('pop-tv', 'tv');" href="javascript:void(0)" lang="en">Popular TV</a></li> 8491 <li><a onclick="requestList('today-tv', 'tv');" href="javascript:void(0)" lang="en">Airs Today TV</a></li> 8492 </ul> 8493 </div> 8494 </div> 8495 <div class="clearfix"></div> 8496 </div> 8497 <div id="request-results" class="row el-element-overlay resultBox-inside"></div> 8498 </div> 8499 </div> 8500 </div> 8501 ` 8502 : ""; 8503} 8504function pagination(c, m) { 8505 var current = c, 8506 last = m, 8507 delta = 2, 8508 left = current - delta, 8509 right = current + delta + 1, 8510 range = [], 8511 rangeWithDots = [], 8512 l; 8513 8514 for (let i = 1; i <= last; i++) { 8515 if (i == 1 || i == last || (i >= left && i < right)) { 8516 range.push(i); 8517 } 8518 } 8519 8520 for (let i of range) { 8521 if (l) { 8522 if (i - l === 2) { 8523 rangeWithDots.push(l + 1); 8524 } else if (i - l !== 1) { 8525 rangeWithDots.push("..."); 8526 } 8527 } 8528 rangeWithDots.push(i); 8529 l = i; 8530 } 8531 8532 return rangeWithDots; 8533} 8534function buildRequestResult( 8535 array, 8536 media_type = null, 8537 list = null, 8538 page = null, 8539 search = false 8540) { 8541 var comments = typeof array.comments !== "undefined" ? true : false; 8542 var comment = ""; 8543 var results = ``; 8544 var buttons = ``; 8545 var next = ``; 8546 var tv = 0; 8547 var movie = 0; 8548 var total = 0; 8549 var totalPages = array.total_pages; 8550 var currentPage = page * 1; 8551 var pagePrevious = page * 1 - 1; 8552 var pageNext = page * 1 + 1; 8553 var pageFirst = 1; 8554 var pageLast = totalPages; 8555 var previousHidden = currentPage == 1 ? "disabled" : ""; 8556 var nextHidden = currentPage == totalPages ? "disabled" : ""; 8557 var pageList = ""; 8558 let previousEnabled = pagePrevious !== 0; 8559 let nextEnabled = pageNext <= totalPages; 8560 if (array.results.length == 0) { 8561 return '<h2 class="text-center" lang="en">No Results</h2>'; 8562 } 8563 $.each(array.results, function (i, v) { 8564 media_type = v.media_type ? v.media_type : media_type; 8565 if (media_type == "tv" || media_type == "movie") { 8566 total = total + 1; 8567 tv = media_type == "tv" ? tv + 1 : tv; 8568 movie = media_type == "movie" ? movie + 1 : movie; 8569 var bg = 8570 v.poster_path !== null 8571 ? `https://image.tmdb.org/t/p/w300/` + v.poster_path 8572 : "plugins/images/homepage/no-list.png"; 8573 var top = v.title 8574 ? v.title 8575 : v.original_title 8576 ? v.original_title 8577 : v.original_name 8578 ? v.original_name 8579 : ""; 8580 var bottom = v.release_date 8581 ? v.release_date 8582 : v.first_air_date 8583 ? v.first_air_date 8584 : ""; 8585 if (comments) { 8586 if (array.comments[media_type + ":" + v.id] !== null) { 8587 comment = array.comments[media_type + ":" + v.id]; 8588 } 8589 } 8590 results += 8591 ` 8592 <div class="col-lg-3 col-md-4 col-sm-6 col-xs-12 m-t-20 request-result-item request-result-` + 8593 media_type + 8594 `"> 8595 <div class="white-box m-b-10"> 8596 <div class="el-card-item p-b-0"> 8597 <div class="el-card-avatar el-overlay-1 m-b-5 preloader-` + 8598 v.id + 8599 `"> <img class="lazyload resultImages" data-src="` + 8600 bg + 8601 `"> 8602 <div class="el-overlay"> 8603 <span class="text-info p-a-5 font-normal">` + 8604 comment + 8605 `</span> 8606 <ul class="el-info"> 8607 <li><a class="btn default btn-outline" href="javascript:void(0);" onclick="processRequest('` + 8608 v.id + 8609 `','` + 8610 media_type + 8611 `');"><i class="icon-link"></i> <span lang="en">Request</span></a></li> 8612 <li><a class="btn default btn-outline" href="https://www.themoviedb.org/` + 8613 media_type + 8614 `/` + 8615 v.id + 8616 `" target="_blank"><i class="icon-info"></i></a></li> 8617 </ul> 8618 </div> 8619 </div> 8620 <div class="el-card-content bg-org"> 8621 <h3 class="box-title elip">` + 8622 top + 8623 `</h3> <small>` + 8624 bottom + 8625 `</small> 8626 <br> 8627 </div> 8628 </div> 8629 </div> 8630 </div> 8631 `; 8632 } 8633 comment = ""; 8634 }); 8635 if (list && page && search == false) { 8636 $.each(pagination(currentPage, totalPages), function (key, value) { 8637 var activePage = currentPage == value ? "active" : ""; 8638 var disabled = value == "..." ? "disabled" : ""; 8639 var pageLink = 8640 value == "..." 8641 ? "" 8642 : `onclick="requestList('` + 8643 list + 8644 `', '` + 8645 media_type + 8646 `', '` + 8647 value + 8648 `');"`; 8649 pageList += 8650 '<li class="' +
8651 activePage + 8652 disabled + 8653 '"> <a ' + 8654 pageLink + 8655 ' href="javascript:void(0)">' + 8656 value + 8657 "</a> </li>"; 8658 }); 8659 let previousOnclick = previousEnabled 8660 ? `onclick="requestList('${list}', '${media_type}', '${pagePrevious}')";` 8661 : ``; 8662 let nextOnclick = nextEnabled 8663 ? `onclick="requestList('${list}', '${media_type}', '${pageNext}')";` 8664 : ``; 8665 next = 8666 ` 8667 <div class="clearfix"></div> 8668 <div class="button-box text-center p-b-0"> 8669 <ul class="pagination m-b-0"> 8670 <li class="` + 8671 previousHidden + 8672 `"> <a href="javascript:void(0)" ${previousOnclick}><i class="fa fa-angle-left"></i></a> </li> 8673 ` + 8674 pageList + 8675 ` 8676 <li class="` + 8677 nextHidden + 8678 `"> <a href="javascript:void(0)" ${nextOnclick}><i class="fa fa-angle-right"></i></a> </li> 8679 </ul> 8680 </div> 8681 `; 8682 } 8683 if (list && page && search == true) { 8684 $.each(pagination(currentPage, totalPages), function (key, value) { 8685 var activePage = currentPage == value ? "active" : ""; 8686 var disabled = value == "..." ? "disabled" : ""; 8687 var pageLink = 8688 value == "..." 8689 ? "" 8690 : `onclick="$('#request-page').val(` + value + `);doneTyping();"`; 8691 pageList += 8692 '<li class="' + 8693 activePage + 8694 disabled + 8695 '"> <a ' + 8696 pageLink + 8697 ' href="javascript:void(0)">' + 8698 value + 8699 "</a> </li>"; 8700 }); 8701 next = 8702 ` 8703 <div class="clearfix"></div> 8704 <div class="button-box text-center p-b-0"> 8705 <ul class="pagination m-b-0"> 8706 <li class="` + 8707 previousHidden + 8708 `"> <a href="javascript:void(0)" onclick="$('#request-page').val(` + 8709 pagePrevious + 8710 `);doneTyping();"><i class="fa fa-angle-left"></i></a> </li> 8711 ` + 8712 pageList + 8713 ` 8714 <li class="` + 8715 nextHidden + 8716 `"> <a href="javascript:void(0)" onclick="$('#request-page').val(` + 8717 pageNext + 8718 `);doneTyping();"><i class="fa fa-angle-right"></i></a> </li> 8719 </ul> 8720 </div> 8721 `; 8722 } 8723 var buttons = 8724 ` 8725 <div class="button-box p-20 text-center p-b-0"> 8726 <button class="btn btn-inverse waves-effect waves-light filter-request-result" data-filter="request-result-all"><span>` + 8727 total + 8728 `</span> <i class="fa fa-th-large m-l-5 fa-fw"></i></button> 8729 <button class="btn btn-primary waves-effect waves-light filter-request-result" data-filter="request-result-movie"><span>` + 8730 movie + 8731 `</span> <i class="fa fa-film m-l-5 fa-fw"></i></button> 8732 <button class="btn btn-info waves-effect waves-light filter-request-result" data-filter="request-result-tv"><span>` + 8733 tv + 8734 `</span> <i class="fa fa-tv m-l-5 fa-fw"></i></button> 8735 </div> 8736 `; 8737 return buttons + next + results + next; 8738} 8739function buildRequestOverseerrSeasons(array) { 8740 var hasSeasons = typeof array.data.seasons !== "undefined"; 8741 if (hasSeasons) { 8742 let seasons = array.data.seasons; 8743 let id = array.data.id; 8744 let SeasonItems = ""; 8745 $.each(seasons, function (i, v) { 8746 if (v.seasonNumber !== 0) { 8747 SeasonItems += ` 8748 <tr> 8749 <td><input type="checkbox" name="overseerr-season-${v.seasonNumber}" class="js-switch overseerr-season" data-seasonNumber="${v.seasonNumber}" data-color="#6164c1" data-size="small" /></td> 8750 <td>${v.name}</td> 8751 <td>${v.episodeCount}</td> 8752 </tr> 8753 `; 8754 } 8755 }); 8756 let html = ` 8757 <div class="panel"> 8758 <div class="bg-org2"> 8759 <div class="panel-heading">Choose Seasons</div> 8760 <div class="panel-wrapper collapse in text-left"> 8761 <div class="table-responsive"> 8762 <table class="table color-bordered-table primary-bordered-table"> 8763 <thead> 8764 <tr> 8765 <th width="20"><input type="checkbox" class="js-switch select-all-overseerr-seasons" data-color="#6164c1" data-size="small" /></th> 8766 <th lang="en">Season</th> 8767 <th lang="en"># Of Episodes</th> 8768 </tr> 8769 </thead> 8770 <tbody>${SeasonItems}</tbody> 8771 </table> 8772 </div> 8773 <div class="pull-right p-b-20"> 8774 <button class="fcbtn btn btn-info btn-outline btn-1c" lang="en" onclick="swal.close();">Cancel</button> 8775 <button class="fcbtn btn btn-success btn-outline btn-1c submit-overseerr-seasons" lang="en" data-seasons="[]" data-id="${id}" disabled onclick="processOverseerrSeasons(this)">Request Seasons</button> 8776 </div> 8777 </div>
8778 </div> 8779 </div> 8780 `; 8781 swal({ 8782 content: createElementFromHTML(html), 8783 button: null, 8784 className: "bg-org", 8785 dangerMode: false, 8786 }); 8787 } 8788} 8789 8790function processOverseerrSeasons(el) { 8791 let seasons = $(el).attr("data-seasons"); 8792 let id = $(el).attr("data-id"); 8793 overseerrActions(id, "add", "tv", seasons); 8794} 8795function processRequest(id, type) { 8796 let service = activeInfo.settings.homepage.requests.service; 8797 switch (service) { 8798 case "ombi": 8799 requestActions(id, "add", type); 8800 return false; 8801 case "overseerr": 8802 if ( 8803 type === "tv" && 8804 activeInfo.settings.homepage.overseerr.userSelectTv === true 8805 ) { 8806 organizrAPI2( 8807 "GET", 8808 "api/v2/homepage/overseerr/metadata/" + type + "/" + id 8809 ) 8810 .success(function (data) { 8811 try { 8812 let response = data.response; 8813 buildRequestOverseerrSeasons(response); 8814 } catch (e) { 8815 organizrCatchError(e, data); 8816 } 8817 }) 8818 .fail(function (xhr) { 8819 OrganizrApiError(xhr, "Overseerr Error"); 8820 }); 8821 } else { 8822 requestActions(id, "add", type); 8823 } 8824 return false; 8825 default: 8826 organizrConsole( 8827 "Request Function", 8828 "Service for Processing not setup", 8829 "error" 8830 ); 8831 return false; 8832 } 8833} 8834function requestActions(id = null, action = null, type = null, extra = null) { 8835 let service = activeInfo.settings.homepage.requests.service; 8836 switch (service) { 8837 case "ombi": 8838 ombiActions(id, action, type, extra); 8839 break; 8840 case "overseerr": 8841 overseerrActions(id, action, type, extra); 8842 break; 8843 default: 8844 organizrConsole( 8845 "Request Function", 8846 "Service for Request not setup", 8847 "error" 8848 ); 8849 return false; 8850 } 8851} 8852//Overseerr Actions 8853function overseerrActions(id, action, type = null, extra = null) { 8854 ajaxloader(".request-" + id + "-div", "in"); 8855 ajaxloader(".preloader-" + id, "in"); 8856 //$.magnificPopup.close(); 8857 messageSingle( 8858 window.lang.translate("Submitting Action to Overseerr"), 8859 "", 8860 activeInfo.settings.notifications.position, 8861 "#FFF", 8862 "success", 8863 "10000" 8864 ); 8865 switch (action) { 8866 case "add": 8867 let seasons = extra !== null ? "/" + extra : ""; 8868 var method = "POST"; 8869 var apiUrl = 8870 "api/v2/homepage/overseerr/requests/" + type + "/" + id + seasons; 8871 var data = {}; 8872 break; 8873 case "available": 8874 case "pending": 8875 case "unavailable": 8876 case "approve": 8877 var method = "POST"; 8878 var apiUrl = 8879 "api/v2/homepage/overseerr/requests/" + type + "/" + id + "/" + action; 8880 var data = {}; 8881 break; 8882 case "deny": 8883 var method = "PUT"; 8884 var apiUrl = 8885 "api/v2/homepage/overseerr/requests/" + type + "/" + id + "/" + action; 8886 var data = {}; 8887 break; 8888 case "delete": 8889 var method = "DELETE"; 8890 var apiUrl = "api/v2/homepage/overseerr/requests/" + type + "/" + id; 8891 var data = {}; 8892 break; 8893 default: 8894 return false; 8895 } 8896 organizrAPI2(method, apiUrl, data) 8897 .success(function (data) { 8898 try { 8899 let response = data.response; 8900 if (action == "add") { 8901 addTempRequest(); 8902 setTimeout(function () { 8903 ajaxloader(); 8904 }, 2000); 8905 } 8906 messageSingle( 8907 response.message, 8908 "", 8909 activeInfo.settings.notifications.position, 8910 "#FFF", 8911 "success", 8912 "5000" 8913 ); 8914 homepageRequests("overseerr"); 8915 cleanCloseSwal(); 8916 } catch (e) { 8917 organizrCatchError(e, data); 8918 } 8919 }) 8920 .fail(function (xhr) { 8921 ajaxloader(); 8922 OrganizrApiError(xhr, "Overseerr Error"); 8923 }); 8924} 8925//Ombi actions 8926function ombiActions(id, action, type, extra = null) { 8927 var msg = 8928 activeInfo.user.groupID <= 1 8929 ? '<a href="https://github.com/tidusjar/Ombi/issues/2176" target="_blank">Not Org Fault - Ask Ombi</a>' 8930 : "Connection Error to Request Server"; 8931 ajaxloader(".request-" + id + "-div", "in"); 8932 ajaxloader(".preloader-" + id, "in"); 8933 //$.magnificPopup.close(); 8934 messageSingle( 8935 window.lang.translate("Submitting Action to Ombi"), 8936 "", 8937 activeInfo.settings.notifications.position, 8938 "#FFF", 8939 "success", 8940 "10000" 8941 ); 8942 switch (action) { 8943 case "add": 8944 var method = "POST";
8945 var apiUrl = "api/v2/homepage/ombi/requests/" + type + "/" + id; 8946 var data = {}; 8947 break; 8948 case "available": 8949 case "unavailable": 8950 case "approve": 8951 var method = "POST"; 8952 var apiUrl = 8953 "api/v2/homepage/ombi/requests/" + type + "/" + id + "/" + action; 8954 var data = {}; 8955 break; 8956 case "deny": 8957 var method = "PUT"; 8958 var apiUrl = 8959 "api/v2/homepage/ombi/requests/" + type + "/" + id + "/" + action; 8960 var data = {}; 8961 break; 8962 case "delete": 8963 var method = "DELETE"; 8964 var apiUrl = "api/v2/homepage/ombi/requests/" + type + "/" + id; 8965 var data = {}; 8966 break; 8967 default: 8968 return false; 8969 } 8970 organizrAPI2(method, apiUrl, data) 8971 .success(function (data) { 8972 try { 8973 let response = data.response; 8974 if (action == "add") { 8975 addTempRequest(); 8976 } 8977 messageSingle( 8978 response.message, 8979 "", 8980 activeInfo.settings.notifications.position, 8981 "#FFF", 8982 "success", 8983 "5000" 8984 ); 8985 homepageRequests("ombi"); 8986 ajaxloader(); 8987 } catch (e) { 8988 organizrCatchError(e, data); 8989 } 8990 }) 8991 .fail(function (xhr) { 8992 ajaxloader(); 8993 OrganizrApiError(xhr, "Ombi Error"); 8994 }); 8995} 8996 8997function addTempRequest() { 8998 let service = activeInfo.settings.homepage.requests.service; 8999 let html = ` 9000 <div class="item lazyload recent-poster request-item request-adding mouse" data-src=""> 9001 <div class="outside-request-div"> 9002 <div class="inside-over-request-div bg-danger"></div> 9003 <div class="inside-request-div bg-info"></div> 9004 </div> 9005 <div class="hover-homepage-item"></div> 9006 <span class="elip request-title-tv"><i class="fa fa-tv"></i></span> 9007 <span class="elip recent-title">Adding Request</span> 9008 </div> 9009 `; 9010 $(".request-items-" + service) 9011 .trigger("add.owl", [html, 0]) 9012 .trigger("refresh.owl"); 9013 setTimeout(function () { 9014 ajaxloader(".request-adding", "in"); 9015 }, 100); 9016} 9017function cleanCloseSwal() { 9018 let state = swal.getState().isOpen; 9019 if (state === true) { 9020 swal.close(); 9021 } 9022} 9023function doneTyping() { 9024 let title = $("#request-input").val(); 9025 if (title == "") { 9026 return false; 9027 } 9028 var page = $("#request-page").val() ? $("#request-page").val() : 1; 9029 if (typeof searchTerm !== "undefined") { 9030 if (searchTerm !== $("#request-input").val()) { 9031 page = 1; 9032 } 9033 } 9034 ajaxloader(".search-div", "in"); 9035 searchTerm = title; 9036 $("#request-page").val(page); 9037 requestSearch(title, page) 9038 .success(function (data) { 9039 $("#request-results").html( 9040 buildRequestResult(data, "", title, page, true) 9041 ); 9042 if (bowser.mobile !== true) { 9043 $(".resultBox-inside").slimScroll({ 9044 height: "100%", 9045 position: "right", 9046 size: "5px", 9047 color: "#dcdcdc", 9048 }); 9049 } 9050 $(".mfp-wrap").animate( 9051 { 9052 scrollTop: "0", 9053 }, 9054 500 9055 ); 9056 ajaxloader(); 9057 }) 9058 .fail(function (xhr) { 9059 OrganizrApiError(xhr, "TMDB Error"); 9060 ajaxloader(); 9061 }); 9062} 9063function requestList(list, type, page = 1) { 9064 ajaxloader(".search-div", "in"); 9065 requestSearchList(list, page) 9066 .success(function (data) { 9067 if (typeof data.results !== "undefined") { 9068 var results = data.results; 9069 } else if (typeof data.items !== "undefined") { 9070 var results = data.items; 9071 } 9072 $("#request-results").html(buildRequestResult(data, type, list, page)); 9073 if (bowser.mobile !== true) { 9074 $(".resultBox-inside").slimScroll({ 9075 height: "100%", 9076 position: "right", 9077 size: "5px", 9078 color: "#dcdcdc", 9079 }); 9080 } 9081 $(".mfp-wrap").animate( 9082 { 9083 scrollTop: "0", 9084 }, 9085 500 9086 ); 9087 ajaxloader(); 9088 }) 9089 .fail(function (xhr) { 9090 OrganizrApiError(xhr, "TMDB Error"); 9091 ajaxloader(); 9092 }); 9093} 9094function buildDownloaderItem(array, source, type = "none") { 9095 var queue = ""; 9096 var count = 0; 9097 var history = ""; 9098 switch (source) { 9099 case "jdownloader": 9100 if (array.content === false) { 9101 queue = 9102 '<tr><td class="max-texts" lang="en">
9102Connection Error to ' + 9103 source + 9104 "</td></tr>"; 9105 break; 9106 } 9107 9108 if ( 9109 array.content.queueItems.length == 0 && 9110 array.content.grabberItems.length == 0 && 9111 array.content.encryptedItems.length == 0 && 9112 array.content.offlineItems.length == 0 9113 ) { 9114 queue = 9115 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9116 } else { 9117 if (array.content.$status[0] == "RUNNING") { 9118 queue += ` 9119 <tr><td> 9120 <a href="#" onclick="return false;"><span class="downloader mouse" data-source="jdownloader" data-action="pause" data-target="main"><i class="fa fa-pause"></i></span></a> 9121 <a href="#" onclick="return false;"><span class="downloader mouse" data-source="jdownloader" data-action="stop" data-target="main"><i class="fa fa-stop"></i></span></a> 9122 </td></tr> 9123 `; 9124 } else if (array.content.$status[0] == "PAUSE") { 9125 queue += `<tr><td><a href="#" onclick="return false;"><span class="downloader mouse" data-source="jdownloader" data-action="resume" data-target="main"><i class="fa fa-fast-forward"></i></span></a></td></tr>`; 9126 } else { 9127 queue += `<tr><td><a href="#" onclick="return false;"><span class="downloader mouse" data-source="jdownloader" data-action="start" data-target="main"><i class="fa fa-play"></i></span></a></td></tr>`; 9128 } 9129 if (array.content.$status[1]) { 9130 queue += `<tr><td><a href="#" onclick="return false;"><span class="downloader mouse" data-source="jdownloader" data-action="update" data-target="main"><i class="fa fa-globe"></i></span></a></td></tr>`; 9131 } 9132 } 9133 $.each(array.content.queueItems, function (i, v) { 9134 count = count + 1; 9135 if (v.speed == null) { 9136 v.speed = "Stopped"; 9137 } 9138 if (v.eta == null) { 9139 if (v.percentage == "100") { 9140 v.speed = "Completed"; 9141 v.eta = "--"; 9142 } else { 9143 v.eta = "--"; 9144 } 9145 } 9146 if (v.enabled == null) { 9147 v.speed = "Disabled"; 9148 } 9149 queue += 9150 ` 9151 <tr> 9152 <td class="max-texts">` + 9153 v.name + 9154 `</td> 9155 <td>` + 9156 v.speed + 9157 `</td> 9158 <td class="hidden-xs" alt="` + 9159 v.done + 9160 `">` + 9161 v.size + 9162 `</td> 9163 <td class="hidden-xs">` + 9164 v.eta + 9165 `</td> 9166 <td class="text-right"> 9167 <div class="progress progress-lg m-b-0"> 9168 <div class="progress-bar progress-bar-info" style="width: ` + 9169 v.percentage + 9170 `%;" role="progressbar">` + 9171 v.percentage + 9172 `%</div> 9173 </div> 9174 </td> 9175 </tr> 9176 `; 9177 }); 9178 $.each(array.content.grabberItems, function (i, v) { 9179 count = count + 1; 9180 queue += 9181 ` 9182 <tr> 9183 <td class="max-texts">` + 9184 v.name + 9185 `</td> 9186 <td>Online</td> 9187 <td class="hidden-xs"> -- </td> 9188 <td class="hidden-xs"> -- </td> 9189 <td class="text-right"> 9190 <div class="progress progress-lg m-b-0"> 9191 <div class="progress-bar progress-bar-info" style="width: 0%;" role="progressbar">0%</div> 9192 </div> 9193 </td> 9194 </tr> 9195 `; 9196 }); 9197 $.each(array.content.encryptedItems, function (i, v) { 9198 count = count + 1; 9199 queue += 9200 ` 9201 <tr> 9202 <td class="max-texts">` + 9203 v.name + 9204 `</td> 9205 <td>Encrypted</td> 9206 <td class="hidden-xs"> -- </td> 9207 <td class="hidden-xs"> -- </td> 9208 <td class="text-right"> 9209 <div class="progress progress-lg m-b-0"> 9210 <div class="progress-bar progress-bar-info" style="width: 0%;" role="progressbar">0%</div> 9211 </div> 9212 </td> 9213 </tr> 9214 `; 9215 }); 9216 $.each(array.content.offlineItems, function (i, v) { 9217 count = count + 1; 9218 queue += 9219 ` 9220 <tr> 9221 <td class="max-texts">` + 9222 v.name + 9223 `</td> 9224 <td>Offline</td> 9225 <td class="hidden-xs"> -- </td> 9226 <td class="hidden-xs"> -- </td> 9227 <td class="text-right"> 9228 <div class="progress progress-lg m-b-0"> 9229 <div class="progress-bar progress-bar-info" style="width: 0%;" role="progressbar">0%</div> 9230 </div> 9231 </td> 9232 </tr> 9233 `; 9234 }); 9235 break; 9236 case "sabnzbd": 9237 if (array.content === false) { 9238 queue = 9239 '<tr><td class="max-texts" lang="en">
9239Connection Error to ' + 9240 source + 9241 "</td></tr>"; 9242 break; 9243 } 9244 if (array.content.queueItems.queue.paused) { 9245 var state = `<a href="#" onclick="return false;"><span class="downloader mouse" data-source="sabnzbd" data-action="resume" data-target="main"><i class="fa fa-play"></i></span></a>`; 9246 var active = "grayscale"; 9247 } else { 9248 var state = `<a href="#" onclick="return false;"><span class="downloader mouse" data-source="sabnzbd" data-action="pause" data-target="main"><i class="fa fa-pause"></i></span></a>`; 9249 var active = ""; 9250 } 9251 $(".sabnzbd-downloader-action").html(state); 9252 9253 if (array.content.queueItems.queue.slots.length == 0) { 9254 queue = 9255 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9256 } 9257 $.each(array.content.queueItems.queue.slots, function (i, v) { 9258 count = count + 1; 9259 var action = v.status == "Downloading" ? "pause" : "resume"; 9260 var actionIcon = v.status == "Downloading" ? "pause" : "play"; 9261 queue += 9262 ` 9263 <tr> 9264 <td class="max-texts">` + 9265 v.filename + 9266 `</td> 9267 <td class="hidden-xs sabnzbd-` + 9268 cleanClass(v.status) + 9269 `">` + 9270 v.status + 9271 `</td> 9272 <td class="downloader mouse" data-target="` + 9273 v.nzo_id + 9274 `" data-source="sabnzbd" data-action="` + 9275 action + 9276 `"><i class="fa fa-` + 9277 actionIcon + 9278 `"></i></td> 9279 <td class="hidden-xs"><span class="label label-info">` + 9280 v.cat + 9281 `</span></td> 9282 <td class="hidden-xs">` + 9283 v.size + 9284 `</td> 9285 <td class="hidden-xs" alt="` + 9286 v.eta + 9287 `">` + 9288 v.timeleft + 9289 `</td> 9290 <td class="text-right"> 9291 <div class="progress progress-lg m-b-0"> 9292 <div class="progress-bar progress-bar-info" style="width: ` + 9293 v.percentage + 9294 `%;" role="progressbar">` + 9295 v.percentage + 9296 `%</div> 9297 </div> 9298 </td> 9299 </tr> 9300 `; 9301 }); 9302 if (array.content.historyItems.history.slots.length == 0) { 9303 history = 9304 '<tr><td class="max-texts" lang="en">Nothing in history</td></tr>'; 9305 } 9306 $.each(array.content.historyItems.history.slots, function (i, v) { 9307 history += 9308 ` 9309 <tr> 9310 <td class="max-texts">` + 9311 v.name + 9312 `</td> 9313 <td class="hidden-xs sabnzbd-` + 9314 cleanClass(v.status) + 9315 `">` + 9316 v.status + 9317 `</td> 9318 <td class="hidden-xs"><span class="label label-info">` + 9319 v.category + 9320 `</span></td> 9321 <td class="hidden-xs">` + 9322 v.size + 9323 `</td> 9324 <td class="text-right"> 9325 <div class="progress progress-lg m-b-0"> 9326 <div class="progress-bar progress-bar-info" style="width: 100%;" role="progressbar">100%</div> 9327 </div> 9328 </td> 9329 </tr> 9330 `; 9331 }); 9332 break; 9333 case "nzbget": 9334 if (array.content === false) { 9335 queue = 9336 '<tr><td class="max-texts" lang="en">Connection Error to ' + 9337 source + 9338 "</td></tr>"; 9339 break; 9340 } 9341 if (array.content.queueItems.result.length == 0) { 9342 queue = 9343 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9344 } 9345 $.each(array.content.queueItems.result, function (i, v) { 9346 count = count + 1; 9347 var action = v.Status == "Downloading" ? "pause" : "resume"; 9348 var actionIcon = v.Status == "Downloading" ? "pause" : "play"; 9349 var percent = Math.floor( 9350 ((v.FileSizeMB - v.RemainingSizeMB) * 100) / v.FileSizeMB 9351 ); 9352 var size = v.FileSizeMB * 1000000; 9353 v.Category = v.Category !== "" ? v.Category : "Not Set"; 9354 queue += 9355 ` 9356 <tr> 9357 <td class="max-texts">` + 9358 v.NZBName + 9359 `</td> 9360 <td class="hidden-xs nzbget-` + 9361 cleanClass(v.Status) + 9362 `">` + 9363 v.Status + 9364 `</td> 9365 <!--<td class="downloader mouse" data-target="` + 9366 v.NZBID + 9367 `" data-source="sabnzbd" data-action="` + 9368 action + 9369 `"><i class="fa fa-` + 9370 actionIcon + 9371 `"></i></td>--> 9372 <td class="hidden-xs"><span class="label label-info">` + 9373 v.Category + 9374 `</span></td> 9375 <td class="hidden-xs">` + 9376 humanFileSize(size, true) + 9377 `</td> 9378 <td class="text-right"> 9379 <div class="progress progress-lg m-b-0"> 9380 <div class="progress-bar progress-bar-info" style="width: ` + 9381 percent + 9382 `%;" role="progressbar">` + 9383 percent + 9384 `%</div> 9385 </div> 9386 </td> 9387 </tr> 9388 `; 9389 }); 9390 if (array.content.historyItems.result.length == 0) { 9391 history = 9392 '<tr><td class="max-texts" lang="en">Nothing in history</td></tr>'; 9393 } 9394 $.each(array.content.historyItems.result, function (i, v) { 9395 v.Category = v.Category !== "" ? v.Category : "Not Set"; 9396 var size = v.FileSizeMB * 1000000; 9397 history += 9398 ` 9399 <tr> 9400 <td class="max-texts">` + 9401 v.NZBName + 9402 `</td> 9403 <td class="hidden-xs nzbget-` + 9404 cleanClass(v.Status) + 9405 `">` + 9406 v.Status + 9407 `</td> 9408 <td class="hidden-xs"><span class="label label-info">` + 9409 v.Category + 9410 `</span></td> 9411 <td class="hidden-xs">` + 9412 humanFileSize(size, true) + 9413 `</td> 9414 <td class="text-right"> 9415 <div class="progress progress-lg m-b-0"> 9416 <div class="progress-bar progress-bar-info" style="width: 100%;" role="progressbar">100%</div> 9417 </div> 9418 </td> 9419 </tr> 9420 `; 9421 }); 9422 break; 9423 case "transmission": 9424 if (array.content === false) { 9425 queue = 9426 '<tr><td class="max-texts" lang="en">
9426Connection Error to ' + 9427 source + 9428 "</td></tr>"; 9429 break; 9430 } 9431 if (array.content.queueItems == 0) { 9432 queue = 9433 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9434 } 9435 $.each(array.content.queueItems, function (i, v) { 9436 count = count + 1; 9437 switch (v.status) { 9438 case 7: 9439 case "7": 9440 var status = "No Peers"; 9441 break; 9442 case 6: 9443 case "6": 9444 var status = "Seeding"; 9445 break; 9446 case 5: 9447 case "5": 9448 var status = "Seeding Queued"; 9449 break; 9450 case 4: 9451 case "4": 9452 var status = "Downloading"; 9453 break; 9454 case 3: 9455 case "3": 9456 var status = "Queued"; 9457 break; 9458 case 2: 9459 case "2": 9460 var status = "Checking Files"; 9461 break; 9462 case 1: 9463 case "1": 9464 var status = "File Check Queued"; 9465 break; 9466 case 0: 9467 case "0": 9468 var status = "Complete"; 9469 break; 9470 default: 9471 var status = "Complete"; 9472 } 9473 var percent = Math.floor(v.percentDone * 100); 9474 v.Category = v.Category !== "" ? v.Category : "Not Set"; 9475 queue += 9476 ` 9477 <tr> 9478 <td class="max-texts">` + 9479 v.name + 9480 `</td> 9481 <td class="hidden-xs transmission-` + 9482 cleanClass(status) + 9483 `">` + 9484 status + 9485 `</td> 9486 <td class="hidden-xs">` + 9487 v.downloadDir + 9488 `</td> 9489 <td class="hidden-xs">` + 9490 humanFileSize(v.totalSize, true) + 9491 `</td> 9492 <td class="text-right"> 9493 <div class="progress progress-lg m-b-0"> 9494 <div class="progress-bar progress-bar-info" style="width: ` + 9495 percent + 9496 `%;" role="progressbar">` + 9497 percent + 9498 `%</div> 9499 </div> 9500 </td> 9501 </tr> 9502 `; 9503 }); 9504 break; 9505 case "rTorrent": 9506 if (array.content === false) { 9507 queue = 9508 '<tr><td class="max-texts" lang="en">Connection Error to ' + 9509 source + 9510 "</td></tr>"; 9511 break; 9512 } 9513 if (array.content.queueItems == 0) { 9514 queue = 9515 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9516 } 9517 $.each(array.content.queueItems, function (i, v) { 9518 count = count + 1; 9519 var percent = Math.floor((v.downloaded / v.size) * 100); 9520 var size = v.size != -1 ? humanFileSize(v.size, false) : "?"; 9521 var upload = v.seed !== "" ? humanFileSize(v.seed, true) : "0 B"; 9522 var download = v.leech !== "" ? humanFileSize(v.leech, true) : "0 B"; 9523 var upTotal = 9524 v.upTotal !== "" ? humanFileSize(v.upTotal, false) : "0 B"; 9525 var downTotal = 9526 v.downTotal !== "" ? humanFileSize(v.downTotal, false) : "0 B"; 9527 var date = new Date(0); 9528 date.setUTCSeconds(v.date); 9529 date = moment(date).format("LLL"); 9530 queue += 9531 ` 9532 <tr> 9533 <td class="max-texts"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 9534 date + 9535 `">` + 9536 v.name + 9537 `</span></td> 9538 <td class="hidden-xs rtorrent-` + 9539 cleanClass(v.status) + 9540 `">` + 9541 v.status + 9542 `</td> 9543 <td class="hidden-xs"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 9544 downTotal + 9545 `"><i class="fa fa-download"></i> ` + 9546 download + 9547 `</span></td> 9548 <td class="hidden-xs"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 9549 upTotal + 9550 `"><i class="fa fa-upload"></i> ` + 9551 upload + 9552 `</span></td> 9553 <td class="hidden-xs">` + 9554 size + 9555 `</td> 9556 <td class="hidden-xs"><span class="label label-info">` + 9557 v.label + 9558 `</span></td> 9559 <td class="text-right"> 9560 <div class="progress progress-lg m-b-0"> 9561 <div class="progress-bar progress-bar-info" style="width: ` + 9562 percent + 9563 `%;" role="progressbar">` + 9564 percent + 9565 `%</div> 9566 </div> 9567 </td> 9568 </tr> 9569 `; 9570 }); 9571 break; 9572 case "utorrent": 9573 if (array.content === false) { 9574 queue = 9575 '<tr><td class="max-texts" lang="en">
9575Connection Error to ' + 9576 source + 9577 "</td></tr>"; 9578 break; 9579 } 9580 if (array.content.queueItems == 0) { 9581 queue = 9582 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9583 } 9584 $.each(array.content.queueItems, function (i, v) { 9585 count = count + 1; 9586 var upload = v.upSpeed !== "" ? humanFileSize(v.upSpeed, false) : "0 B"; 9587 var download = 9588 v.downSpeed !== "" ? humanFileSize(v.downSpeed, false) : "0 B"; 9589 var size = v.Size !== "" ? humanFileSize(v.Size, false) : "0 B"; 9590 queue += 9591 ` 9592 <tr> 9593 <td class="max-texts"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="">` + 9594 v.Name + 9595 `</span></td> 9596 <td class="hidden-xs utorrent-` + 9597 cleanClass(v.Status) + 9598 `">` + 9599 v.Status + 9600 `</td> 9601 <td class="hidden-xs"><span class="label label-info">` + 9602 v.Labels + 9603 `</span></td> 9604 <td class="hidden-xs"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 9605 download + 9606 `"><i class="fa fa-download"></i> ` + 9607 download + 9608 `</span></td> 9609 <td class="hidden-xs"><span class="tooltip-info" data-toggle="tooltip" data-placement="right" title="" data-original-title="` + 9610 upload + 9611 `"><i class="fa fa-upload"></i> ` + 9612 upload + 9613 `</span></td> 9614 <td class="hidden-xs">` + 9615 size + 9616 `</td> 9617 <td class="text-right"> 9618 <div class="progress progress-lg m-b-0"> 9619 <div class="progress-bar progress-bar-info" style="width: ` + 9620 v.Percent + 9621 `;" role="progressbar">` + 9622 v.Percent + 9623 `</div> 9624 </div> 9625 </td> 9626 </tr> 9627 `; 9628 }); 9629 break; 9630 case "sonarr": 9631 if (array.content === false) { 9632 queue = 9633 '<tr><td class="max-texts" lang="en">Connection Error to ' + 9634 source + 9635 "</td></tr>"; 9636 break; 9637 } 9638 if (array.content.queueItems == 0) { 9639 queue = 9640 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9641 break; 9642 } 9643 if (array.content.queueItems.records == 0) { 9644 queue = 9645 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9646 break; 9647 } 9648 let sonarrQueueSet = 9649 typeof array.content.queueItems.records == "undefined" 9650 ? array.content.queueItems 9651 : array.content.queueItems.records; 9652 $.each(sonarrQueueSet, function (i, v) { 9653 count = count + 1; 9654 var percent = Math.floor(((v.size - v.sizeleft) / v.size) * 100); 9655 percent = isNaN(percent) ? "0" : percent; 9656 var size = v.size != -1 ? humanFileSize(v.size, false) : "?"; 9657 v.name = typeof v.series == "undefined" ? v.title : v.series.title; 9658 queue += 9659 ` 9660 <tr> 9661 <td class="">` + 9662 v.name + 9663 `</td> 9664 <td class="">S` + 9665 pad(v.episode.seasonNumber, 2) + 9666 `E` + 9667 pad(v.episode.episodeNumber, 2) + 9668 `</td> 9669 <td class="max-texts">` + 9670 v.episode.title + 9671 `</td> 9672 <td class="hidden-xs sonarr-` + 9673 cleanClass(v.status) + 9674 `">` + 9675 v.status + 9676 `</td> 9677 <td class="hidden-xs">` + 9678 size + 9679 `</td> 9680 <td class="hidden-xs"><span class="label label-info">` + 9681 v.protocol + 9682 `</span></td> 9683 <td class="text-right"> 9684 <div class="progress progress-lg m-b-0"> 9685 <div class="progress-bar progress-bar-info" style="width: ` + 9686 percent + 9687 `%;" role="progressbar">` + 9688 percent + 9689 `%</div> 9690 </div> 9691 </td> 9692 </tr> 9693 `; 9694 }); 9695 break; 9696 case "radarr": 9697 if (array.content === false) { 9698 queue = 9699 '<tr><td class="max-texts" lang="en">
9699Connection Error to ' + 9700 source + 9701 "</td></tr>"; 9702 break; 9703 } 9704 if (array.content.queueItems == 0) { 9705 queue = 9706 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9707 break; 9708 } 9709 if (array.content.queueItems.records == 0) { 9710 queue = 9711 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9712 break; 9713 } 9714 let queueSet = 9715 typeof array.content.queueItems.records == "undefined" 9716 ? array.content.queueItems 9717 : array.content.queueItems.records; 9718 $.each(queueSet, function (i, v) { 9719 count = count + 1; 9720 var percent = Math.floor(((v.size - v.sizeleft) / v.size) * 100); 9721 percent = isNaN(percent) ? "0" : percent; 9722 var size = v.size != -1 ? humanFileSize(v.size, false) : "?"; 9723 v.name = typeof v.movie == "undefined" ? v.title : v.movie.title; 9724 queue += ` 9725 <tr> 9726 <td class="max-texts">${v.name}</td> 9727 <td class="hidden-xs sonarr-${cleanClass(v.status)}">${ 9728 v.status 9729 }</td> 9730 <td class="hidden-xs">${size}</td> 9731 <td class="hidden-xs"><span class="label label-info">${ 9732 v.protocol 9733 }</span></td> 9734 <td class="text-right"> 9735 <div class="progress progress-lg m-b-0"> 9736 <div class="progress-bar progress-bar-info" style="width: ${percent}%;" role="progressbar">${percent}%</div> 9737 </div> 9738 </td> 9739 </tr> 9740 `; 9741 }); 9742 if (queue == "") { 9743 queue = 9744 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9745 } 9746 break; 9747 case "qBittorrent": 9748 if (array.content === false) { 9749 queue = 9750 '<tr><td class="max-texts" lang="en">Connection Error to ' + 9751 source + 9752 "</td></tr>"; 9753 break; 9754 } 9755 if (array.content.queueItems == 0) { 9756 queue = 9757 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9758 } 9759 $.each(array.content.queueItems, function (i, v) { 9760 count = count + 1; 9761 switch (v.state) { 9762 case "stalledDL": 9763 var status = "No Peers"; 9764 break; 9765 case "metaDL": 9766 var status = "Getting Metadata"; 9767 break; 9768 case "uploading": 9769 var status = "Seeding"; 9770 break; 9771 case "queuedUP": 9772 var status = "Seeding Queued"; 9773 break; 9774 case "downloading": 9775 var status = "Downloading"; 9776 break; 9777 case "queuedDL": 9778 var status = "Queued"; 9779 break; 9780 case "checkingDL": 9781 case "checkingUP": 9782 var status = "Checking Files"; 9783 break; 9784 case "pausedDL": 9785 var status = "Paused"; 9786 break; 9787 case "pausedUP": 9788 var status = "Complete"; 9789 break; 9790 default: 9791 var status = "Complete"; 9792 } 9793 var percent = Math.floor(v.progress * 100); 9794 var size = v.total_size != -1 ? humanFileSize(v.total_size, true) : "?"; 9795 queue += 9796 ` 9797 <tr> 9798 <td class="max-texts">` + 9799 v.name + 9800 `</td> 9801 <td class="hidden-xs qbit-` + 9802 cleanClass(status) + 9803 `">` + 9804 status + 9805 `</td> 9806 <td class="hidden-xs">` + 9807 v.save_path + 9808 `</td> 9809 <td class="hidden-xs">` + 9810 size + 9811 `</td> 9812 <td class="text-right"> 9813 <div class="progress progress-lg m-b-0"> 9814 <div class="progress-bar progress-bar-info" style="width: ` + 9815 percent + 9816 `%;" role="progressbar">` + 9817 percent + 9818 `%</div> 9819 </div> 9820 </td> 9821 </tr> 9822 `; 9823 }); 9824 break; 9825 case "deluge": 9826 if (array.content === false) { 9827 queue = 9828 '<tr><td class="max-texts" lang="en">
9828Connection Error to ' + 9829 source + 9830 "</td></tr>"; 9831 break; 9832 } 9833 if (array.content.queueItems.length == 0) { 9834 queue = 9835 '<tr><td class="max-texts" lang="en">Nothing in queue</td></tr>'; 9836 } 9837 $.each(array.content.queueItems, function (i, v) { 9838 count = count + 1; 9839 var percent = Math.floor(v.progress); 9840 var size = v.total_size != -1 ? humanFileSize(v.total_size, true) : "?"; 9841 var upload = 9842 v.upload_payload_rate != -1 9843 ? humanFileSize(v.upload_payload_rate, true) 9844 : "?"; 9845 var download = 9846 v.download_payload_rate != -1 9847 ? humanFileSize(v.download_payload_rate, true) 9848 : "?"; 9849 var action = v.Status == "Downloading" ? "pause" : "resume"; 9850 var actionIcon = v.Status == "Downloading" ? "pause" : "play"; 9851 queue += 9852 ` 9853 <tr> 9854 <td class="max-texts">` + v.name; 9855 if (v.tracker_status != "") 9856 queue += 9857 `<i class="fa fa-caret-down ml-2" style="cursor:pointer" onclick="$(this).toggleClass('fa-caret-down');$(this).toggleClass('fa-caret-up');$('#status-` + 9858 v.hash + 9859 `').toggleClass('d-none');" aria-hidden="true"></i><br /><div class="well mb-0 mt-2 p-3 d-none" id="status-` + 9860 v.hash + 9861 `">` + 9862 v.tracker_status + 9863 `</div>`; 9864 queue += 9865 `</td> 9866 <td class="hidden-xs deluge-` + 9867 cleanClass(v.state) + 9868 `">` + 9869 v.state + 9870 `</td> 9871 <td class="hidden-xs">` + 9872 size + 9873 `</td> 9874 <td class="hidden-xs"><i class="fa fa-download"></i> ` + 9875 download + 9876 `</td> 9877 <td class="hidden-xs"><i class="fa fa-upload"></i> ` + 9878 upload + 9879 `</td> 9880 <td class="text-right"> 9881 <div class="progress progress-lg m-b-0"> 9882 <div class="progress-bar progress-bar-info" style="width: ` + 9883 percent + 9884 `%;" role="progressbar">` + 9885 percent + 9886 `%</div> 9887 </div> 9888 </td> 9889 </tr> 9890 `; 9891 }); 9892 break; 9893 default: 9894 return false; 9895 } 9896 if (queue !== "") { 9897 $("." + source + "-queue").html(queue); 9898 } 9899 if (history !== "") { 9900 $("." + source + "-history").html(history); 9901 } 9902 $("#count-" + source).html(count); 9903} 9904function buildDownloader(source) { 9905 var queueButton = "QUEUE"; 9906 var historyButton = "HISTORY"; 9907 switch (source) { 9908 case "jdownloader": 9909 var queue = true; 9910 var history = false; 9911 queueButton = "REFRESH"; 9912 break; 9913 case "sabnzbd": 9914 case "nzbget": 9915 var queue = true; 9916 var history = true; 9917 break; 9918 case "transmission": 9919 case "qBittorrent": 9920 case "deluge": 9921 case "utorrent": 9922 var queue = true; 9923 break; 9924 case "rTorrent": 9925 case "sonarr": 9926 case "radarr": 9927 var queue = true; 9928 var history = false; 9929 queueButton = "REFRESH"; 9930 break; 9931 default: 9932 var queue = false; 9933 var history = false; 9934 } 9935 var menu = `<ul class="nav customtab nav-tabs pull-right" role="tablist">`; 9936 var listing = ""; 9937 var state = ""; 9938 var active = ""; 9939 var headerAlt = ""; 9940 var header = ""; 9941 //console.log(array); 9942 //console.log(queueItems); 9943 //console.log(historyItems); 9944 //console.log(downloader); 9945 if (queue) { 9946 menu += 9947 ` 9948 <li role="presentation" class="active" onclick="homepageDownloader('` + 9949 source + 9950 `')"><a href="#` + 9951 source + 9952 `-queue" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="true"><span class="visible-xs"><i class="ti-download"></i></span><span class="hidden-xs">` + 9953 queueButton + 9954 `</span></a></li> 9955 `; 9956 listing += 9957 ` 9958 <div role="tabpanel" class="tab-pane fade active in" id="` + 9959 source + 9960 `-queue"> 9961 <div class="inbox-center table-responsive"> 9962 <table class="table table-hover"> 9963 <tbody class="` + 9964 source + 9965 `-queue"></tbody> 9966 </table> 9967 </div> 9968 <div class="clearfix"></div> 9969 </div> 9970 `; 9971 } 9972 if (history) { 9973 menu += 9974 ` 9975 <li role="presentation" class=""><a href="#` + 9976 source + 9977 `-history" aria-controls="profile" role="tab" data-toggle="tab" aria-expanded="false"><span class="visible-xs"><i class="ti-time"></i></span> <span class="hidden-xs">` + 9978 historyButton + 9979 `</span></a></li> 9980 `; 9981 listing += 9982 ` 9983 <div role="tabpanel" class="tab-pane fade" id="` + 9984 source + 9985 `-history"> 9986 <div class="inbox-center table-responsive"> 9987 <table class="table table-hover"> 9988 <tbody class="` + 9989 source + 9990 `-history"></tbody> 9991 </table> 9992 </div> 9993 <div class="clearfix"></div> 9994 </div> 9995 `; 9996 } 9997 menu += "</ul>"; 9998 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 9999 var headerAlt = 10000 ` 10001 <div class="col-md-12"> 10002 <h2 class="text-white m-0 pull-left text-uppercase"><img class="lazyload homepageImageTitle ` + 10003 active + 10004 `" data-src="plugins/images/tabs/` + 10005 source + 10006 `.png"> ` + 10007 state + 10008 `</h2> 10009 ` + 10010 menu + 10011 ` 10012 <hr class="hidden-xs"><div class="clearfix"></div> 10013 </div> 10014 <div class="clearfix"></div> 10015 `; 10016 } else { 10017 var header = 10018 ` 10019 <div class="white-box bg-info m-b-0 p-b-0 p-t-10 mailbox-widget"> 10020 <h2 class="text-white m-0 pull-left text-uppercase"><img class="lazyload homepageImageTitle ` + 10021 active + 10022 `" data-src="plugins/images/tabs/` + 10023 source + 10024 `.png"> ` + 10025 state + 10026 `</h2> 10027 ` + 10028 menu + 10029 ` 10030 <div class="clearfix"></div> 10031 </div> 10032 `; 10033 } 10034 return ( 10035 ` 10036 <div class="row"> 10037 ` + 10038 headerAlt + 10039 ` 10040 <div class="col-lg-12"> 10041 ` + 10042 header + 10043 ` 10044 <div class="white-box p-0"> 10045 <div class="tab-content m-t-0">` + 10046 listing + 10047 `</div> 10048 </div> 10049 </div> 10050 </div> 10051 ` 10052 ); 10053} 10054function buildDownloaderCombined(source) { 10055 var first = $(".combinedDownloadRow").length == 0 ? true : false;
10056 var active = first ? "active" : ""; 10057 var queueButton = "QUEUE"; 10058 var historyButton = "HISTORY"; 10059 switch (source) { 10060 case "jdownloader": 10061 var queue = true; 10062 var history = false; 10063 queueButton = "REFRESH"; 10064 break; 10065 case "sabnzbd": 10066 case "nzbget": 10067 var queue = true; 10068 var history = true; 10069 break; 10070 case "utorrent": 10071 var queue = true; 10072 break; 10073 case "transmission": 10074 case "qBittorrent": 10075 case "deluge": 10076 case "rTorrent": 10077 case "sonarr": 10078 case "radarr": 10079 var queue = true; 10080 var history = false; 10081 queueButton = "REFRESH"; 10082 break; 10083 default: 10084 var queue = false; 10085 var history = false; 10086 } 10087 var mainMenu = `<ul class="nav customtab nav-tabs combinedMenuList" role="tablist">`; 10088 var addToMainMenu = 10089 `<li role="presentation" class="` + 10090 active + 10091 `"><a onclick="homepageDownloader('` + 10092 source + 10093 `')" href="#combined-` + 10094 source + 10095 `" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="true"><span class=""><img src="./plugins/images/tabs/` + 10096 source + 10097 `.png" class="homepageImageTitle"><span class="badge bg-org downloaderCount" id="count-` + 10098 source + 10099 `"><i class="fa fa-spinner fa-spin"></i></span></span></a></li>`; 10100 var listing = ""; 10101 var headerAlt = ""; 10102 var header = ""; 10103 var menu = `<ul class="nav customtab nav-tabs m-t-5" role="tablist">`; 10104 if (queue) { 10105 menu += 10106 ` 10107 <li role="presentation" class="active" onclick="homepageDownloader('` + 10108 source + 10109 `')"><a href="#` + 10110 source + 10111 `-queue" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="true"><span class="visible-xs"><i class="ti-download"></i></span><span class="hidden-xs">` + 10112 queueButton + 10113 `</span></a></li> 10114 `; 10115 listing += 10116 ` 10117 <div role="tabpanel" class="tab-pane fade active in" id="` + 10118 source + 10119 `-queue"> 10120 <div class="inbox-center table-responsive"> 10121 <table class="table table-hover"> 10122 <tbody class="` + 10123 source + 10124 `-queue"></tbody> 10125 </table> 10126 </div> 10127 <div class="clearfix"></div> 10128 </div> 10129 `; 10130 } 10131 if (history) { 10132 menu += 10133 ` 10134 <li role="presentation" class=""><a href="#` + 10135 source + 10136 `-history" aria-controls="profile" role="tab" data-toggle="tab" aria-expanded="false"><span class="visible-xs"><i class="ti-time"></i></span> <span class="hidden-xs">` + 10137 historyButton + 10138 `</span></a></li> 10139 `; 10140 listing += 10141 ` 10142 <div role="tabpanel" class="tab-pane fade" id="` + 10143 source + 10144 `-history"> 10145 <div class="inbox-center table-responsive"> 10146 <table class="table table-hover"> 10147 <tbody class="` + 10148 source + 10149 `-history"></tbody> 10150 </table> 10151 </div> 10152 <div class="clearfix"></div> 10153 </div> 10154 `; 10155 } 10156 menu += 10157 '<li class="' + 10158 source + 10159 '-downloader-action"></li></ul><div class="clearfix"></div>'; 10160 menu = queue && history ? menu : ""; 10161 var listingMain = 10162 '<div role="tabpanel" class="tab-pane fade ' + 10163 active + 10164 ' in" id="combined-' + 10165 source + 10166 '">' + 10167 menu + 10168 '<div class="tab-content m-t-0 listingSingle">' + 10169 listing + 10170 "</div></div>"; 10171 mainMenu += first ? addToMainMenu + "</ul>" : ""; 10172 if (first) { 10173 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 10174 var headerAlt = 10175 ` 10176 <div class="col-md-12"> 10177 ` + 10178 mainMenu + 10179 ` 10180 <div class="clearfix"></div> 10181 </div> 10182 <div class="clearfix"></div> 10183 `; 10184 } else { 10185 var header = 10186 ` 10187 <div class="white-box bg-info m-b-0 p-b-0 p-10 mailbox-widget"> 10188 ` + 10189 mainMenu + 10190 ` 10191 <div class="clearfix"></div> 10192 </div> 10193 `; 10194 } 10195 var built = 10196 ` 10197 <div class="row combinedDownloadRow"> 10198 ` + 10199 headerAlt + 10200 ` 10201 <div class="col-lg-12"> 10202 ` + 10203 header + 10204 ` 10205 <div class="white-box p-0"> 10206 <div class="tab-content m-t-0 listingMain">` + 10207 listingMain + 10208 `</div> 10209 </div> 10210 </div> 10211 </div> 10212 `; 10213 $("#homepageOrderdownloader").html(built); 10214 } else {
10215 $(addToMainMenu).appendTo(".combinedMenuList"); 10216 $(listingMain).appendTo(".listingMain"); 10217 } 10218} 10219function buildMetadata(array, source) { 10220 var metadata = ""; 10221 var genres = ""; 10222 var actors = ""; 10223 var rating = '<div class="col-xs-2 p-10"></div>'; 10224 var sourceIcon = source === "jellyfin" ? "fish" : source; 10225 $.each(array.content, function (i, v) { 10226 // Normalize per-item source when coming from JellyStat or unknown 10227 var itemSource = source; 10228 try { 10229 if ( 10230 source === "jellystat" || 10231 (source !== "emby" && source !== "jellyfin") 10232 ) { 10233 if (v.tabName) { 10234 var tn = String(v.tabName).toLowerCase(); 10235 if (tn.indexOf("emby") !== -1) { 10236 itemSource = "emby"; 10237 } else if (tn.indexOf("jellyfin") !== -1) { 10238 itemSource = "jellyfin"; 10239 } 10240 } 10241 // Fallback inference from address if tabName did not resolve 10242 if ( 10243 (itemSource === source || itemSource === "jellystat") && 10244 v.address 10245 ) { 10246 var addr = String(v.address).toLowerCase(); 10247 if (addr.indexOf("jellyfin") !== -1) { 10248 itemSource = "jellyfin"; 10249 } else if (addr.indexOf("emby") !== -1) { 10250 itemSource = "emby"; 10251 } 10252 } 10253 } 10254 } catch (e) {} 10255 // Normalize to lowercase to avoid casing issues like 'Emby' 10256 itemSource = (itemSource || "").toString().toLowerCase(); 10257 var hasActor = typeof v.metadata.actors !== "string" ? true : false; 10258 var hasGenre = typeof v.metadata.genres !== "string" ? true : false; 10259 if (hasActor) { 10260 $.each(v.metadata.actors, function (i, v) { 10261 actors += 10262 '<div class="item lazyload recent-poster" data-src="' + 10263 v.thumb.replace("http://", "https://") + 10264 '" alt="' + 10265 v.name + 10266 '" ><span class="elip recent-title p-a-5">' + 10267 v.name + 10268 '<br><small class="font-light">' + 10269 v.role + 10270 "</small></span></div>"; 10271 }); 10272 } 10273 if (hasGenre) { 10274 $.each(v.metadata.genres, function (i, v) { 10275 genres += '<span class="badge bg-org m-r-10">' + v + "</span>"; 10276 }); 10277 } 10278 if (v.metadata.rating) { 10279 var ratingRound = Math.ceil(v.metadata.rating) * 10; 10280 rating = 10281 `<div class="col-xs-2 p-10"><div data-label="` + 10282 v.metadata.rating * 10 + 10283 `%" class="css-bar css-bar-` + 10284 Math.ceil(ratingRound / 5) * 5 + 10285 ` css-bar-sm m-b-0 css-bar-info"><img src="plugins/images/rotten.png" class="nowPlayingUserThumb" alt="User"></div></div>`; 10286 } 10287 var seconds = v.metadata.duration / 1000; // or "2000" 10288 seconds = parseInt(seconds); //because moment js dont know to handle number in string format 10289 var format = 10290 Math.floor(moment.duration(seconds, "seconds").asHours()) + 10291 ":" + 10292 moment.duration(seconds, "seconds").minutes() + 10293 ":" + 10294 moment.duration(seconds, "seconds").seconds(); 10295 // Build icon HTML: use image for Emby to avoid missing MDI glyphs; keep MDI for others 10296 var sourceIconHtml = ""; 10297 var iconChoice = itemSource === "jellyfin" ? "fish" : itemSource; 10298 if (itemSource === "emby") { 10299 sourceIconHtml = 10300 '<img src="plugins/images/tabs/emby.png" class="metadata-source-image" style="height:24px;width:24px;" />'; 10301 } else { 10302 sourceIconHtml = '<i class="fa mdi mdi-' + iconChoice + ' fa-2x"></i>'; 10303 } 10304 metadata = 10305 ` 10306 <div class="white-box m-b-0"> 10307 <div class="user-bg lazyload" data-src="` + 10308 v.nowPlayingImageURL + 10309 `"> 10310 ` + 10311 rating + 10312 ` 10313 <div class="col-xs-10"> 10314 <h2 class="m-b-0 font-medium pull-right text-right"> 10315 ` + 10316 v.title + 10317 `<button type="button" class="btn bg-org btn-circle close-popup m-l-10"><i class="fa fa-times"></i> </button><br> 10318 <small class="m-t-0 text-white">` + 10319 v.metadata.tagline + 10320 `</small><br> 10321 <button class="btn waves-effect waves-light openTab bg-` + 10322 itemSource + 10323 `" type="button" data-tab-name="` + 10324 cleanClass(v.tabName) + 10325 `" data-type="` + 10326 v.type + 10327 `" data-open-tab="` + 10328 v.openTab + 10329 `" data-url="` + 10330 v.address + 10331 `" href="javascript:void(0);"> ` + 10332 sourceIconHtml + 10333 ` </button> 10334 ` + 10335 buildYoutubeLink(v.title + " " + v.metadata.year + " " + v.type) + 10336 ` 10337 </h2> 10338 </div> 10339 <div class="genre-list p-10">` + 10340 genres + 10341 `</div> 10342 </div> 10343 </div> 10344 <div class="panel panel-info p-b-0 p-t-0"> 10345 <div class="panel-body p-b-0 p-t-0 m-b-0"> 10346 <div class="p-20 text-center"> 10347 <p class="">` + 10348 v.metadata.summary + 10349 `</p> 10350 </div> 10351 <div class="row"> 10352 <div class="col-lg-12"> 10353 <div class="owl-carousel owl-theme metadata-actors p-b-10">` + 10354 actors + 10355 `</div> 10356 </div>
10357 </div> 10358 </div> 10359 </div> 10360 10361 `; 10362 }); 10363 return metadata; 10364} 10365function buildYoutubeLink(title) { 10366 if (title) { 10367 var str = createRandomString(10); 10368 return ( 10369 ` 10370 <button class="btn btn-youtube waves-effect waves-light" type="button" onclick="youtubeCheck('` + 10371 escape(title) + 10372 `','` + 10373 str + 10374 `')"> <i class="fa fa-youtube-play fa-2x"></i> </button> 10375 <a class="hidden inline-popups ` + 10376 str + 10377 `" href="#open-youtube" data-effect="mfp-zoom-out"></a> 10378 ` 10379 ); 10380 } 10381} 10382function buildPVRLink(href, ico = "", frame = "", showLink = true) { 10383 if (href && showLink) { 10384 var styleOverride = `width:55px;height:44px;background-image: url(${ico});background-repeat:no-repeat;background-size:25px;background-position:center;`; 10385 if (frame) { 10386 return ` 10387 <div class="btn btn-inverse waves-effect waves-light" type="button" onclick="tabActions(event,'${frame}','${href}');" style="${styleOverride}"></div> 10388 `; 10389 } else { 10390 return ` 10391 <div class="btn btn-inverse waves-effect waves-light" type="button" onclick="window.open('${href}')" style="${styleOverride}"></div> 10392 `; 10393 } 10394 } else { 10395 return ` 10396 10397 `; 10398 } 10399} 10400function buildCalendarMetadata(array) { 10401 var metadata = ""; 10402 var genres = ""; 10403 var actors = ""; 10404 var rating = '<div class="col-xs-2 p-10"></div>'; 10405 var hasGenre = typeof array.genres !== "string" ? true : false; 10406 if (hasGenre) { 10407 $.each(array.genres, function (i, v) { 10408 genres += '<span class="badge bg-org m-r-10">' + v + "</span>"; 10409 }); 10410 } 10411 if (array.ratings) { 10412 var ratingRound = Math.ceil(array.ratings) * 10; 10413 rating = 10414 `<div class="col-xs-2 p-10"><div data-label="` + 10415 array.ratings * 10 + 10416 `%" class="css-bar css-bar-` + 10417 Math.ceil(ratingRound / 5) * 5 + 10418 ` css-bar-sm m-b-0 css-bar-info"><img src="plugins/images/rotten.png" class="nowPlayingUserThumb" alt="User"></div></div>`; 10419 } 10420 var seconds = array.runtime / 1000; // or "2000" 10421 seconds = parseInt(seconds); //because moment js dont know to handle number in string format 10422 var format = 10423 Math.floor(moment.duration(seconds, "seconds").asHours()) + 10424 ":" + 10425 moment.duration(seconds, "seconds").minutes() + 10426 ":" + 10427 moment.duration(seconds, "seconds").seconds(); 10428 metadata = 10429 ` 10430 <div class="white-box m-b-0"> 10431 <div class="user-bg lazyload" data-src="` + 10432 array.image + 10433 `"> 10434 ` + 10435 rating + 10436 ` 10437 <div class="col-xs-10"> 10438 <h2 class="m-b-0 font-medium pull-right text-right"> 10439 ` + 10440 array.topTitle + 10441 `<button type="button" class="btn bg-org btn-circle close-popup m-l-10"><i class="fa fa-times"></i> </button><br> 10442 <small class="m-t-0 text-white">` + 10443 array.bottomTitle + 10444 `</small><br> 10445 ` + 10446 buildPVRLink(array.href, array.icon, array.frame, array.showLink) + 10447 buildYoutubeLink(array.topTitle) + 10448 ` 10449 </h2> 10450 </div> 10451 <div class="genre-list p-10">` + 10452 genres + 10453 `</div> 10454 </div> 10455 </div> 10456 <div class="panel panel-info p-b-0 p-t-0"> 10457 <div class="panel-body p-b-0 p-t-0 m-b-0"> 10458 <div class="p-20 text-center"> 10459 <p class="">` + 10460 array.overview + 10461 `</p> 10462 </div> 10463 </div> 10464 </div> 10465 10466 `; 10467 return metadata; 10468} 10469function buildHealthChecks(array) { 10470 if (array === false) { 10471 return ""; 10472 } 10473 var checks = 10474 typeof array.content.checks !== "undefined" 10475 ? array.content.checks.length 10476 : false; 10477 return checks 10478 ? ` 10479 <div id="allHealthChecks" class="m-b-30"> 10480 <div class="el-element-overlay row"> 10481 <div class="col-md-12"> 10482 <h4 class="pull-left homepage-element-title"><span lang="en">Health Checks</span> : </h4><h4 class="pull-left"> <span class="label label-info m-l-20 checkbox-circle good-health-checks mouse" onclick="homepageHealthChecks()">` + 10483 checks + 10484 `</span></h4> 10485 <hr class="hidden-xs"> 10486 </div> 10487 <div class="clearfix"></div> 10488 <!-- .cards --> 10489 <div class="healthCheckCards"> 10490 ` + 10491 buildHealthChecksItem(array) + 10492 ` 10493 </div> 10494 <!-- /.cards--> 10495 </div> 10496 </div> 10497 <div class="clearfix"></div> 10498 ` 10499 : ""; 10500} 10501function buildPihole(array) { 10502 if (array === false) { 10503 return ""; 10504 } 10505 var html = ` 10506 <div id="allPihole"> 10507 <div class="el-element-overlay row">`; 10508 if (array["options"]["title"]) { 10509 html += ` 10510 <div class="col-md-12"> 10511 <h4 class="pull-left homepage-element-title"><span lang="en">
10511Pi-hole</span> : </h4><h4 class="pull-left"> </h4> 10512 <hr class="hidden-xs ml-2"> 10513 </div> 10514 <div class="clearfix"></div> 10515 `; 10516 } 10517 html += 10518 ` 10519 <div class="piholeCards col-sm-12 my-3"> 10520 ` + 10521 buildPiholeItem(array) + 10522 ` 10523 </div> 10524 </div> 10525 </div> 10526 `; 10527 return array ? html : ""; 10528} 10529function buildAdGuard(array) { 10530 if (array === false) { 10531 return ""; 10532 } 10533 var html = ` 10534 <div id="allAdGuard"> 10535 <div class="el-element-overlay row">`; 10536 if (array["options"]["title"]) { 10537 html += ` 10538 <div class="col-md-12"> 10539 <h4 class="pull-left homepage-element-title"><span lang="en">AdGuard Home</span> : </h4><h4 class="pull-left"> </h4> 10540 <hr class="hidden-xs ml-2"> 10541 </div> 10542 <div class="clearfix"></div> 10543 `; 10544 } 10545 html += 10546 ` 10547 <div class="adguardCards col-sm-12 my-3"> 10548 ` + 10549 buildAdGuardItem(array) + 10550 ` 10551 </div> 10552 </div> 10553 </div> 10554 `; 10555 return array ? html : ""; 10556} 10557function buildUnifi(array) { 10558 if (array === false) { 10559 return ""; 10560 } 10561 var items = 10562 typeof array.content.unifi.data !== "undefined" 10563 ? array.content.unifi.data.length 10564 : false; 10565 return items 10566 ? ` 10567 <div id="allUnifi"> 10568 10569 <!-- <div class="row"> 10570 <div class="col-md-12"> 10571 <div class="white-box"> 10572 <h3 class="box-title">Unifi</h3> 10573 ` + 10574 buildUnifiItemNew(array.content.unifi.data) + 10575 ` 10576 </div> 10577 </div> 10578 </div> --> 10579 10580 10581 <div class="row"> 10582 <div class="col-md-12"> 10583 <h4 class="pull-left homepage-element-title"><span lang="en">UniFi</span> : </h4><h4 class="pull-left"> </h4> 10584 <hr class="hidden-xs"> 10585 </div> 10586 <div class="clearfix"></div> 10587 <!-- .cards --> 10588 <div class="unifiCards"> 10589 ` + 10590 buildUnifiItem(array.content.unifi.data) + 10591 ` 10592 </div> 10593 <!-- /.cards--> 10594 </div> 10595 </div> 10596 <div class="clearfix"></div> 10597 ` 10598 : ""; 10599} 10600function buildUnifiItemNew(array) { 10601 let items = ""; 10602 let count = 0; 10603 let navTabItems = ""; 10604 $.each(array, function (i, v) { 10605 let name = typeof v.subsystem !== "undefined" ? v.subsystem : ""; 10606 let stats = {}; 10607 let panelColor = ""; 10608 let proceed = v.status == "ok"; 10609 let active = count <= 0 ? "active in" : ""; 10610 let icon = "ti-home"; 10611 count++; 10612 switch (name) { 10613 case "wlan": 10614 panelColor = "info"; 10615 stats["clients"] = v.num_user; 10616 stats["tx"] = v["tx_bytes-r"]; 10617 stats["rx"] = v["rx_bytes-r"]; 10618 break; 10619 case "wan": 10620 panelColor = "success"; 10621 stats["IP"] = v.wan_ip; 10622 stats["tx"] = v["tx_bytes-r"]; 10623 stats["rx"] = v["rx_bytes-r"]; 10624 break; 10625 case "lan": 10626 panelColor = "primary"; 10627 stats["clients"] = v.num_user; 10628 stats["tx"] = v["tx_bytes-r"]; 10629 stats["rx"] = v["rx_bytes-r"]; 10630 break; 10631 case "www": 10632 panelColor = "warning"; 10633 stats["drops"] = v.drops; 10634 stats["latency"] = v.latency; 10635 stats["uptime"] = v.uptime; 10636 stats["tx"] = v["tx_bytes-r"]; 10637 stats["rx"] = v["rx_bytes-r"]; 10638 break; 10639 case "vpn": 10640 panelColor = "inverse"; 10641 stats["clients"] = v.remote_user_num_active; 10642 stats["tx"] = v.remote_user_tx_bytes; 10643 stats["rx"] = v.remote_user_rx_bytes; 10644 break; 10645 default: 10646 } 10647 var statItems = ""; 10648 if (proceed) { 10649 navTabItems += `<li role="presentation" class="${active}"><a href="#unifi-${name}" aria-controls="unifi-${name}" role="tab" data-toggle="tab" aria-expanded="false"><span class="visible-xs"><i class="${icon}"></i></span><span class="hidden-xs text-uppercase"> ${name}</span></a></li>`; 10650 $.each(stats, function (istat, vstat) { 10651 statItems += ` 10652 <div class="stat-item"> 10653 <h6 class="text-uppercase">${istat}</h6> 10654 <b>${vstat}</b> 10655 </div> 10656 `; 10657 }); 10658 items += ` 10659 <div role="tabpanel" class="tab-pane fade ${active}" id="unifi-${name}"> 10660 <div class="col-md-12">${statItems}</div> 10661 <div class="clearfix"></div> 10662 </div> 10663 `; 10664 } 10665 }); 10666 let navTabs = `<ul class="nav customtab nav-tabs" role="tablist">${navTabItems}</ul>`; 10667 items = `<div class="tab-content">${items}</div>`; 10668 return navTabs + items; 10669} 10670function buildUnifiItem(array) { 10671 var items = ""; 10672 $.each(array, function (i, v) { 10673 var name = typeof v.subsystem !== "undefined" ? v.subsystem : ""; 10674 var stats = {}; 10675 var panelColor = ""; 10676 var proceed = v.status == "ok"; 10677 switch (name) { 10678 case "wlan": 10679 panelColor = "info"; 10680 stats["clients"] = v.num_user;
10681 stats["tx"] = v["tx_bytes-r"]; 10682 stats["rx"] = v["rx_bytes-r"]; 10683 break; 10684 case "wan": 10685 panelColor = "success"; 10686 stats["IP"] = v.wan_ip; 10687 stats["tx"] = v["tx_bytes-r"]; 10688 stats["rx"] = v["rx_bytes-r"]; 10689 break; 10690 case "lan": 10691 panelColor = "primary"; 10692 stats["clients"] = v.num_user; 10693 stats["tx"] = v["tx_bytes-r"]; 10694 stats["rx"] = v["rx_bytes-r"]; 10695 break; 10696 case "www": 10697 panelColor = "warning"; 10698 stats["drops"] = v.drops; 10699 stats["latency"] = v.latency; 10700 stats["uptime"] = v.uptime; 10701 stats["tx"] = v["tx_bytes-r"]; 10702 stats["rx"] = v["rx_bytes-r"]; 10703 break; 10704 case "vpn": 10705 panelColor = "inverse"; 10706 stats["clients"] = v.remote_user_num_active; 10707 stats["tx"] = v.remote_user_tx_bytes; 10708 stats["rx"] = v.remote_user_rx_bytes; 10709 break; 10710 default: 10711 } 10712 var statItems = ""; 10713 if (proceed) { 10714 $.each(stats, function (istat, vstat) { 10715 statItems += ` 10716 <div class="stat-item"> 10717 <h6 class="text-uppercase">${istat}</h6> 10718 <b>${vstat}</b> 10719 </div> 10720 `; 10721 }); 10722 items += ` 10723 <div class="col-lg-4 col-md-6 col-center"> 10724 <div class="panel panel-${panelColor}"> 10725 <div class="panel-heading"> <span class="text-uppercase">${name}</span> 10726 <div class="pull-right"><a href="#" data-perform="panel-collapse"><i class="ti-minus"></i></a></div> 10727 </div> 10728 <div class="panel-wrapper collapse in" aria-expanded="true"> 10729 <div class="panel-body"> 10730 ${statItems} 10731 </div> 10732 </div> 10733 </div> 10734 </div> 10735 `; 10736 } 10737 }); 10738 return items; 10739} 10740function healthCheckIcon(tags) { 10741 var allTags = tags.split(" "); 10742 var useIcon = ""; 10743 $.each(allTags, function (i, v) { 10744 //check for image 10745 var file = 10746 v.substring(v.lastIndexOf(".") + 1, v.length).toLowerCase() || 10747 v.toLowerCase(); 10748 switch (file) { 10749 case "png": 10750 case "jpg": 10751 case "jpeg": 10752 case "gif": 10753 useIcon = 10754 '<img class="lazyload loginTitle" data-src="' + v + '"> '; 10755 break; 10756 default: 10757 } 10758 }); 10759 return useIcon; 10760} 10761function buildHealthChecksItem(array) { 10762 var checks = ""; 10763 $.each(array.content.checks, function (i, v) { 10764 var hasIcon = healthCheckIcon(v.tags); 10765 v.name = v.name ? v.name : "New Item"; 10766 v.desc = 10767 array.options.desc && v.desc ? "<h5>Notes: " + v.desc + "</h5>" : ""; 10768 switch (v.status) { 10769 case "up": 10770 var statusColor = "success"; 10771 var statusIcon = "ti-link text-success"; 10772 var nextPing = moment 10773 .utc(v.next_ping, "YYYY-MM-DD hh:mm[Z]") 10774 .local() 10775 .fromNow(); 10776 var lastPing = moment 10777 .utc(v.last_ping, "YYYY-MM-DD hh:mm[Z]") 10778 .local() 10779 .fromNow(); 10780 break; 10781 case "down": 10782 var statusColor = "danger animated-3 loop-animation flash"; 10783 var statusIcon = "ti-unlink text-danger"; 10784 var nextPing = "Service Down"; 10785 var lastPing = moment 10786 .utc(v.last_ping, "YYYY-MM-DD hh:mm[Z]") 10787 .local() 10788 .fromNow(); 10789 break; 10790 case "new": 10791 var statusColor = "info"; 10792 var statusIcon = "ti-time text-info"; 10793 var nextPing = "Waiting..."; 10794 var lastPing = "n/a"; 10795 break; 10796 case "grace": 10797 var statusColor = "warning"; 10798 var statusIcon = "ti-alert text-warning"; 10799 var nextPing = moment 10800 .utc(v.next_ping, "YYYY-MM-DD hh:mm[Z]") 10801 .local() 10802 .fromNow(); 10803 var lastPing = "Missed"; 10804 break; 10805 case "paused": 10806 var statusColor = "primary"; 10807 var statusIcon = "ti-control-pause text-primary"; 10808 var nextPing = "Paused"; 10809 var lastPing = moment 10810 .utc(v.last_ping, "YYYY-MM-DD hh:mm[Z]") 10811 .local() 10812 .fromNow(); 10813 break; 10814 default: 10815 var statusColor = "warning"; 10816 var statusIcon = "ti-timer text-warning"; 10817 var nextPing = "Waiting..."; 10818 var lastPing = "n/a"; 10819 } 10820 var tagPrimaryElem = "", 10821 tagSecondaryElem = ""; 10822 if (array.options.tags && v.tags) { 10823 v.tags = v.tags.split(" "); 10824 $.each(v.tags, function (key, value) { 10825 if (isURL(value)) { 10826 v.tags = arrayRemove(v.tags, value); 10827 } 10828 }); 10829 tagPrimaryElem = 10830 '<span class="pull-right mt-3 mr-2"><span class="label text-uppercase bg-' + 10831 statusColor.replace("animated-3 loop-animation flash", "") + 10832 ' label-rounded font-12">' + 10833 v.tags[0] + 10834 "</span></span>"; 10835 tagSecondaryElem = "<h5>Tags: "; 10836 tagSecondaryElem += v.tags 10837 .map((t) => { 10838 return t; 10839 }) 10840 .join(", "); 10841 tagSecondaryElem += "</h5>"; 10842 } 10843 checks += 10844 ` 10845 <div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-xs-12"> 10846 <div class="card bg-inverse text-white mb-3 showMoreHealth mouse" data-id="` + 10847 i + 10848 `"> 10849 <div class="card-body bg-org-alt pt-1 pb-1"> 10850 <div class="d-flex no-block align-items-center"> 10851 <div class="left-health bg-` + 10852 statusColor + 10853 `"></div> 10854 <div class="ml-1 w-100">
10855 <span class="pull-right mt-3 mb-2"><i class="` + 10856 statusIcon + 10857 ` font-20"></i></span> 10858 ` + 10859 tagPrimaryElem + 10860 ` 10861 <h3 class="d-flex no-block align-items-center mt-2 mb-2">` + 10862 hasIcon + 10863 v.name + 10864 `</h3> 10865 <div class="clearfix"></div> 10866 <div class="d-none showMoreHealthDiv-` + 10867 i + 10868 `"><h5>Last: ` + 10869 lastPing + 10870 `</h5><h5>Next: ` + 10871 nextPing + 10872 `</h5>` + 10873 v.desc + 10874 tagSecondaryElem + 10875 `</div> 10876 <div class="clearfix"></div> 10877 </div> 10878 </div> 10879 </div> 10880 </div> 10881 </div> 10882 `; 10883 }); 10884 return checks; 10885} 10886function isURL(str) { 10887 const pattern = new RegExp( 10888 "^(https?:\\/\\/)?" + // protocol 10889 "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name 10890 "((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address 10891 "(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path 10892 "(\\?[;&a-z\\d%_.~+=-]*)?" + // query string 10893 "(\\#[-a-z\\d_]*)?$", 10894 "i" 10895 ); // fragment locator 10896 return !!pattern.test(str); 10897} 10898function arrayRemove(arr, value) { 10899 return arr.filter(function (ele) { 10900 return ele != value; 10901 }); 10902} 10903function buildAdGuardItem(array) { 10904 var stats = ` 10905 <style> 10906 .bg-green { 10907 background-color: #00a65a !important; 10908 } 10909 10910 .bg-aqua { 10911 background-color: #00c0ef!important; 10912 } 10913 10914 .bg-yellow { 10915 background-color: #f39c12!important; 10916 } 10917 10918 .bg-red { 10919 background-color: #dd4b39!important; 10920 } 10921 10922 .adguard-stat { 10923 color: #fff !important; 10924 } 10925 10926 .adguard-stat .card-body h3 { 10927 font-size: 38px; 10928 font-weight: 700; 10929 } 10930 10931 .adguard-stat .card-body i { 10932 font-size: 5em; 10933 float: right; 10934 color: #ffffff6b; 10935 } 10936 10937 .inline-block { 10938 display: inline-block; 10939 } 10940 </style> 10941 `; 10942 var length = Object.keys(array["data"]).length; 10943 var combine = array["options"]["combine"]; 10944 var totalQueries = function (data) { 10945 var card = ` 10946 <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12"> 10947 <div class="card text-white mb-3 adguard-stat bg-green"> 10948 <div class="card-body"> 10949 <div class="inline-block"> 10950 <p class="d-inline mr-1">Total Queries</p>`; 10951 for (var key in data) { 10952 var e = data[key]; 10953 if (length > 1 && !combine) { 10954 card += `<p class="d-inline text-muted">(` + key + `)</p>`; 10955 } 10956 card += 10957 `<h3 data-toggle="tooltip" data-placement="right" title="` + 10958 key + 10959 `">` + 10960 e["num_dns_queries"].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + 10961 `</h3>`; 10962 } 10963 card += ` 10964 </div> 10965 <i class="fa fa-globe inline-block" aria-hidden="true"></i> 10966 </div> 10967 </div> 10968 </div> 10969 `; 10970 return card; 10971 }; 10972 var totalBlocked = function (data) { 10973 var card = ` 10974 <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12"> 10975 <div class="card bg-inverse text-white mb-3 adguard-stat bg-aqua"> 10976 <div class="card-body"> 10977 <div class="inline-block"> 10978 <p class="d-inline mr-1">Queries Blocked</p>`; 10979 for (var key in data) { 10980 var e = data[key]; 10981 if (length > 1 && !combine) { 10982 card += `<p class="d-inline text-muted">(${key})</p>`; 10983 } 10984 card += `<h3 data-toggle="tooltip" data-placement="right" title="${key}">${e[ 10985 "num_blocked_filtering" 10986 ] 10987 .toString() 10988 .replace(/\B(?=(\d{3})+(?!\d))/g, ",")}</h3>`; 10989 } 10990 card += ` 10991 </div> 10992 <i class="fa fa-hand-paper-o inline-block" aria-hidden="true"></i> 10993 </div> 10994 </div> 10995 </div> 10996 `; 10997 return card; 10998 }; 10999 var avgProcessingTime = function (data) { 11000 var card = ` 11001 <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12"> 11002 <div class="card bg-inverse text-white mb-3 adguard-stat bg-purple"> 11003 <div class="card-body"> 11004 <div class="inline-block"> 11005 <p class="d-inline mr-1">Avg Processing Time</p>`; 11006 for (var key in data) { 11007 var e = data[key]; 11008 if (length > 1 && !combine) { 11009 card += `<p class="d-inline text-muted">(${key})</p>`; 11010 } 11011 ms_time = parseFloat(e["avg_processing_time"]) * 1000; 11012 card += `<h3 data-toggle="tooltip" data-placement="right" title="${key}">${ms_time.toFixed( 11013 2 11014 )} ms</h3>`; 11015 } 11016 card += ` 11017 </div> 11018 <i class="fa fa-group inline-block" aria-hidden="true"></i> 11019 </div> 11020 </div> 11021 </div> 11022 `; 11023 return card; 11024 }; 11025 var domainsBlocked = function (data) { 11026 var card = ` 11027 <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12"> 11028 <div class="card bg-inverse text-white mb-3 adguard-stat bg-red"> 11029 <div class="card-body"> 11030 <div class="inline-block"> 11031 <p class="d-inline mr-1">Domains on Blocklist</p>`; 11032 for (var key in data) { 11033 var e = data[key]; 11034 if (length > 1 && !combine) { 11035 card += `<p class="d-inline text-muted">(${key})</p>`; 11036 } 11037 var total_domains_blocked = 0; 11038 for (var key in e["filters"]) { 11039 total_domains_blocked += parseFloat(e["filters"][key]["rules_count"]); 11040 } 11041 card += `<h3 data-toggle="tooltip" data-placement="right" title="${key}">${total_domains_blocked 11042 .toString() 11043 .replace(/\B(?=(\d{3})+(?!\d))/g, ",")}</h3>`; 11044 } 11045 card += ` 11046 </div> 11047 <i class="fa fa-list inline-block" aria-hidden="true"></i> 11048 </div> 11049 </div> 11050 </div> 11051 `; 11052 return card; 11053 }; 11054 var domainsBlocked = function (data) { 11055 var card = ` 11056 <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12"> 11057 <div class="card bg-inverse text-white mb-3 adguard-stat bg-red"> 11058 <div class="card-body"> 11059 <div class="inline-block"> 11060 <p class="d-inline mr-1">Domains on Blocklist</p>`; 11061 for (var key in data) { 11062 var e = data[key]; 11063 if (length > 1 && !combine) { 11064 card += `<p class="d-inline text-muted">(${key})</p>`; 11065 } 11066 var total_domains_blocked = 0; 11067 for (var key in e["filters"]) { 11068 total_domains_blocked += parseFloat(e["filters"][key]["rules_count"]); 11069 } 11070 total_domains_blocked += Object.keys(e["user_rules"]).length; 11071 card += `<h3 data-toggle="tooltip" data-placement="right" title="${key}">${total_domains_blocked 11072 .toString() 11073 .replace(/\B(?=(\d{3})+(?!\d))/g, ",")}</h3>`; 11074 } 11075 card += ` 11076 </div> 11077 <i class="fa fa-list inline-block" aria-hidden="true"></i> 11078 </div> 11079 </div> 11080 </div> 11081 `; 11082 return card; 11083 }; 11084 var percentBlocked = function (data) { 11085 var card = ` 11086 <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12"> 11087 <div class="card bg-inverse text-white mb-3 adguard-stat bg-yellow"> 11088 <div class="card-body"> 11089 <div class="inline-block"> 11090 <p class="d-inline mr-1">Percent Blocked</p>`; 11091 for (var key in data) { 11092 var e = data[key]; 11093 if (typeof e["FTLnotrunning"] == "undefined") { 11094 if (length > 1 && !combine) { 11095 card += `<p class="d-inline text-muted">(${key})</p>`; 11096 } 11097 var percent = 11098 100 * 11099 (parseFloat(e["num_blocked_filtering"]) / 11100 parseFloat(e["num_dns_queries"])); 11101 card += `<h3 data-toggle="tooltip" data-placement="right" title="${key}">${percent.toFixed( 11102 2 11103 )}%</h3>`; 11104 } 11105 } 11106 card += ` 11107 </div> 11108 <i class="fa fa-pie-chart inline-block" aria-hidden="true"></i> 11109 </div> 11110 </div> 11111 </div> 11112 `; 11113 return card; 11114 }; 11115 if (combine) { 11116 stats += '<div class="row">'; 11117 if (array["options"]["queries"]) {
11118 stats += totalQueries(array["data"]); 11119 } 11120 if (array["options"]["blocked_count"]) { 11121 stats += totalBlocked(array["data"]); 11122 } 11123 if (array["options"]["blocked_percent"]) { 11124 stats += percentBlocked(array["data"]); 11125 } 11126 if (array["options"]["processing_time"]) { 11127 stats += avgProcessingTime(array["data"]); 11128 } 11129 if (array["options"]["domain_count"]) { 11130 stats += domainsBlocked(array["filters"]); 11131 } 11132 stats += "</div>"; 11133 } else { 11134 for (var key in array["data"]) { 11135 var data = array["data"][key]; 11136 obj = {}; 11137 obj[key] = data; 11138 stats += '<div class="row">'; 11139 if (array["options"]["queries"]) { 11140 stats += totalQueries(array["data"]); 11141 } 11142 if (array["options"]["blocked_count"]) { 11143 stats += totalBlocked(array["data"]); 11144 } 11145 if (array["options"]["blocked_percent"]) { 11146 stats += percentBlocked(array["data"]); 11147 } 11148 if (array["options"]["processing_time"]) { 11149 stats += avgProcessingTime(array["data"]); 11150 } 11151 if (array["options"]["domain_count"]) { 11152 stats += domainsBlocked(array["filters"]); 11153 } 11154 stats += "</div>"; 11155 } 11156 } 11157 return stats; 11158} 11159 11160function buildPiholeItem(array) { 11161 var stats = ` 11162 <style> 11163 .bg-green { 11164 background-color: #00a65a !important; 11165 } 11166 11167 .bg-aqua { 11168 background-color: #00c0ef!important; 11169 } 11170 11171 .bg-yellow { 11172 background-color: #f39c12!important; 11173 } 11174 11175 .bg-red { 11176 background-color: #dd4b39!important; 11177 } 11178 11179 .pihole-stat { 11180 color: #fff !important; 11181 } 11182 11183 .pihole-stat .card-body h3 { 11184 font-size: 38px; 11185 font-weight: 700; 11186 } 11187 11188 .pihole-stat .card-body i { 11189 font-size: 5em; 11190 float: right; 11191 color: #ffffff6b; 11192 } 11193 11194 .inline-block { 11195 display: inline-block; 11196 } 11197 11198 ul.multi-column { 11199 column-count: 1; 11200 column-gap: 2em; 11201 } 11202 11203 @media (min-width: 650px) { 11204 ul.multi-column { 11205 column-count: 3; 11206 } 11207 } 11208 11209 @media (min-width: 1200px) { 11210 ul.multi-column { 11211 column-count: 5; 11212 } 11213 } 11214 </style> 11215 `; 11216 var length = Object.keys(array["data"]).length; 11217 var combine = array["options"]["combine"]; 11218 var totalQueries = function (data) { 11219 var card = ` 11220 <div class="col-lg-4 col-md-6 col-sm-6 col-xs-12"> 11221 <div class="card text-white mb-3 pihole-stat bg-green"> 11222 <div class="card-body"> 11223 <div class="inline-block"> 11224 <p class="d-inline mr-1">Total queries (last 24 hours)</p>`; 11225 for (var key in data) { 11226 var e = data[key]; 11227 if (typeof e["FTLnotrunning"] == "undefined") { 11228 if (length > 1 && !combine) { 11229 card += `<p class="d-inline text-muted">(` + key + `)</p>`; 11230 } 11231 let value = "Error"; 11232 if (e.length == undefined) { 11233 value = e["sum_queries"] 11234 .toString() 11235 .replace(/\B(?=(\d{3})+(?!\d))/g, ","); 11236 } 11237 card += 11238 `<h3 data-toggle="tooltip" data-placement="right" title="` + 11239 key + 11240 `">` + 11241 value + 11242 `</h3>`; 11243 } 11244 } 11245 card += ` 11246 </div> 11247 <i class="fa fa-globe inline-block" aria-hidden="true"></i> 11248 </div> 11249 </div> 11250 </div> 11251 `; 11252 return card; 11253 }; 11254 var totalBlocked = function (data) { 11255 var card = ` 11256 <div class="col-lg-4 col-md-6 col-sm-6 col-xs-12"> 11257 <div class="card bg-inverse text-white mb-3 pihole-stat bg-aqua"> 11258 <div class="card-body"> 11259 <div class="inline-block"> 11260 <p class="d-inline mr-1">Queries Blocked (last 24 hours)</p>`; 11261 for (var key in data) { 11262 var e = data[key]; 11263 if (typeof e["FTLnotrunning"] == "undefined") { 11264 if (length > 1 && !combine) { 11265 card += `<p class="d-inline text-muted">(${key})</p>`; 11266 } 11267 let value = "Error"; 11268 if (e.length == undefined) { 11269 value = e["sum_blocked"] 11270 .toString() 11271 .replace(/\B(?=(\d{3})+(?!\d))/g, ","); 11272 } 11273 card += 11274 `<h3 data-toggle="tooltip" data-placement="right" title="` + 11275 key + 11276 `">` + 11277 value + 11278 `</h3>`; 11279 } 11280 } 11281 card += ` 11282 </div> 11283 <i class="fa fa-hand-paper-o inline-block" aria-hidden="true"></i> 11284 </div> 11285 </div> 11286 </div> 11287 `; 11288 return card; 11289 }; 11290 var percentBlocked = function (data) { 11291 var card = ` 11292 <div class="col-lg-4 col-md-6 col-sm-6 col-xs-12"> 11293 <div class="card bg-inverse text-white mb-3 pihole-stat bg-yellow"> 11294 <div class="card-body"> 11295 <div class="inline-block"> 11296 <p class="d-inline mr-1">Percent Blocked (last 24 hours)</p>`; 11297 for (var key in data) { 11298 var e = data[key]; 11299 if (typeof e["FTLnotrunning"] == "undefined") { 11300 if (length > 1 && !combine) { 11301 card += `<p class="d-inline text-muted">(${key})</p>`; 11302 } 11303 let value = "Error"; 11304 if (e.length == undefined) { 11305 value = e["percent_blocked"].toFixed(1); 11306 } 11307 card += 11308 `<h3 data-toggle="tooltip" data-placement="right" title="` + 11309 key + 11310 `">` + 11311 value + 11312 `</h3>`; 11313 } 11314 } 11315 card += ` 11316 </div> 11317 <i class="fa fa-pie-chart inline-block" aria-hidden="true"></i> 11318 </div> 11319 </div> 11320 </div> 11321 `; 11322 return card; 11323 }; 11324 var domainsBlocked = function (data) { 11325 var card = ` 11326 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> 11327 <div class="card bg-inverse text-white mb-3 pihole-stat bg-red"> 11328 <div class="card-body"> 11329 <div class="inline-block"> 11330 <p class="d-inline mr-1">Domains on Blocklist (last 24 hours)</p>`; 11331 for (var key in data) { 11332 var e = data[key]; 11333 if (typeof e["FTLnotrunning"] == "undefined") { 11334 if (length > 1 && !combine) { 11335 card += `<p class="d-inline text-muted">(${key})</p>`; 11336 } 11337 let value = "Error"; 11338 value = e["domains_being_blocked"] 11339 .map(function (x) { 11340 return `<li>${x.toString()}</li>`; 11341 }) 11342 .join(""); 11343 card += 11344 `<ul class="multi-column" data-toggle="tooltip" title="` + 11345 key + 11346 `">` + 11347 value + 11348 `</ul>`; 11349 } 11350 } 11351 card += ` 11352 </div> 11353 <i class="fa fa-list inline-block" aria-hidden="true"></i> 11354 </div> 11355 </div> 11356 </div> 11357 `; 11358 return card; 11359 }; 11360 11361 if (combine) { 11362 stats += '<div class="row">';
11363 stats += totalQueries(array["data"]); 11364 stats += totalBlocked(array["data"]); 11365 stats += percentBlocked(array["data"]); 11366 stats += domainsBlocked(array["data"]); 11367 stats += "</div>"; 11368 } else { 11369 for (var key in array["data"]) { 11370 var data = array["data"][key]; 11371 obj = {}; 11372 obj[key] = data; 11373 stats += '<div class="row">'; 11374 stats += totalQueries(obj); 11375 stats += totalBlocked(obj); 11376 stats += percentBlocked(obj); 11377 stats += domainsBlocked(obj); 11378 stats += "</div>"; 11379 } 11380 } 11381 return stats; 11382} 11383function homepagePihole(timeout) { 11384 var timeout = 11385 typeof timeout !== "undefined" 11386 ? timeout 11387 : activeInfo.settings.homepage.refresh.homepagePiholeRefresh; 11388 organizrAPI2("GET", "api/v2/homepage/pihole/stats") 11389 .success(function (data) { 11390 try { 11391 let response = data.response; 11392 document.getElementById("homepageOrderPihole").innerHTML = ""; 11393 if (response.data !== null) { 11394 buildPihole(response.data); 11395 $("#homepageOrderPihole").html(buildPihole(response.data)); 11396 } 11397 } catch (e) { 11398 organizrCatchError(e, data); 11399 } 11400 }) 11401 .fail(function (xhr) { 11402 OrganizrApiError(xhr); 11403 }); 11404 let timeoutTitle = "PiHole-Homepage"; 11405 if (typeof timeouts[timeoutTitle] !== "undefined") { 11406 clearTimeout(timeouts[timeoutTitle]); 11407 } 11408 timeouts[timeoutTitle] = setTimeout(function () { 11409 homepagePihole(timeout); 11410 }, timeout); 11411 delete timeout; 11412} 11413function homepageAdGuard(timeout) { 11414 var timeout = 11415 typeof timeout !== "undefined" 11416 ? timeout 11417 : activeInfo.settings.homepage.refresh.homepageAdGuardRefresh; 11418 organizrAPI2("GET", "api/v2/homepage/adguard/stats") 11419 .success(function (data) { 11420 try { 11421 let response = data.response; 11422 document.getElementById("homepageOrderAdGuard").innerHTML = ""; 11423 if (response.data !== null) { 11424 buildAdGuard(response.data); 11425 $("#homepageOrderAdGuard").html(buildAdGuard(response.data)); 11426 } 11427 } catch (e) { 11428 organizrCatchError(e, data); 11429 } 11430 }) 11431 .fail(function (xhr) { 11432 OrganizrApiError(xhr); 11433 }); 11434 let timeoutTitle = "AdGuard-Homepage"; 11435 if (typeof timeouts[timeoutTitle] !== "undefined") { 11436 clearTimeout(timeouts[timeoutTitle]); 11437 } 11438 timeouts[timeoutTitle] = setTimeout(function () { 11439 homepageAdGuard(timeout); 11440 }, timeout); 11441 delete timeout; 11442} 11443function homepageHealthChecks(tags, timeout) { 11444 tags = 11445 typeof tags !== "undefined" 11446 ? tags 11447 : activeInfo.settings.homepage.options.healthChecksTags; 11448 if (tags == "") { 11449 var apiUrl = "api/v2/homepage/healthchecks"; 11450 } else { 11451 var apiUrl = "api/v2/homepage/healthchecks/" + tags; 11452 } 11453 timeout = 11454 typeof timeout !== "undefined" 11455 ? timeout 11456 : activeInfo.settings.homepage.refresh.homepageHealthChecksRefresh; 11457 organizrAPI2("GET", apiUrl) 11458 .success(function (data) { 11459 try { 11460 var response = data.response; 11461 document.getElementById("homepageOrderhealthchecks").innerHTML = ""; 11462 if (response.data !== null) { 11463 $("#homepageOrderhealthchecks").html( 11464 buildHealthChecks(response.data) 11465 ); 11466 } 11467 } catch (e) { 11468 organizrCatchError(e, data); 11469 } 11470 }) 11471 .fail(function (xhr) { 11472 OrganizrApiError(xhr); 11473 }); 11474 let timeoutTitle = "HealthChecks-Homepage"; 11475 if (typeof timeouts[timeoutTitle] !== "undefined") { 11476 clearTimeout(timeouts[timeoutTitle]); 11477 } 11478 timeouts[timeoutTitle] = setTimeout(function () { 11479 homepageHealthChecks(tags, timeout); 11480 }, timeout); 11481 delete timeout; 11482} 11483function homepageUnifi(timeout) { 11484 var timeout = 11485 typeof timeout !== "undefined" 11486 ? timeout 11487 : activeInfo.settings.homepage.refresh.homepageUnifiRefresh; 11488 organizrAPI2("GET", "api/v2/homepage/unifi/data") 11489 .success(function (data) { 11490 try { 11491 let response = data.response; 11492 document.getElementById("homepageOrderunifi").innerHTML = ""; 11493 if (response.data !== null) { 11494 $("#homepageOrderunifi").html(buildUnifi(response.data)); 11495 } 11496 } catch (e) { 11497 organizrCatchError(e, data); 11498 } 11499 }) 11500 .fail(function (xhr) { 11501 OrganizrApiError(xhr); 11502 }); 11503 var timeoutTitle = "Unifi-Homepage"; 11504 if (typeof timeouts[timeoutTitle] !== "undefined") { 11505 clearTimeout(timeouts[timeoutTitle]); 11506 } 11507 timeouts[timeoutTitle] = setTimeout(function () { 11508 homepageUnifi(timeout); 11509 }, timeout); 11510 delete timeout; 11511} 11512function homepageDownloader(type, timeout) { 11513 var timeout = 11514 typeof timeout !== "undefined" 11515 ? timeout 11516 : activeInfo.settings.homepage.refresh.homepageDownloadRefresh; 11517 switch (type) { 11518 case "jdownloader": 11519 var action = "getJdownloader"; 11520 break; 11521 case "sabnzbd": 11522 var action = "getSabnzbd"; 11523 break; 11524 case "nzbget": 11525 var action = "getNzbget"; 11526 break; 11527 case "transmission": 11528 var action = "getTransmission"; 11529 break; 11530 case "sonarr": 11531 var action = "getSonarrQueue"; 11532 break; 11533 case "radarr": 11534 var action = "getRadarrQueue"; 11535 break; 11536 case "qBittorrent": 11537 var action = "getqBittorrent"; 11538 break; 11539 case "deluge": 11540 var action = "getDeluge"; 11541 break; 11542 case "rTorrent": 11543 var action = "getrTorrent"; 11544 break; 11545 case "utorrent": 11546 var action = "getutorrent"; 11547 break; 11548 default: 11549 } 11550 let lowerType = type.toLowerCase();
11551 organizrAPI2("GET", "api/v2/homepage/" + lowerType + "/queue") 11552 .success(function (data) { 11553 try { 11554 let response = data.response; 11555 if (response.data !== null) { 11556 buildDownloaderItem(response.data, type); 11557 } 11558 } catch (e) { 11559 organizrCatchError(e, data); 11560 } 11561 }) 11562 .fail(function (xhr) { 11563 OrganizrApiError(xhr); 11564 }); 11565 let timeoutTitle = type + "-Downloader-Homepage"; 11566 if (typeof timeouts[timeoutTitle] !== "undefined") { 11567 clearTimeout(timeouts[timeoutTitle]); 11568 } 11569 timeouts[timeoutTitle] = setTimeout(function () { 11570 homepageDownloader(type, timeout); 11571 }, timeout); 11572 delete timeout; 11573} 11574function homepageStream(type, timeout) { 11575 var timeout = 11576 typeof timeout !== "undefined" 11577 ? timeout 11578 : activeInfo.settings.homepage.refresh.homepageStreamRefresh; 11579 organizrAPI2("GET", "api/v2/homepage/" + type + "/streams") 11580 .success(function (data) { 11581 try { 11582 let response = data.response; 11583 document.getElementById( 11584 "homepageOrder" + type + "nowplaying" 11585 ).innerHTML = ""; 11586 $("#homepageOrder" + type + "nowplaying").html( 11587 buildStream(response.data, type) 11588 ); 11589 } catch (e) { 11590 organizrCatchError(e, data); 11591 } 11592 }) 11593 .fail(function (xhr) { 11594 OrganizrApiError(xhr); 11595 }); 11596 let timeoutTitle = type + "-Stream-Homepage"; 11597 if (typeof timeouts[timeoutTitle] !== "undefined") { 11598 clearTimeout(timeouts[timeoutTitle]); 11599 } 11600 timeouts[timeoutTitle] = setTimeout(function () { 11601 homepageStream(type, timeout); 11602 }, timeout); 11603 delete timeout; 11604} 11605function homepageRecent(type, timeout) { 11606 var timeout = 11607 typeof timeout !== "undefined" 11608 ? timeout 11609 : activeInfo.settings.homepage.refresh.homepageRecentRefresh; 11610 switch (type) { 11611 case "plex": 11612 var action = "getPlexRecent"; 11613 break; 11614 case "emby": 11615 case "jellyfin": 11616 var action = "getEmbyRecent"; 11617 break; 11618 default: 11619 } 11620 organizrAPI2("GET", "api/v2/homepage/" + type + "/recent") 11621 .success(function (data) { 11622 try { 11623 let response = data.response; 11624 document.getElementById("homepageOrder" + type + "recent").innerHTML = 11625 ""; 11626 $("." + type + "-recent").trigger("destroy.owl.carousel"); 11627 $("#homepageOrder" + type + "recent").html( 11628 buildRecent(response.data, type) 11629 ); 11630 $(".recent-items").owlCarousel({ 11631 nav: false, 11632 autoplay: false, 11633 dots: false, 11634 margin: 10, 11635 autoWidth: true, 11636 items: 4, 11637 }); 11638 } catch (e) { 11639 organizrCatchError(e, data); 11640 } 11641 }) 11642 .fail(function (xhr) { 11643 OrganizrApiError(xhr); 11644 }); 11645 let timeoutTitle = type + "-Recent-Homepage"; 11646 if (typeof timeouts[timeoutTitle] !== "undefined") { 11647 clearTimeout(timeouts[timeoutTitle]); 11648 } 11649 timeouts[timeoutTitle] = setTimeout(function () { 11650 homepageRecent(type, timeout); 11651 }, timeout); 11652 delete timeout; 11653} 11654function homepagePlaylist(type, timeout = 30000) { 11655 organizrAPI2("GET", "api/v2/homepage/" + type + "/playlists") 11656 .success(function (data) { 11657 try { 11658 let response = data.response; 11659 document.getElementById("homepageOrder" + type + "playlist").innerHTML = 11660 ""; 11661 $("#homepageOrder" + type + "playlist").html( 11662 buildPlaylist(response.data, type) 11663 ); 11664 $(".playlist-items").owlCarousel({ 11665 nav: false, 11666 autoplay: false, 11667 dots: false, 11668 margin: 10, 11669 autoWidth: true, 11670 items: 4, 11671 }); 11672 } catch (e) { 11673 organizrCatchError(e, data); 11674 } 11675 }) 11676 .fail(function (xhr) { 11677 OrganizrApiError(xhr); 11678 }); 11679} 11680function defaultRequestFilter(service) { 11681 switch (service) { 11682 case "ombi": 11683 var defaultFilter = { 11684 "request-filter-approved-ombi": 11685 activeInfo.settings.homepage.ombi.ombiDefaultFilterApproved, 11686 "request-filter-unapproved-ombi": 11687 activeInfo.settings.homepage.ombi.ombiDefaultFilterUnapproved, 11688 "request-filter-available-ombi": 11689 activeInfo.settings.homepage.ombi.ombiDefaultFilterAvailable, 11690 "request-filter-unavailable-ombi": 11691 activeInfo.settings.homepage.ombi.ombiDefaultFilterUnavailable, 11692 "request-filter-denied-ombi": 11693 activeInfo.settings.homepage.ombi.ombiDefaultFilterDenied, 11694 }; 11695 $.each(defaultFilter, function (i, v) { 11696 if (v == false) { 11697 $("#" + i).click(); 11698 } 11699 }); 11700 case "overseerr": 11701 var defaultFilter = { 11702 "request-filter-approved-overseerr": 11703 activeInfo.settings.homepage.overseerr.overseerrDefaultFilterApproved, 11704 "request-filter-unapproved-overseerr": 11705 activeInfo.settings.homepage.overseerr 11706 .overseerrDefaultFilterUnapproved, 11707 "request-filter-available-overseerr": 11708 activeInfo.settings.homepage.overseerr 11709 .overseerrDefaultFilterAvailable, 11710 "request-filter-unavailable-overseerr": 11711 activeInfo.settings.homepage.overseerr 11712 .overseerrDefaultFilterUnavailable, 11713 "request-filter-denied-overseerr": 11714 activeInfo.settings.homepage.overseerr.overseerrDefaultFilterDenied, 11715 }; 11716 $.each(defaultFilter, function (i, v) { 11717 if (v == false) { 11718 $("#" + i).click(); 11719 } 11720 }); 11721 } 11722} 11723function homepageRequests(service, timeout) { 11724 switch (service) { 11725 case "ombi":
11726 var apiUrl = "api/v2/homepage/ombi/requests"; 11727 var div = "homepageOrderombi"; 11728 var timeout = 11729 typeof timeout !== "undefined" 11730 ? timeout 11731 : activeInfo.settings.homepage.refresh.ombiRefresh; 11732 break; 11733 case "overseerr": 11734 var apiUrl = "api/v2/homepage/overseerr/requests"; 11735 var div = "homepageOrderoverseerr"; 11736 var timeout = 11737 typeof timeout !== "undefined" 11738 ? timeout 11739 : activeInfo.settings.homepage.refresh.overseerrRefresh; 11740 break; 11741 default: 11742 return false; 11743 } 11744 organizrAPI2("GET", apiUrl) 11745 .success(function (data) { 11746 try { 11747 let response = data.response; 11748 document.getElementById(div).innerHTML = ""; 11749 if (response.data.content !== false) { 11750 $("#" + div).html(buildRequest(service, div, response.data)); 11751 } 11752 $(".request-items-" + service).owlCarousel({ 11753 nav: false, 11754 autoplay: false, 11755 dots: false, 11756 margin: 10, 11757 autoWidth: true, 11758 items: 4, 11759 }); 11760 // Default Filter 11761 defaultRequestFilter(service); 11762 } catch (e) { 11763 organizrCatchError(e, data); 11764 } 11765 }) 11766 .fail(function (xhr) { 11767 OrganizrApiError(xhr); 11768 }); 11769 if (typeof timeouts[service + "-Requests-Homepage"] !== "undefined") { 11770 clearTimeout(timeouts[service + "-Requests-Homepage"]); 11771 } 11772 timeouts[service + "-Requests-Homepage"] = setTimeout(function () { 11773 homepageRequests(service, timeout); 11774 }, timeout); 11775 delete timeout; 11776} 11777function testAPIConnection(service, data = "") { 11778 messageSingle( 11779 "", 11780 " Testing now...", 11781 activeInfo.settings.notifications.position, 11782 "#FFF", 11783 "info", 11784 "60000" 11785 ); 11786 organizrAPI2("POST", "api/v2/test/" + service, data) 11787 .success(function (data) { 11788 try { 11789 let response = data.response; 11790 messageSingle( 11791 "", 11792 " API Connection Success", 11793 activeInfo.settings.notifications.position, 11794 "#FFF", 11795 "success", 11796 "10000" 11797 ); 11798 } catch (e) { 11799 organizrCatchError(e, data); 11800 } 11801 }) 11802 .fail(function (xhr) { 11803 OrganizrApiError(xhr, "API Error"); 11804 }); 11805} 11806function getUnifiSite() { 11807 messageSingle( 11808 "", 11809 " Grabbing now...", 11810 activeInfo.settings.notifications.position, 11811 "#FFF", 11812 "info", 11813 "10000" 11814 ); 11815 organizrAPI2("POST", "api/v2/test/unifi/site", {}) 11816 .success(function (data) { 11817 try { 11818 var response = data.response; 11819 if (response.data !== false) { 11820 var sites = ""; 11821 if (response.data.data) { 11822 $.each(response.data.data, function (i, v) { 11823 sites += 11824 '<div class="form-group row"><div class="col-sm-12"><h4 class="mouse" onclick="unifiSiteApply(\'' + 11825 v.name + 11826 "')\">" + 11827 v.desc + 11828 "</h4></div></div>"; 11829 }); 11830 } else { 11831 //console.log('no'); 11832 } 11833 var div = 11834 ` 11835 <div class="row"> 11836 <div class="col-12"> 11837 <div class="card m-b-0"> 11838 <div class="form-horizontal"> 11839 <div class="card-body"> 11840 <h4 class="card-title" lang="en">Choose Unifi Site</h4> 11841 ` + 11842 sites + 11843 ` 11844 </div> 11845 </div> 11846 </div> 11847 </div> 11848 </div> 11849 `; 11850 swal({ 11851 content: createElementFromHTML(div),
11852 buttons: false, 11853 className: "bg-org", 11854 }); 11855 } else { 11856 messageSingle( 11857 "API Connection Failed", 11858 response.data, 11859 activeInfo.settings.notifications.position, 11860 "#FFF", 11861 "error", 11862 "10000" 11863 ); 11864 } 11865 } catch (e) { 11866 organizrCatchError(e, data); 11867 } 11868 }) 11869 .fail(function (xhr) { 11870 OrganizrApiError(xhr, "API Error"); 11871 }); 11872} 11873function unifiSiteApply(name) { 11874 $("#homepage-UniFi-form [name=unifiSiteName]").val(name); 11875 $("#homepage-UniFi-form [name=unifiSiteName]").change(); 11876 swal.close(); 11877 messageSingle( 11878 "", 11879 " Grabbed Site - Please Save Now", 11880 activeInfo.settings.notifications.position, 11881 "#FFF", 11882 "success", 11883 "10000" 11884 ); 11885} 11886function homepageCalendar(timeout) { 11887 var timeout = 11888 typeof timeout !== "undefined" 11889 ? timeout 11890 : activeInfo.settings.homepage.refresh.calendarRefresh; 11891 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 11892 $(".fc-toolbar").addClass("fc-alternate"); 11893 } 11894 organizrAPI2("GET", "api/v2/homepage/calendar") 11895 .success(function (data) { 11896 try { 11897 let response = data.response; 11898 $("#calendar").fullCalendar("removeEvents"); 11899 $("#calendar").fullCalendar("addEventSource", response.data.events); 11900 $("#calendar").fullCalendar("addEventSource", response.data.ical); 11901 $("#calendar").fullCalendar("today"); 11902 } catch (e) { 11903 organizrCatchError(e, data); 11904 } 11905 }) 11906 .fail(function (xhr) { 11907 OrganizrApiError(xhr); 11908 }); 11909 if (typeof timeouts["calendar-Homepage"] !== "undefined") { 11910 clearTimeout(timeouts["calendar-Homepage"]); 11911 } 11912 timeouts["calendar-Homepage"] = setTimeout(function () { 11913 homepageCalendar(timeout); 11914 }, timeout); 11915 delete timeout; 11916} 11917function buildTautulliItem(array) { 11918 var cards = ""; 11919 var homestats = array.homestats.data; 11920 var libstats = array.libstats; 11921 var options = array.options; 11922 var friendlyName = array.options.friendlyName; 11923 var buildLibraries = function (data) { 11924 var libs = data.data; 11925 var movies = []; 11926 var tv = []; 11927 var audio = []; 11928 11929 libs.forEach((e) => { 11930 switch (e["section_type"]) { 11931 case "movie": 11932 movies.push(e); 11933 break; 11934 case "show": 11935 tv.push(e); 11936 break; 11937 case "artist": 11938 audio.push(e); 11939 break; 11940 default: 11941 break; 11942 } 11943 }); 11944 11945 movies = movies.sort((a, b) => 11946 parseInt(a["count"]) > parseInt(b["count"]) ? -1 : 1 11947 ); 11948 tv = tv.sort((a, b) => 11949 parseInt(a["count"]) > parseInt(b["count"]) ? -1 : 1 11950 ); 11951 audio = audio.sort((a, b) => 11952 parseInt(a["count"]) > parseInt(b["count"]) ? -1 : 1 11953 ); 11954 11955 var buildCard = function (type, data) { 11956 var extraField = null; 11957 var section_name = null; 11958 if (type == "movie") { 11959 extraField = "Movies"; 11960 section_name = "Movie Libraries"; 11961 } else if (type == "show") { 11962 extraField = "Shows/Seasons/Episodes"; 11963 section_name = "TV Show Libraries"; 11964 } else if (type == "artist") { 11965 extraField = "Artists/Albums/Tracks"; 11966 section_name = "Music Libraries"; 11967 } 11968 var cardTitle = 11969 '<th><span class="pull-left cardTitle">' + 11970 section_name.toUpperCase() + 11971 '</span><span class="pull-right cardCountType">' + 11972 extraField.toUpperCase() + 11973 "</th>"; 11974 var card = 11975 ` 11976 <div class="col-lg-4 col-md-6 col-sm-12 col-xs-12"> 11977 <div class="card text-white mb-3 homepage-tautulli-card library-card"> 11978 <div class="card-body h-100 bg-org-alt"> 11979 <table class="h-100 w-100"> 11980 <tr> 11981 <td rowspan='2' class="poster-td text-center"><img src="data/cache/tautulli-` + 11982 type + 11983 `.svg" class="lib-icon" alt="library icon"></td> 11984 ${cardTitle} 11985 </tr> 11986 <tr> 11987 <td> 11988 <div class="scrollable default-scroller">`; 11989 for (var i = 0; i < data.length; i++) { 11990 var rowType = 11991 i == 0 11992 ? "tautulliFirstItem" 11993 : i == data.length - 1 11994 ? "tautulliLastItem" 11995 : ""; 11996 var rowValue = ""; 11997 var firstDivCol = ""; 11998 var secondDivCol = ""; 11999 if (type == "movie") { 12000 rowValue = data[i]["count"]; 12001 firstDivCol = "col-md-9"; 12002 secondDivCol = "col-md-2"; 12003 } else { 12004 rowValue = 12005 data[i]["count"] + 12006 '<span class="tautulliSeparator"> / </span>' + 12007 data[i]["parent_count"] + 12008 '<span class="tautulliSeparator"> / </span>' + 12009 data[i]["child_count"]; 12010 firstDivCol = "col-md-5"; 12011 secondDivCol = "col-md-6"; 12012 } 12013 card += ` 12014 <div class="cardListItem elip row w-100 p-r-0 m-0 ${rowType}"> 12015 <div class="tautulliRank col-md-1 p-0">${ 12016 i + 1 12017 }</div> 12018 <div class="${firstDivCol} p-0 text-left elip"> ${ 12019 data[i]["section_name"] 12020 }</div> 12021 <div class="${secondDivCol} cardListCount text-right m-l-10 p-0">${rowValue}</div> 12022 </div> 12023 `; 12024 } 12025 12026 card += ` 12027 </div> 12028 </td> 12029 </tr> 12030 </table> 12031 </div> 12032 </div> 12033 </div>`; 12034 return card; 12035 }; 12036 var card = movies.length > 0 ? buildCard("movie", movies) : ""; 12037 card += tv.length > 0 ? buildCard("show", tv) : ""; 12038 card += audio.length > 0 ? buildCard("artist", audio) : ""; 12039 return card; 12040 }; 12041 var buildStats = function (data, stat, friendlyName = true) { 12042 var card = ""; 12043 data.forEach((e) => { 12044 let classes = ""; 12045 if (e["stat_id"] == stat && e["rows"].length > 0) { 12046 if (stat === "top_platforms") { 12047 classes = " platform-" + e["rows"][0]["platform_name"] + "-rgba"; 12048 } else { 12049 classes = " bg-org-alt"; 12050 } 12051 card += `
12052 <div class="col-xl-3 col-lg-4 col-md-6 col-sm-12 col-xs-12"> 12053 <div class="card text-white mb-3 homepage-tautulli-card">`; 12054 if (stat !== "top_users" && stat !== "top_platforms") { 12055 card += 12056 ` 12057 <div class="bg-img-cont"> 12058 <img class="bg-img" src="` + 12059 e["rows"][0]["art"] + 12060 `" alt="background art"> 12061 </div> 12062 `; 12063 } 12064 card += 12065 ` 12066 <div class="card-body h-100` + 12067 classes + 12068 `"> 12069 <table class="h-100 w-100"> 12070 <tr>`; 12071 if (stat == "top_users") { 12072 card += 12073 `<td rowspan="2" class="poster-td text-center"><img src="` + 12074 e["rows"][0]["user_thumb"] + 12075 `" class="poster avatar" alt="user avatar"></td>`; 12076 } else if (stat == "top_platforms") { 12077 card += 12078 `<td rowspan="2" class="poster-td text-center"><img src="data/cache/tautulli-` + 12079 e["rows"][0]["platform_name"] + 12080 `.svg" class="poster" alt="platform icon"></td>`; 12081 } else { 12082 card += 12083 `<td rowspan="2" class="poster-td"><img src="` + 12084 e["rows"][0]["thumb"] + 12085 `" class="poster" alt="movie poster"></td>`; 12086 } 12087 var extraField = null; 12088 if (e["stat_title"].includes("Popular")) { 12089 extraField = "users"; 12090 } else if ( 12091 e["stat_title"].includes("Watched") || 12092 e["stat_title"].includes("Active") 12093 ) { 12094 extraField = "plays"; 12095 } 12096 var cardTitle = 12097 '<th><span class="pull-left cardTitle">' + 12098 e["stat_title"].toUpperCase() + 12099 '</span><span class="pull-right cardCountType">' + 12100 extraField.toUpperCase() + 12101 "</th>"; 12102 card += 12103 cardTitle + 12104 ` 12105 </tr> 12106 <tr> 12107 <td><div class="scrollable default-scroller">`; 12108 for (var i = 0; i < e["rows"].length; i++) { 12109 var item = e["rows"][i]; 12110 var rowType = 12111 i == 0 12112 ? "tautulliFirstItem" 12113 : i == e["rows"].length - 1 12114 ? "tautulliLastItem" 12115 : ""; 12116 var rowNameValue = ""; 12117 var rowValue = ""; 12118 if (stat == "top_users") { 12119 if (friendlyName) { 12120 rowNameValue = item["friendly_name"]; 12121 } else { 12122 rowNameValue = item["user"]; 12123 } 12124 rowValue = item["total_plays"]; 12125 } else if (stat == "top_platforms") { 12126 rowNameValue = item["platform"]; 12127 rowValue = item["total_plays"]; 12128 } else if (extraField == "users") { 12129 rowNameValue = item["title"]; 12130 rowValue = item["users_watched"]; 12131 } else { 12132 rowNameValue = item["title"]; 12133 rowValue = item["total_plays"]; 12134 } 12135 card += ` 12136 <div class="cardListItem elip row w-100 p-r-0 m-0 ${rowType}"> 12137 <div class="tautulliRank col-md-1 p-0">${ 12138 i + 1 12139 }</div> 12140 <div class="col-md-9 p-0 text-left elip">${rowNameValue}</div> 12141 <div class="col-md-2 cardListCount text-right m-l-10 p-0">${rowValue}</div> 12142 </div>`; 12143 } 12144 card += ` 12145 </div></td> 12146 </tr> 12147 </table> 12148 </div> 12149 </div> 12150 </div>`; 12151 } else { 12152 return ""; 12153 } 12154 }); 12155 return card; 12156 }; 12157 cards += '<div class="row tautulliTop">'; 12158 cards += options["libraries"] ? buildLibraries(libstats) : "";
12159 cards += options["popularMovies"] 12160 ? buildStats(homestats, "popular_movies") 12161 : ""; 12162 cards += options["popularTV"] ? buildStats(homestats, "popular_tv") : ""; 12163 cards += options["topMovies"] ? buildStats(homestats, "top_movies") : ""; 12164 cards += options["topTV"] ? buildStats(homestats, "top_tv") : ""; 12165 cards += options["topUsers"] 12166 ? buildStats(homestats, "top_users", friendlyName) 12167 : ""; 12168 cards += options["topPlatforms"] 12169 ? buildStats(homestats, "top_platforms") 12170 : ""; 12171 cards += "</div>"; 12172 cards += '<div class="row tautulliLibraries">'; 12173 cards += "</div>"; 12174 return cards; 12175} 12176function buildTautulli(array) { 12177 if (array === false) { 12178 return ""; 12179 } 12180 var html = ` 12181 <div id="allTautulli"> 12182 <div class="el-element-overlay row">`; 12183 if (array["options"]["title"]) { 12184 html += 12185 ` 12186 <div class="col-md-12"> 12187 <h4 class="pull-left homepage-element-title"><span class="mouse" onclick="homepageTautulli()">` + 12188 activeInfo.settings.homepage.options.titles.tautulli + 12189 `</span> : </h4><h4 class="pull-left"> </h4> 12190 <hr class="hidden-xs ml-2"> 12191 </div> 12192 <div class="clearfix"></div> 12193 `; 12194 } 12195 html += 12196 ` 12197 <div class="tautulliCards col-sm-12 my-3"> 12198 ` + 12199 buildTautulliItem(array) + 12200 ` 12201 </div> 12202 </div> 12203 </div> 12204 `; 12205 return array ? html : ""; 12206} 12207function homepageTautulli(timeout) { 12208 var timeout = 12209 typeof timeout !== "undefined" 12210 ? timeout 12211 : activeInfo.settings.homepage.refresh.homepageTautulliRefresh; 12212 organizrAPI2("GET", "api/v2/homepage/tautulli/data") 12213 .success(function (data) { 12214 try { 12215 let response = data.response; 12216 document.getElementById("homepageOrdertautulli").innerHTML = ""; 12217 if (response.data !== null) { 12218 $("#homepageOrdertautulli").html(buildTautulli(response.data)); 12219 } 12220 } catch (e) { 12221 organizrCatchError(e, data); 12222 } 12223 }) 12224 .fail(function (xhr) { 12225 OrganizrApiError(xhr); 12226 }); 12227 let timeoutTitle = "Tautulli-Homepage"; 12228 if (typeof timeouts[timeoutTitle] !== "undefined") { 12229 clearTimeout(timeouts[timeoutTitle]); 12230 } 12231 timeouts[timeoutTitle] = setTimeout(function () { 12232 homepageTautulli(timeout); 12233 }, timeout); 12234 delete timeout; 12235} 12236function weatherIcon(code, daytime = true) { 12237 switch (code) { 12238 case 1: 12239 case 2: 12240 return daytime ? "wi-day-sunny" : "wi-night-clear"; 12241 case 3: 12242 case 4: 12243 case 5: 12244 case 6: 12245 case 22: 12246 return daytime ? "wi-day-sunny-overcast" : "wi-night-alt-partly-cloudy"; 12247 case 7: 12248 case 8: 12249 case 9: 12250 return daytime ? "wi-day-cloudy-high" : "wi-night-partly-cloudy"; 12251 case 10: 12252 case 11: 12253 case 12: 12254 return daytime ? "wi-day-thunderstorm" : "wi-night-thunderstorm"; 12255 case 13: 12256 case 14: 12257 case 15: 12258 return daytime ? "wi-day-haze" : "wi-night-cloudy-windy"; 12259 case 16: 12260 case 17: 12261 case 18: 12262 return daytime ? "wi-day-fog" : "wi-night-fog"; 12263 case 19: 12264 case 20: 12265 case 21: 12266 return daytime ? "wi-day-cloudy-high" : "wi-night-cloudy-high"; 12267 case 23: 12268 case 25: 12269 return daytime ? "wi-day-rain" : "wi-night-rain"; 12270 case 24: 12271 case 26: 12272 return daytime ? "wi-day-snow" : "wi-night-snow"; 12273 case 27: 12274 case 28: 12275 case 30: 12276 case 31: 12277 case 33: 12278 return daytime ? "wi-day-rain-mix" : "wi-night-alt-rain-mix"; 12279 case 29: 12280 case 32: 12281 case 34: 12282 case 35: 12283 return daytime 12284 ? "wi-day-snow-thunderstorm" 12285 : "wi-night-alt-snow-thunderstorm"; 12286 default: 12287 return daytime ? "wi-day-sunny" : "wi-night-clear"; 12288 } 12289} 12290function buildWeatherAndAir(array) { 12291 var returnData = ""; 12292 if (typeof array.content === "undefined") { 12293 return ""; 12294 } 12295 if (array.content.weather !== false) { 12296 if (array.content.weather.error === null) { 12297 let dates = {}; 12298 $.each(array.content.weather.data, function (i, v) { 12299 let date = moment(v.datetime).format("YYYY-MM-DD"); 12300 if (typeof dates[date] === "undefined") { 12301 dates[date] = v; 12302 dates[date]["temps"] = { 12303 high: v.temperature.value, 12304 low: v.temperature.value, 12305 }; 12306 } else { 12307 if (moment(v.datetime).format("hh:mm a") == "12:00 pm") { 12308 dates[date]["icon_code"] = v.icon_code; 12309 dates[date]["is_day_time"] = v.is_day_time; 12310 } 12311 if (v.temperature.value > dates[date]["temps"]["high"]) { 12312 dates[date]["temps"]["high"] = v.temperature.value; 12313 } 12314 if (v.temperature.value < dates[date]["temps"]["low"]) { 12315 dates[date]["temps"]["low"] = v.temperature.value; 12316 } 12317 } 12318 }); 12319 let weatherItems = '<div class="row">'; 12320 let weatherItemsCount = 0; 12321 $.each(dates, function (i, v) { 12322 if (weatherItemsCount === 0) { 12323 weatherItems += 12324 ` 12325 <div class="col-lg-4 col-sm-12 col-xs-12"> 12326 <div class="white-box"> 12327 <h3 class="box-title"><small class="pull-right m-t-10">Feels Like ` + 12328 Math.round(v.feels_like_temperature.value) + 12329 `°</small>` + 12330 moment(v.datetime).format("dddd") + 12331 `<br/><small class="text-uppercase elip">` + 12332 v.weather_text + 12333 `</small></h3> 12334 <ul class="list-inline two-part" style="margin-top: -13px;"> 12335 <li><i class="wi ` + 12336 weatherIcon(v.icon_code, v.is_day_time) + 12337 ` text-info"></i></li> 12338 <li class="text-right"><span class="counter">` + 12339 Math.round(v.temperature.value) + 12340 `<small><sup>°` + 12341 v.temperature.units + 12342 `</sup></small></span></li> 12343 </ul> 12344 <ul class="list-inline m-b-0"> 12345 <li class="pull-left w-50 hidden-xs"></li> 12346 <li class="pull-right" style="width:75px"><small><i class="wi wi-strong-wind m-r-5 text-primary tooltip-primary" data-toggle="tooltip" data-placement="top" title="" data-original-title="Wind"></i>` + 12347 Math.round(v.wind.speed.value) + 12348 ` ` + 12349 v.wind.speed.units + 12350 `</small></li> 12351 <li class="pull-right" style="width:75px"><small><i class="wi wi-barometer m-r-5 text-primary tooltip-primary" data-toggle="tooltip" data-placement="top" title="" data-original-title="Pressure"></i>` + 12352 Math.round(v.pressure.value) + 12353 ` ` + 12354 v.pressure.units + 12355 `</small></li> 12356 <li class="pull-right" style="width:45px"><small><i class="wi wi-humidity m-r-5 text-primary tooltip-primary" data-toggle="tooltip" data-placement="top" title="" data-original-title="Humidity"></i>` + 12357 Math.round(v.relative_humidity) + 12358 `</small></li> 12359 <li class="pull-right" style="width:45px"><small><i class="wi wi-raindrop m-r-5 text-primary tooltip-primary" data-toggle="tooltip" data-placement="top" title="" data-original-title="Dew Point"></i>` + 12360 Math.round(v.dew_point.value) + 12361 `°</small></li> 12362 <div class="clearfix"></div> 12363 </ul> 12364 </div> 12365 </div> 12366 `; 12367 } else if (weatherItemsCount !== 5) { 12368 weatherItems += 12369 ` 12370 <div class="col-lg-2 col-sm-3 col-xs-12"> 12371 <div class="white-box"> 12372 <h3 class="box-title">` + 12373 moment(v.datetime).format("dddd") + 12374 `</h3> 12375 <ul class="list-inline two-part"> 12376 <li><i class="wi ` + 12377 weatherIcon(v.icon_code, v.is_day_time) + 12378 ` text-info"></i></li> 12379 <li class="text-right"><span class="counter">` + 12380 Math.round(v.temps.high) + 12381 `<small><sup>°` + 12382 v.temperature.units + 12383 `</sup></small></span></li> 12384 </ul> 12385 <ul class="list-inline m-b-0"> 12386 <li class="pull-left w-100"><small class="text-uppercase elip">` + 12387 v.weather_text + 12388 `</small></li> 12389 <div class="clearfix"></div> 12390 </ul> 12391 </div> 12392 </div> 12393 `; 12394 } 12395 weatherItemsCount++; 12396 }); 12397 weatherItems += "</div>"; 12398 returnData += weatherItems; 12399 } 12400 } 12401 if (array.content.air !== false) { 12402 if (array.content.air.error === null) { 12403 let airItems = '<div class="row">'; 12404 let activeClasses = { 12405 poor: "", 12406 low: "", 12407 moderate: "", 12408 good: "", 12409 excellent: "", 12410 text: "", 12411 }; 12412 if (array.content.air.data.indexes.baqi.aqi <= 20) { 12413 activeClasses["poor"] = "active"; 12414 activeClasses["text"] = "text-poor-gradient"; 12415 } else if (array.content.air.data.indexes.baqi.aqi <= 40) { 12416 activeClasses["low"] = "active"; 12417 activeClasses["text"] = "text-low-gradient"; 12418 } else if (array.content.air.data.indexes.baqi.aqi <= 60) { 12419 activeClasses["moderate"] = "active"; 12420 activeClasses["text"] = "text-moderate-gradient"; 12421 } else if (array.content.air.data.indexes.baqi.aqi <= 80) { 12422 activeClasses["good"] = "active"; 12423 activeClasses["text"] = "text-good-gradient"; 12424 } else if (array.content.air.data.indexes.baqi.aqi <= 100) { 12425 activeClasses["excellent"] = "active"; 12426 activeClasses["text"] = "text-excellent-gradient"; 12427 } 12428 airItems += ` 12429 <div class="col-lg-4 col-sm-12 col-xs-12"> 12430 <div class="white-box text-white"> 12431 <div class="aqi-scale-component-wrapper"> 12432 <div class="aqi__header"> 12433 <div class="aqi__value"> 12434 <div class="component-wrapper aqi-number ${ 12435 activeClasses["text"] 12436 }">${
12437 array.content.air.data.indexes.baqi.aqi 12438 }</div> 12439 </div> 12440 <div class="aqi__text"><h2 >AirQuality Index</h2></div> 12441 </div> 12442 <div class="aqi-scale m-t-40"> 12443 <div class="category"> 12444 <div class="chip ${activeClasses["poor"]}"> 12445 <div class="chip__text text-white">Poor</div> 12446 <div class="chip__bar bg-poor-gradient"></div> 12447 </div> 12448 <div class="category__min-value text-white">0</div> 12449 <div class="category__max-value text-white">20</div> 12450 </div> 12451 <div class="category"> 12452 <div class="chip ${activeClasses["low"]}"> 12453 <div class="chip__text text-white">Low</div> 12454 <div class="chip__bar bg-low-gradient"></div> 12455 </div> 12456 <div class="category__max-value text-white">40</div> 12457 </div> 12458 <div class="category"> 12459 <div class="chip ${activeClasses["moderate"]}"> 12460 <div class="chip__text text-white">Moderate</div> 12461 <div class="chip__bar bg-moderate-gradient"></div> 12462 </div> 12463 <div class="category__max-value text-white">60</div> 12464 </div> 12465 <div class="category"> 12466 <div class="chip ${activeClasses["good"]}"> 12467 <div class="chip__text text-white">Good</div> 12468 <div class="chip__bar bg-good-gradient"></div> 12469 </div> 12470 <div class="category__max-value text-white">80</div> 12471 </div> 12472 <div class="category"> 12473 <div class="chip ${activeClasses["excellent"]}"> 12474 <div class="chip__text text-white">Excellent</div> 12475 <div class="chip__bar bg-excellent-gradient"></div> 12476 </div> 12477 <div class="category__max-value text-white">100</div> 12478 </div> 12479 </div> 12480 </div> 12481 </div> 12482 </div> 12483 ${buildPollutant(array.content.air.data.pollutants)} 12484 ${buildHealthRecommendation( 12485 array.content.air.data.health_recommendations 12486 )} 12487 `; 12488 airItems += "</div>"; 12489 returnData += airItems; 12490 } 12491 } 12492 if (array.content.pollen !== false) { 12493 if (array.content.pollen.error === null) { 12494 } 12495 } 12496 return returnData; 12497} 12498function buildHealthRecommendation(array) { 12499 var healthHeader = ""; 12500 var healthSection = ""; 12501 $.each(array, function (i, v) { 12502 var title = i 12503 .toString() 12504 .replace("_", " ") 12505 .toLowerCase() 12506 .split(" ") 12507 .map((word) => word.charAt(0).toUpperCase() + word.substring(1)) 12508 .join(" "); 12509 switch (i) { 12510 case "general_population": 12511 var icon = "fa fa-group"; 12512 break; 12513 case "elderly": 12514 var icon = "ti ti-wheelchair"; 12515 break; 12516 case "lung_diseases": 12517 var icon = "mdi mdi-spray"; 12518 break; 12519 case "heart_diseases": 12520 var icon = "mdi mdi-heart-pulse"; 12521 break; 12522 case "active": 12523 var icon = "mdi mdi-run-fast"; 12524 break; 12525 case "pregnant_women": 12526 var icon = "mdi mdi-human-pregnant"; 12527 break; 12528 case "children": 12529 var icon = "fa fa-child"; 12530 break; 12531 default: 12532 var icon = ""; 12533 } 12534 healthHeader += 12535 '<li><a href="#section-health-' + 12536 i + 12537 '" class="sticon ' + 12538 icon + 12539 '"></a></li>'; 12540 healthSection += ` 12541 <section id="section-pollutant-${i}" class="" > 12542 <h5 class="m-t-0">${title}</h5>
12543 <span>${v}</span> 12544 </section> 12545 `; 12546 }); 12547 var html = ` 12548 <div class="col-lg-4 hidden-xs hidden-sm"> 12549 <div class="white-box text-white p-0"> 12550 <!-- Tabstyle start --> 12551 <section class=""> 12552 <div class="sttabs sttabs-main-weather-health-div tabs-style-iconbox"> 12553 <nav> 12554 <ul>${healthHeader}</ul> 12555 </nav> 12556 <div class="content-wrap health-and-pollutant-section default-scroller">${healthSection}</div> 12557 <!-- /content --> 12558 </div> 12559 <!-- /tabs --> 12560 </section> 12561 <!-- Tabstyle start --> 12562 </div> 12563 </div> 12564 <script> 12565 (function() { 12566 [].slice.call(document.querySelectorAll('.sttabs-main-weather-health-div')).forEach(function(el) { 12567 new CBPFWTabs(el); 12568 }); 12569 })(); 12570 </script>`; 12571 return html; 12572} 12573function buildPollutant(array) { 12574 var pollutantHeader = ""; 12575 var pollutantSection = ""; 12576 $.each(array, function (i, v) { 12577 pollutantHeader += 12578 '<li><a href="#section-pollutant-' + 12579 i + 12580 '" class="sticon"><strong>' + 12581 v.display_name + 12582 '</strong><br/><small class="elip">' + 12583 v.concentration.value + 12584 " " + 12585 v.concentration.units + 12586 "</small></a></li>"; 12587 pollutantSection += ` 12588 <section id="section-pollutant-${i}"> 12589 <h5 class="m-t-0">${v.full_name}</h5> 12590 <h6>Sources</h6> 12591 <span>${v.sources_and_effects.sources}</span> 12592 <hr> 12593 <h6>Effects</h6> 12594 <span>${v.sources_and_effects.effects}</span> 12595 </section> 12596 `; 12597 }); 12598 var html = ` 12599 <div class="col-lg-4 hidden-xs hidden-sm"> 12600 <div class="white-box text-white p-0"> 12601 <!-- Tabstyle start --> 12602 <section class=""> 12603 <div class="sttabs sttabs-main-weather-pollutant-div tabs-style-iconbox"> 12604 <nav> 12605 <ul>${pollutantHeader}</ul> 12606 </nav> 12607 <div class="content-wrap health-and-pollutant-section default-scroller">${pollutantSection}</div> 12608 <!-- /content --> 12609 </div> 12610 <!-- /tabs --> 12611 </section> 12612 <!-- Tabstyle start --> 12613 </div> 12614 </div> 12615 <script> 12616 (function() { 12617 [].slice.call(document.querySelectorAll('.sttabs-main-weather-pollutant-div')).forEach(function(el) { 12618 new CBPFWTabs(el); 12619 }); 12620 })(); 12621 </script>`; 12622 return html; 12623} 12624function homepageWeatherAndAir(timeout) { 12625 var timeout = 12626 typeof timeout !== "undefined" 12627 ? timeout 12628 : activeInfo.settings.homepage.refresh.homepageWeatherAndAirRefresh; 12629 organizrAPI2("GET", "api/v2/homepage/weather/data") 12630 .success(function (data) { 12631 try { 12632 let response = data.response; 12633 if (response.data !== null) { 12634 document.getElementById("homepageOrderWeatherAndAir").innerHTML = ""; 12635 $("#homepageOrderWeatherAndAir").html( 12636 buildWeatherAndAir(response.data) 12637 ); 12638 } 12639 } catch (e) { 12640 organizrCatchError(e, data); 12641 } 12642 }) 12643 .fail(function (xhr) { 12644 OrganizrApiError(xhr); 12645 }); 12646 let timeoutTitle = "WeatherAndAir-Homepage"; 12647 if (typeof timeouts[timeoutTitle] !== "undefined") { 12648 clearTimeout(timeouts[timeoutTitle]); 12649 } 12650 timeouts[timeoutTitle] = setTimeout(function () { 12651 homepageWeatherAndAir(timeout); 12652 }, timeout); 12653 delete timeout; 12654} 12655function buildMonitorrItem(array) { 12656 var cards = ""; 12657 var options = array["options"]; 12658 var services = array["services"]; 12659 var tabName = ""; 12660 12661 var buildCard = function (name, data) { 12662 if (data.status == true) { 12663 var statusColor = "success"; 12664 var imageText = "fa fa-check-circle text-success"; 12665 } else if (data.status == "unresponsive") { 12666 var statusColor = "warning animated-3 loop-animation flash"; 12667 var imageText = "fa fa-times-circle text-warning"; 12668 } else { 12669 var statusColor = "danger animated-3 loop-animation flash"; 12670 var imageText = "fa fa-times-circle text-danger"; 12671 } 12672 if (typeof data.link !== "undefined" && data.link.includes("#")) { 12673 tabName = data.link.substring(data.link.indexOf("#") + 1); 12674 console.log(tabName); 12675 // Need to rework tabActions 12676 monitorrLink = 12677 '<a href="javascript:void(0)" onclick="tabActions(event,\'' + 12678 tabName + 12679 "',1)\">"; 12680 } else if (typeof data.link !== "undefined") { 12681 monitorrLink = '<a href="' + data.link + '" target="_blank">'; 12682 } 12683 if (options["compact"]) { 12684 var card = 12685 ` 12686 <div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-xs-12"> 12687 <div class="card bg-inverse text-white mb-3 monitorr-card"> 12688 <div class="card-body bg-org-alt pt-1 pb-1"> 12689 <div class="d-flex no-block align-items-center"> 12690 <div class="left-health bg-` + 12691 statusColor + 12692 `"></div> 12693 <div class="ml-1 w-100"> 12694 <i class="` + 12695 imageText + 12696 ` font-20 pull-right mt-3 mb-2"></i> 12697 `; 12698 if (typeof data.link !== "undefined") { 12699 card += monitorrLink; 12700 } 12701 card += 12702 `<h3 class="d-flex no-block align-items-center mt-2 mb-2"><img class="lazyload loginTitle" src="` + 12703 data.image + 12704 `"> ` + 12705 name + 12706 `</h3> 12707 `; 12708 if (typeof data.link !== "undefined") { 12709 card += `</a>`; 12710 } 12711 card += `<div class="clearfix"></div> 12712 </div> 12713 </div> 12714 </div> 12715 </div> 12716 </div>`; 12717 } else { 12718 var card = ` 12719 <div class="col-lg-2 col-md-3 col-sm-4 col-xs-6"> 12720 <div class="card bg-inverse text-white mb-3 monitorr-card"> 12721 <div class="card-body bg-org-alt text-center"> 12722 `; 12723 if (typeof data.link !== "undefined") { 12724 card += `<a href="` + data.link + `" target="_blank">`; 12725 } 12726 card += 12727 `<div class="d-block"> 12728 <h3 class="mt-0 mb-3">` + 12729 name + 12730 `</h3> 12731 <img class="monitorrImage" src="` + 12732 data.image + 12733 `" alt="service icon"> 12734 </div> 12735 <div class="d-inline-block mt-4 py-2 px-4 badge indicator bg-` + 12736 statusColor + 12737 `"> 12738 <p class="mb-0">`; 12739 if (data.status == true) { 12740 card += "ONLINE"; 12741 } else if (data.status == "unresponsive") { 12742 card += "UNRESPONSIVE"; 12743 } else { 12744 card += "OFFLINE"; 12745 } 12746 card += `</p> 12747 </div> 12748 `; 12749 if (typeof data.link !== "undefined") { 12750 card += `</a>`; 12751 } 12752 card += `</div> 12753 </div> 12754 </div> 12755 `; 12756 } 12757 return card; 12758 }; 12759 for (var key in services) { 12760 cards += buildCard(key, services[key]); 12761 } 12762 return cards; 12763} 12764function buildMonitorr(array) { 12765 if (array === false) { 12766 return ""; 12767 } 12768 if (array.error != undefined) { 12769 organizrConsole("Monitorr Function", array.error, "error"); 12770 } else { 12771 var services = 12772 typeof array.services !== "undefined" 12773 ? Object.keys(array.services).length 12774 : false;
12775 var html = ` 12776 <div id="allMonitorr"> 12777 <div class="el-element-overlay row">`; 12778 if (array["options"]["titleToggle"]) { 12779 html += 12780 ` 12781 <div class="col-md-12"> 12782 <h4 class="pull-left homepage-element-title"><span lang="en">` + 12783 array["options"]["title"] + 12784 `</span> : </h4><h4 class="pull-left"> <span class="label label-info m-l-20 checkbox-circle good-monitorr-services mouse" onclick="homepageMonitorr()">` + 12785 services + 12786 `</span></h4></h4> 12787 <hr class="hidden-xs ml-2"> 12788 </div> 12789 <div class="clearfix"></div> 12790 `; 12791 } 12792 html += 12793 ` 12794 <div class="monitorrCards"> 12795 ` + 12796 buildMonitorrItem(array) + 12797 ` 12798 </div> 12799 </div> 12800 </div> 12801 <div class="clearfix"></div> 12802 `; 12803 } 12804 return array ? html : ""; 12805} 12806function homepageMonitorr(timeout) { 12807 var timeout = 12808 typeof timeout !== "undefined" 12809 ? timeout 12810 : activeInfo.settings.homepage.refresh.homepagePiholeRefresh; 12811 organizrAPI2("GET", "api/v2/homepage/monitorr/data") 12812 .success(function (data) { 12813 try { 12814 let response = data.response; 12815 document.getElementById("homepageOrderMonitorr").innerHTML = ""; 12816 if (response.data !== null) { 12817 buildMonitorr(response.data); 12818 $("#homepageOrderMonitorr").html(buildMonitorr(response.data)); 12819 } 12820 } catch (e) { 12821 organizrCatchError(e, data); 12822 } 12823 }) 12824 .fail(function (xhr) { 12825 OrganizrApiError(xhr); 12826 }); 12827 let timeoutTitle = "Monitorr-Homepage"; 12828 if (typeof timeouts[timeoutTitle] !== "undefined") { 12829 clearTimeout(timeouts[timeoutTitle]); 12830 } 12831 timeouts[timeoutTitle] = setTimeout(function () { 12832 homepageMonitorr(timeout); 12833 }, timeout); 12834 delete timeout; 12835} 12836function buildUptimeKumaItem(array) { 12837 var cards = ""; 12838 var options = array["options"]; 12839 var services = array["data"]; 12840 var tabName = ""; 12841 12842 var buildCard = function (name, data) { 12843 if (data.status == true) { 12844 var statusColor = "success"; 12845 var imageText = "fa fa-check-circle text-success"; 12846 } else { 12847 var statusColor = "danger animated-3 loop-animation flash"; 12848 var imageText = "fa fa-times-circle text-danger"; 12849 } 12850 tabName = data.name; 12851 kumaLink = 12852 '<a href="javascript:void(0)" onclick="tabActions(event,\'' + 12853 tabName + 12854 "',1)\">"; 12855 if (options["compact"]) { 12856 var card = 12857 ` 12858 <div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-xs-12"> 12859 <div class="card bg-inverse text-white mb-3 monitorr-card"> 12860 <div class="card-body bg-org-alt pt-1 pb-1"> 12861 <div class="d-flex no-block align-items-center"> 12862 <div class="left-health bg-` + 12863 statusColor + 12864 `"></div> 12865 <div class="ml-1 w-100"> 12866 <i class="` + 12867 imageText + 12868 ` font-20 pull-right mt-3 mb-2"></i> 12869 `; 12870 if (typeof data.url !== "undefined") { 12871 card += kumaLink; 12872 } 12873 card += 12874 `<h3 class="d-flex no-block align-items-center mt-2 mb-2"><img class="lazyload loginTitle"> ` + 12875 data.name; 12876 if (data.latency != null && options.showLatency) { 12877 card += 12878 `<span class="ml-3 font-12 align-self-center text-dark">` + 12879 data.latency + 12880 `ms</span></h3>`; 12881 } 12882 card += `</h3>`; 12883 if (typeof data.url !== "undefined") { 12884 card += `</a>`; 12885 } 12886 card += `<div class="clearfix"></div> 12887 </div> 12888 </div> 12889 </div> 12890 </div> 12891 </div>`; 12892 } else { 12893 var card = ` 12894 <div class="col-lg-2 col-md-3 col-sm-4 col-xs-6"> 12895 <div class="card bg-inverse text-white mb-3 monitorr-card"> 12896 <div class="card-body bg-org-alt text-center"> 12897 `; 12898 if (typeof data.url !== "undefined") { 12899 card += `<a href="` + data.url + `" target="_blank">`; 12900 } 12901 card += 12902 `<div class="d-block"> 12903 <h3 class="mt-0 mb-2">` + 12904 data.name + 12905 `</h3>`; 12906 12907 if (data.latency != null && options.showLatency) { 12908 card += `<p class="text-dark mb-0">` + data.latency + `ms</p>`; 12909 } 12910 12911 card += 12912 `</div> 12913 <div class="d-inline-block mt-4 py-2 px-4 badge indicator bg-` + 12914 statusColor + 12915 `"> 12916 <p class="mb-0">`; 12917 if (data.status == true) { 12918 card += "ONLINE"; 12919 } else { 12920 card += "OFFLINE"; 12921 } 12922 card += `</p> 12923 </div> 12924 `; 12925 if (typeof data.url !== "undefined") { 12926 card += `</a>`; 12927 } 12928 card += `</div> 12929 </div> 12930 </div> 12931 `; 12932 } 12933 return card; 12934 }; 12935 for (var key in services) { 12936 cards += buildCard(key, services[key]); 12937 } 12938 return cards; 12939} 12940function buildUptimeKuma(array) { 12941 if (array === false) { 12942 return ""; 12943 } 12944 if (array.error != undefined) { 12945 organizrConsole("Uptime Kuma Function", array.error, "error"); 12946 } else { 12947 var html = ` 12948 <div id="allUptimeKuma"> 12949 <div class="el-element-overlay row">`; 12950 if (array["options"]["titleToggle"]) { 12951 html += 12952 ` 12953 <div class="col-md-12"> 12954 <h4 class="pull-left homepage-element-title"><span lang="en">` + 12955 array["options"]["title"] + 12956 `</span> : </h4> 12957 <hr class="hidden-xs ml-2"> 12958 </div> 12959 <div class="clearfix"></div> 12960 `; 12961 } 12962 html += 12963 ` 12964 <div class="uptimeKumaCards"> 12965 ` + 12966 buildUptimeKumaItem(array) + 12967 ` 12968 </div> 12969 </div> 12970 </div> 12971 <div class="clearfix"></div> 12972 `; 12973 } 12974 return array ? html : ""; 12975} 12976function homepageUptimeKuma(timeout) { 12977 var timeout = 12978 typeof timeout !== "undefined" 12979 ? timeout 12980 : activeInfo.settings.homepage.refresh.homepageUptimeKumaRefresh;
12981 organizrAPI2("GET", "api/v2/homepage/kuma/data") 12982 .success(function (data) { 12983 try { 12984 let response = data.response; 12985 document.getElementById("homepageOrderUptimeKuma").innerHTML = ""; 12986 if (response.data !== null) { 12987 buildUptimeKuma(response.data); 12988 $("#homepageOrderUptimeKuma").html(buildUptimeKuma(response.data)); 12989 } 12990 } catch (e) { 12991 console.log(e); 12992 organizrCatchError(e, data); 12993 } 12994 }) 12995 .fail(function (xhr) { 12996 OrganizrApiError(xhr); 12997 }); 12998 let timeoutTitle = "UptimeKuma-Homepage"; 12999 if (typeof timeouts[timeoutTitle] !== "undefined") { 13000 clearTimeout(timeouts[timeoutTitle]); 13001 } 13002 timeouts[timeoutTitle] = setTimeout(function () { 13003 homepageUptimeKuma(timeout); 13004 }, timeout); 13005 delete timeout; 13006} 13007function buildPromPageItem(array) { 13008 var cards = ""; 13009 var options = array["options"]; 13010 var services = array["data"]; 13011 var tabName = ""; 13012 console.log(options); 13013 13014 var buildCard = function (name, data) { 13015 if (data.status == true) { 13016 var statusColor = "success"; 13017 var imageText = "fa fa-check-circle text-success"; 13018 } else { 13019 var statusColor = "danger animated-3 loop-animation flash"; 13020 var imageText = "fa fa-times-circle text-danger"; 13021 } 13022 tabName = data.name; 13023 if (options["compact"]) { 13024 var card = 13025 ` 13026 <div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-xs-12"> 13027 <div class="card bg-inverse text-white mb-3 monitorr-card"> 13028 <div class="card-body bg-org-alt pt-1 pb-1"> 13029 <div class="d-flex no-block align-items-center"> 13030 <div class="left-health bg-` + 13031 statusColor + 13032 `"></div> 13033 <div class="ml-1 w-100"> 13034 <i class="` + 13035 imageText + 13036 ` font-20 pull-right mt-3 mb-2"></i> 13037 `; 13038 card += 13039 `<h3 class="d-flex no-block align-items-center mt-2 mb-2"><img class="lazyload loginTitle"> ` + 13040 data.name; 13041 if (data.uptime != null && options.showUptime) { 13042 card += 13043 `<span class="ml-3 font-12 align-self-center text-dark">` + 13044 Math.round(data.uptime * 100) / 100 + 13045 `%</span></h3>`; 13046 } 13047 card += `</h3>`; 13048 card += `<div class="clearfix"></div> 13049 </div> 13050 </div> 13051 </div> 13052 </div> 13053 </div>`; 13054 } else { 13055 var card = ` 13056 <div class="col-lg-2 col-md-3 col-sm-4 col-xs-6"> 13057 <div class="card bg-inverse text-white mb-3 monitorr-card"> 13058 <div class="card-body bg-org-alt text-center"> 13059 `; 13060 card += 13061 `<div class="d-block"> 13062 <h3 class="mt-0 mb-2">` + 13063 data.name + 13064 `</h3>`; 13065 13066 if (data.uptime != null && options.showUptime) { 13067 card += 13068 `<p class="text-dark mb-0">` + 13069 Math.round(data.uptime * 100) / 100 + 13070 `%</p>`; 13071 } 13072 13073 card += 13074 `</div> 13075 <div class="d-inline-block mt-4 py-2 px-4 badge indicator bg-` + 13076 statusColor + 13077 `"> 13078 <p class="mb-0">`; 13079 if (data.status == true) { 13080 card += "UP"; 13081 } else { 13082 card += "DOWN"; 13083 } 13084 card += `</p> 13085 </div> 13086 `; 13087 card += `</div> 13088 </div> 13089 </div> 13090 `; 13091 } 13092 return card; 13093 }; 13094 for (var key in services) { 13095 cards += buildCard(key, services[key]); 13096 } 13097 return cards; 13098} 13099function buildPromPage(array) { 13100 if (array === false) { 13101 return ""; 13102 } 13103 if (array.error != undefined) { 13104 organizrConsole("PromPage Function", array.error, "error"); 13105 } else { 13106 var html = ` 13107 <div id="allPromPage"> 13108 <div class="el-element-overlay row">`; 13109 if (array["options"]["titleToggle"]) { 13110 html += 13111 ` 13112 <div class="col-md-12"> 13113 <h4 class="pull-left homepage-element-title"><span lang="en">` + 13114 array["options"]["title"] + 13115 `</span> : </h4> 13116 <hr class="hidden-xs ml-2"> 13117 </div> 13118 <div class="clearfix"></div> 13119 `; 13120 } 13121 html += 13122 ` 13123 <div class="promPageCards"> 13124 ` + 13125 buildPromPageItem(array) + 13126 ` 13127 </div> 13128 </div> 13129 </div> 13130 <div class="clearfix"></div> 13131 `; 13132 } 13133 return array ? html : ""; 13134} 13135function homepagePromPage(timeout) { 13136 var timeout = 13137 typeof timeout !== "undefined" 13138 ? timeout 13139 : activeInfo.settings.homepage.refresh.homepagePromPageRefresh;
13140 organizrAPI2("GET", "api/v2/homepage/prompage/data") 13141 .success(function (data) { 13142 try { 13143 let response = data.response; 13144 document.getElementById("homepageOrderPromPage").innerHTML = ""; 13145 if (response.data !== null) { 13146 buildUptimeKuma(response.data); 13147 $("#homepageOrderPromPage").html(buildPromPage(response.data)); 13148 } 13149 } catch (e) { 13150 console.log(e); 13151 organizrCatchError(e, data); 13152 } 13153 }) 13154 .fail(function (xhr) { 13155 OrganizrApiError(xhr); 13156 }); 13157 let timeoutTitle = "PromPage-Homepage"; 13158 if (typeof timeouts[timeoutTitle] !== "undefined") { 13159 clearTimeout(timeouts[timeoutTitle]); 13160 } 13161 timeouts[timeoutTitle] = setTimeout(function () { 13162 homepagePromPage(timeout); 13163 }, timeout); 13164 delete timeout; 13165} 13166function homepageSpeedtest(timeout) { 13167 var timeout = 13168 typeof timeout !== "undefined" 13169 ? timeout 13170 : activeInfo.settings.homepage.refresh.homepageSpeedtestRefresh; 13171 organizrAPI2("GET", "api/v2/homepage/speedtest/data") 13172 .success(function (data) { 13173 try { 13174 let response = data.response; 13175 document.getElementById("homepageOrderSpeedtest").innerHTML = ""; 13176 if (response.data !== null) { 13177 $("#homepageOrderSpeedtest").html(buildSpeedtest(response.data)); 13178 } 13179 } catch (e) { 13180 organizrCatchError(e, data); 13181 } 13182 }) 13183 .fail(function (xhr) { 13184 OrganizrApiError(xhr); 13185 }); 13186 let timeoutTitle = "Speedtest-Homepage"; 13187 if (typeof timeouts[timeoutTitle] !== "undefined") { 13188 clearTimeout(timeouts[timeoutTitle]); 13189 } 13190 timeouts[timeoutTitle] = setTimeout(function () { 13191 homepageSpeedtest(timeout); 13192 }, timeout); 13193 delete timeout; 13194} 13195function buildSpeedtest(array) { 13196 if (array === false) { 13197 return ""; 13198 } 13199 var html = ` 13200 <style> 13201 .shadow-sm { 13202 -webkit-box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075) !important; 13203 box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075) !important; 13204 } 13205 .speedtest-card { 13206 background-color: #2d2c2c; 13207 } 13208 .speedtest-card .text-success { 13209 color: #07db71 !important; 13210 } 13211 .speedtest-card .text-warning { 13212 color: #fca503 !important; 13213 } 13214 .speedtest-card .text-primary { 13215 color: #3e95cd !important; 13216 } 13217 .speedtest-card span.icon { 13218 font-size: 2em; 13219 } 13220 .speedtest-card h5 { 13221 } 13222 13223 .speedtest-card h4, 13224 .speedtest-card h3 { 13225 font-weight: 450; 13226 line-height: 1.2; 13227 } 13228 13229 .speedtest-card .text-muted, 13230 .speedtest-card h5 { 13231 color: #9e9e9e !important; 13232 } 13233 </style> 13234 `; 13235 var current = array.data.current; 13236 var average = array.data.average; 13237 var maximum = array.data.maximum; 13238 var minimum = array.data.minimum; 13239 var options = array.options; 13240 13241 html += ` 13242 <div id="allSpeedtest"> 13243 `; 13244 if (options.titleToggle) { 13245 html += 13246 ` 13247 <div class="row"> 13248 <div class="col-sm-12"> 13249 <h4 class="pull-left homepage-element-title"><span lang="en">` + 13250 array["options"]["title"] + 13251 ` : </h4> 13252 </div> 13253 </div> 13254 `; 13255 } 13256 html += 13257 ` 13258 <div class="row"> 13259 <div class="my-2 col-lg-4 col-md-4 col-sm-12"> 13260 <div class="card speedtest-card shadow-sm mb-3"> 13261 <div class="card-body"> 13262 <div class="d-flex align-items-center justify-content-between"> 13263 <h4>Ping</h4> 13264 <span class="ti-pulse icon text-success" /> 13265 </div> 13266 <div class="text-truncate"> 13267 <h3 class="d-inline">` + 13268 parseFloat(current.ping).toFixed(1) + 13269 `</h3> 13270 <p class="d-inline ml-1 text-white">ms (current)</p> 13271 </div>`; 13272 if (average != undefined) { 13273 html += 13274 ` 13275 <div class="text-truncate text-muted"> 13276 <h5 class="d-inline">` + 13277 parseFloat(average.ping).toFixed(1) + 13278 `</h5> 13279 <p class="d-inline ml-1">ms (average)</p> 13280 </div> 13281 `; 13282 } 13283 if (maximum != undefined) { 13284 html += 13285 ` 13286 <div class="text-truncate text-muted"> 13287 <h5 class="d-inline">` + 13288 parseFloat(maximum.ping).toFixed(1) + 13289 `</h5> 13290 <p class="d-inline ml-1">ms (maximum)</p> 13291 </div> 13292 `; 13293 } 13294 if (minimum != undefined) { 13295 html += 13296 ` 13297 <div class="text-truncate text-muted"> 13298 <h5 class="d-inline">` + 13299 parseFloat(minimum.ping).toFixed(1) + 13300 `</h5> 13301 <p class="d-inline ml-1">ms (minimum)</p> 13302 </div> 13303 `; 13304 } 13305 html += 13306 ` </div> 13307 </div> 13308 </div> 13309 <div class="my-2 col-lg-4 col-md-4 col-sm-12"> 13310 <div class="card speedtest-card shadow-sm mb-3"> 13311 <div class="card-body"> 13312 <div class="d-flex align-items-center justify-content-between"> 13313 <h4>Download</h4>
13314 <span class="ti-download icon text-warning" /> 13315 </div> 13316 <div class="text-truncate"> 13317 <h3 class="d-inline">` + 13318 parseFloat(current.download).toFixed(1) + 13319 `</h3> 13320 <p class="d-inline ml-1 text-white">Mbit/s (current)</p> 13321 </div>`; 13322 if (average != undefined) { 13323 html += 13324 ` 13325 <div class="text-truncate text-muted"> 13326 <h5 class="d-inline">` + 13327 parseFloat(average.download).toFixed(1) + 13328 `</h5> 13329 <p class="d-inline ml-1">Mbit/s (average)</p> 13330 </div> 13331 `; 13332 } 13333 if (maximum != undefined) { 13334 html += 13335 ` 13336 <div class="text-truncate text-muted"> 13337 <h5 class="d-inline">` + 13338 parseFloat(maximum.download).toFixed(1) + 13339 `</h5> 13340 <p class="d-inline ml-1">Mbit/s (maximum)</p> 13341 </div> 13342 `; 13343 } 13344 if (minimum != undefined) { 13345 html += 13346 ` 13347 <div class="text-truncate text-muted"> 13348 <h5 class="d-inline">` + 13349 parseFloat(minimum.download).toFixed(1) + 13350 `</h5> 13351 <p class="d-inline ml-1">Mbit/s (minimum)</p> 13352 </div> 13353 `; 13354 } 13355 html += 13356 ` </div> 13357 </div> 13358 </div> 13359 <div class="my-2 col-lg-4 col-md-4 col-sm-12"> 13360 <div class="card speedtest-card shadow-sm mb-3"> 13361 <div class="card-body"> 13362 <div class="d-flex align-items-center justify-content-between"> 13363 <h4>Upload</h4> 13364 <span class="ti-upload icon text-primary" /> 13365 </div> 13366 <div class="text-truncate"> 13367 <h3 class="d-inline">` + 13368 parseFloat(current.upload).toFixed(1) + 13369 `</h3> 13370 <p class="d-inline ml-1 text-white">Mbit/s (current)</p> 13371 </div>`; 13372 if (average != undefined) { 13373 html += 13374 ` 13375 <div class="text-truncate text-muted"> 13376 <h5 class="d-inline">` + 13377 parseFloat(average.upload).toFixed(1) + 13378 `</h5> 13379 <p class="d-inline ml-1">Mbit/s (average)</p> 13380 </div> 13381 `; 13382 } 13383 if (maximum != undefined) { 13384 html += 13385 ` 13386 <div class="text-truncate text-muted"> 13387 <h5 class="d-inline">` + 13388 parseFloat(maximum.upload).toFixed(1) + 13389 `</h5> 13390 <p class="d-inline ml-1">Mbit/s (maximum)</p> 13391 </div> 13392 `; 13393 } 13394 if (minimum != undefined) { 13395 html += 13396 ` 13397 <div class="text-truncate text-muted"> 13398 <h5 class="d-inline">` + 13399 parseFloat(minimum.upload).toFixed(1) + 13400 `</h5> 13401 <p class="d-inline ml-1">Mbit/s (minimum)</p> 13402 </div> 13403 `; 13404 } 13405 html += ` </div> 13406 </div> 13407 </div> 13408 </div> 13409 </div> 13410 `; 13411 13412 return array ? html : ""; 13413} 13414function buildNetdataItem(array) { 13415 var html = ` 13416 <style> 13417 .all-netdata .easyPieChart-value { 13418 position: absolute; 13419 top: 77px; 13420 width: 100%; 13421 text-align: center; 13422 left: 0; 13423 font-size: 24.4625px; 13424 font-weight: normal; 13425 } 13426 .all-netdata .easyPieChart-title { 13427 position: absolute; 13428 width: 100%; 13429 text-align: center; 13430 left: 0; 13431 font-weight: bold; 13432 } 13433 .all-netdata .easyPieChart-units { 13434 position: absolute; 13435 top: 118px; 13436 width: 100%; 13437 text-align: center; 13438 left: 0; 13439 font-size: 15px; 13440 font-weight: normal; 13441 } 13442 13443 .all-netdata .gauge-chart .gauge-value { 13444 position: relative; 13445 width: 100%; 13446 text-align: center; 13447 top: 30px; 13448 color: #dcdcdc; 13449 font-weight: bold; 13450 left: 0; 13451 font-size: 26px; 13452 } 13453 13454 .all-netdata .gauge-chart .gauge-title { 13455 position: relative; 13456 width: 100%; 13457 text-align: center; 13458 top: -10px; 13459 //color: #fff; 13460 font-weight: bold; 13461 left: 0; 13462 font-size: 15px; 13463 } 13464 13465 .all-netdata .chart-lg .gauge-chart .gauge-value { 13466 top: 70px; 13467 font-size: 26px; 13468 } 13469 13470 .all-netdata .chart-lg .gauge-chart .gauge-title { 13471 top: 45px; 13472 font-size: 15px; 13473 } 13474 13475 .all-netdata .chart-md .gauge-chart .gauge-value { 13476 top: 65px; 13477 font-size: 26px; 13478 } 13479 13480 .all-netdata .chart-md .gauge-chart .gauge-title { 13481 top: 45px; 13482 font-size: 15px; 13483 } 13484 13485 .all-netdata .chart-sm .gauge-chart .gauge-value { 13486 top: 65px; 13487 font-size: 26px; 13488 } 13489 13490 .all-netdata .chart-sm .gauge-chart .gauge-title { 13491 top: 45px; 13492 font-size: 15px; 13493 } 13494 13495 .all-netdata .chart-lg, 13496 .all-netdata .chart-md, 13497 .all-netdata .chart-sm { 13498 display: inline-block; 13499 margin: 15px; 13500 } 13501 13502 .all-netdata .chart-lg, 13503 .all-netdata .chart-lg .chart { 13504 height: 180px; 13505 width: 180px; 13506 } 13507 13508 .all-netdata .chart-md, 13509 .all-netdata .chart-md .chart { 13510 height: 160px; 13511 width: 160px; 13512 } 13513 13514 .all-netdata .chart-sm, 13515 .all-netdata .chart-sm .chart { 13516 height: 140px; 13517 width: 140px; 13518 } 13519 13520 .all-netdata .chart-lg .gauge-chart,
13521 .all-netdata .gauge-cont.chart-lg { 13522 //height: 300px; 13523 width: 300px; 13524 } 13525 13526 .all-netdata .chart-md .gauge-chart, 13527 .all-netdata .gauge-cont.chart-md { 13528 //height: 275px; 13529 width: 275px; 13530 } 13531 13532 .all-netdata .chart-sm .gauge-chart, 13533 .all-netdata .gauge-cont.chart-sm { 13534 //height: 250px; 13535 width: 250px; 13536 } 13537 13538 .all-netdata .chart-lg .easyPieChart-title { 13539 top: 37px; 13540 font-size: 15px; 13541 } 13542 13543 .all-netdata .chart-md .easyPieChart-title { 13544 top: 33px; 13545 font-size: 13.5px; 13546 } 13547 13548 .all-netdata .chart-sm .easyPieChart-title { 13549 top: 30px; 13550 font-size: 12px; 13551 } 13552 13553 .all-netdata .chart-lg .easyPieChart-value { 13554 top: 75px; 13555 font-size: 24.4625px; 13556 } 13557 13558 .all-netdata .chart-md .easyPieChart-value { 13559 top: 65px; 13560 font-size: 24.4625px; 13561 } 13562 13563 .all-netdata .chart-sm .easyPieChart-value { 13564 top: 55px; 13565 font-size: 24.4625px; 13566 } 13567 13568 .all-netdata .chart-lg .easyPieChart-units { 13569 top: 130px; 13570 font-size: 15px; 13571 } 13572 13573 .all-netdata .chart-md .easyPieChart-units { 13574 top: 108px; 13575 font-size: 15px; 13576 } 13577 13578 .all-netdata .chart-sm .easyPieChart-units { 13579 top: 95px; 13580 font-size: 15px; 13581 } 13582 </style> 13583 `; 13584 13585 var buildEasyPieChart = function (e, i, size, easySize, display) { 13586 return ( 13587 ` 13588 <div class="chart-` + 13589 size + 13590 ` my-3 text-center ` + 13591 display + 13592 `"> 13593 <div class="chart" id="easyPieChart` + 13594 (i + 1) + 13595 `" data-percent="` + 13596 e.percent + 13597 `"> 13598 <span class="easyPieChart-title">` + 13599 e.title + 13600 `</span> 13601 <span class="easyPieChart-value" id="easyPieChart` + 13602 (i + 1) + 13603 `Value">` + 13604 parseFloat(e.value).toFixed(1) + 13605 `</span> 13606 <span class="easyPieChart-units" id="easyPieChart` + 13607 (i + 1) + 13608 `Units">` + 13609 e.units + 13610 `</span> 13611 </div> 13612 </div> 13613 <script> 13614 $(function() { 13615 var opts = { 13616 size: ` + 13617 easySize + 13618 `, 13619 lineWidth: 7, 13620 scaleColor: false, 13621 barColor: '#` + 13622 e.colour + 13623 `', 13624 trackColor: '#636363', 13625 }; 13626 if(` + 13627 e.percent + 13628 ` == 0) { 13629 opts.lineCap = 'butt'; 13630 } 13631 $('#easyPieChart` + 13632 (i + 1) + 13633 `').easyPieChart(opts); 13634 }); 13635 </script> 13636 ` 13637 ); 13638 }; 13639 13640 var buildGaugeChart = function (e, i, size, easySize, display) { 13641 switch (size) { 13642 case "lg": 13643 easySize = 300; 13644 break; 13645 case "sm": 13646 easySize = 275; 13647 break; 13648 case "md": 13649 default: 13650 easySize = 250; 13651 break; 13652 } 13653 return ( 13654 ` 13655 <div class="mx-0 gauge-cont chart-` + 13656 size + 13657 ` my-3 text-center ` + 13658 display + 13659 `"> 13660 <div class="gauge-chart text-center"> 13661 <span class="gauge-title d-block" id="gaugeChart` + 13662 (i + 1) + 13663 `Title">` + 13664 e.title + 13665 `</span> 13666 <span class="gauge-value d-block" id="gaugeChart` + 13667 (i + 1) + 13668 `Value">` + 13669 parseFloat(e.value).toFixed(1) + 13670 `</span> 13671 <canvas id="gaugeChart` + 13672 (i + 1) + 13673 `" style="width: 100%"></canvas> 13674 </div> 13675 </div> 13676 <script> 13677 $(function() { 13678 var opts = { 13679 angle: 0.14, // The span of the gauge arc 13680 lineWidth: 0.54, // The line thickness 13681 radiusScale: 1, // Relative radius 13682 pointer: { 13683 length: 0.77, // // Relative to gauge radius 13684 strokeWidth: 0.075, // The thickness 13685 color: '#A1A1A1' // Fill color 13686 }, 13687 limitMax: false, // If false, max value increases automatically if value > maxValue 13688 limitMin: false, // If true, the min value of the gauge will be fixed 13689 colorStart: '#` + 13690 e.colour + 13691 `', // Colors 13692 colorStop: '#` + 13693 e.colour + 13694 `', // just experiment with them 13695 strokeColor: '#636363', // to see which ones work best for you 13696 generateGradient: true, 13697 highDpiSupport: true, // High resolution support 13698 13699 }; 13700 var target = document.getElementById('gaugeChart` + 13701 (i + 1) + 13702 `'); // your canvas element 13703 var gauge = new Gauge(target).setOptions(opts); // create sexy gauge! 13704 gauge.maxValue = ` + 13705 e.max + 13706 `; // set max gauge value 13707 gauge.setMinValue(0); // Prefer setter over gauge.minValue = 0 13708 gauge.animationSpeed = 8; // set animation speed (32 is default value) 13709 gauge.set(` + 13710 e.percent + 13711 `); // set actual value 13712 window.netdata[` + 13713 (i + 1) + 13714 `] = gauge 13715 }); 13716 </script> 13717 ` 13718 ); 13719 }; 13720 13721 array.forEach((e, i) => { 13722 var size = e.size; 13723 var easySize; 13724 if (size == "") { 13725 size = "md"; 13726 } 13727 switch (size) { 13728 case "lg": 13729 easySize = 180; 13730 break; 13731 case "sm": 13732 easySize = 140; 13733 break; 13734 case "md": 13735 default: 13736 easySize = 160; 13737 break; 13738 } 13739 13740 var display = " "; 13741 if (e.lg) { 13742 display += " d-xl-inline-block d-lg-inline-block"; 13743 } else { 13744 display += " d-xl-none d-lg-none d-none"; 13745 } 13746 if (e.md) { 13747 display += " d-md-inline-block"; 13748 } else { 13749 display += " d-md-none d-none"; 13750 } 13751 if (e.sm) { 13752 display += " d-sm-inline-block d-xs-inline-block"; 13753 } else { 13754 display += " d-sm-none d-xs-none d-none"; 13755 } 13756 display += " "; 13757 13758 if (e.error) { 13759 organizrConsole( 13760 "Netdata Function", 13761 "(Chart " + (i + 1) + "): " + e.error, 13762 "error" 13763 ); 13764 } else if (e.chart == "easypiechart") { 13765 html += buildEasyPieChart(e, i, size, easySize, display); 13766 } else if (e.chart == "gauge") { 13767 html += buildGaugeChart(e, i, size, easySize, display); 13768 } 13769 }); 13770 13771 return html; 13772} 13773function buildNetdata(array) { 13774 var data = array.data; 13775 if (array === false) { 13776 return ""; 13777 } 13778 window.netdata = []; 13779 13780 var html = ` 13781 <style> 13782 .clearfix { 13783 *zoom: 1; 13784 } 13785 .all-netdata .clearfix:before, 13786 .all-netdata .clearfix:after { 13787 display: table; 13788 content: ""; 13789 } 13790 .all-netdata .clearfix:after { 13791 clear: both; 13792 } 13793 13794 .all-netdata .easyPieChart { 13795 position: relative; 13796 text-align: center; 13797 } 13798 13799 .all-netdata .easyPieChart canvas { 13800 position: absolute; 13801 top: 0; 13802 left: 0; 13803 } 13804 13805 .all-netdata .chart { 13806 float: left; 13807 //margin: 10px; 13808 } 13809 13810 .all-netdata .percentage, 13811 .all-netdata .label { 13812 text-align: center; 13813 color: #333; 13814 font-weight: 100; 13815 font-size: 1.2em; 13816 margin-bottom: 0.3em; 13817 } 13818 13819 .all-netdata .credits { 13820 padding-top: 0.5em; 13821 clear: both; 13822 color: #999; 13823 } 13824 13825 .all-netdata .credits a { 13826 color: #333; 13827 } 13828 13829 .all-netdata .dark { 13830 background: #333; 13831 } 13832 13833 .all-netdata .dark .percentage-light, 13834 .all-netdata .dark .label { 13835 text-align: center; 13836 color: #999; 13837 font-weight: 100; 13838 font-size: 1.2em; 13839 margin-bottom: 0.3em; 13840 } 13841 13842 13843 .all-netdata .button { 13844 -webkit-box-shadow: inset 0 0 1px #000, inset 0 1px 0 1px rgba(255,255,255,0.2), 0 1px 1px -1px rgba(0, 0, 0, .5); 13845 -moz-box-shadow: inset 0 0 1px #000, inset 0 1px 0 1px rgba(255,255,255,0.2), 0 1px 1px -1px rgba(0, 0, 0, .5); 13846 box-shadow: inset 0 0 1px #000, inset 0 1px 0 1px rgba(255,255,255,0.2), 0 1px 1px -1px rgba(0, 0, 0, .5); 13847 -webkit-border-radius: 3px; 13848 -moz-border-radius: 3px; 13849 border-radius: 3px; 13850 padding: 6px 20px; 13851 font-weight: bold; 13852 text-transform: uppercase; 13853 display: block; 13854 margin: 0 auto 2em; 13855 max-width: 200px; 13856 text-align: center; 13857 background-color: #5c5c5c; 13858 background-image: -moz-linear-gradient(top, #666666, #4d4d4d);
13859 background-image: -ms-linear-gradient(top, #666666, #4d4d4d); 13860 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#666666), to(#4d4d4d)); 13861 background-image: -webkit-linear-gradient(top, #666666, #4d4d4d); 13862 background-image: -o-linear-gradient(top, #666666, #4d4d4d); 13863 background-image: linear-gradient(top, #666666, #4d4d4d); 13864 background-repeat: repeat-x; 13865 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#666666', endColorstr='#4d4d4d', GradientType=0); 13866 color: #ffffff; 13867 text-shadow: 0 1px 1px #333333; 13868 } 13869 .all-netdata .button:hover { 13870 color: #ffffff; 13871 text-decoration: none; 13872 background-color: #616161; 13873 background-image: -moz-linear-gradient(top, #6b6b6b, #525252); 13874 background-image: -ms-linear-gradient(top, #6b6b6b, #525252); 13875 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6b6b6b), to(#525252)); 13876 background-image: -webkit-linear-gradient(top, #6b6b6b, #525252); 13877 background-image: -o-linear-gradient(top, #6b6b6b, #525252); 13878 background-image: linear-gradient(top, #6b6b6b, #525252); 13879 background-repeat: repeat-x; 13880 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#6b6b6b', endColorstr='#525252', GradientType=0); 13881 } 13882 .all-netdata .button:active { 13883 background-color: #575757; 13884 background-image: -moz-linear-gradient(top, #616161, #474747); 13885 background-image: -ms-linear-gradient(top, #616161, #474747); 13886 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#616161), to(#474747)); 13887 background-image: -webkit-linear-gradient(top, #616161, #474747); 13888 background-image: -o-linear-gradient(top, #616161, #474747); 13889 background-image: linear-gradient(top, #616161, #474747); 13890 background-repeat: repeat-x; 13891 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#616161', endColorstr='#474747', GradientType=0); 13892 -webkit-transform: translate(0, 1px); 13893 -moz-transform: translate(0, 1px); 13894 -ms-transform: translate(0, 1px); 13895 -o-transform: translate(0, 1px); 13896 transform: translate(0, 1px); 13897 } 13898 .all-netdata .button:disabled { 13899 background-color: #dddddd; 13900 background-image: -moz-linear-gradient(top, #e7e7e7, #cdcdcd); 13901 background-image: -ms-linear-gradient(top, #e7e7e7, #cdcdcd); 13902 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e7e7e7), to(#cdcdcd)); 13903 background-image: -webkit-linear-gradient(top, #e7e7e7, #cdcdcd); 13904 background-image: -o-linear-gradient(top, #e7e7e7, #cdcdcd); 13905 background-image: linear-gradient(top, #e7e7e7, #cdcdcd); 13906 background-repeat: repeat-x; 13907 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e7e7e7', endColorstr='#cdcdcd', GradientType=0); 13908 color: #939393; 13909 text-shadow: 0 1px 1px #fff; 13910 } 13911 </style> 13912 `; 13913 13914 html += ` 13915 <div class="row m-b-30"> 13916 13917 <div class="d-block text-center all-netdata"> 13918 `; 13919 html += buildNetdataItem(data); 13920 html += ` 13921 </div> 13922 13923 </div>`; 13924 13925 return array ? html : ""; 13926} 13927function homepageNetdata(timeout) { 13928 var timeout = 13929 typeof timeout !== "undefined" 13930 ? timeout 13931 : activeInfo.settings.homepage.refresh.homepageNetdataRefresh; 13932 organizrAPI2("GET", "api/v2/homepage/netdata/data") 13933 .success(function (data) { 13934 try { 13935 let response = data.response; 13936 if (!tryUpdateNetdata(response.data.data)) { 13937 document.getElementById("homepageOrderNetdata").innerHTML = ""; 13938 if (response.data !== null) { 13939 $("#homepageOrderNetdata").html(buildNetdata(response.data)); 13940 } 13941 } 13942 } catch (e) { 13943 organizrCatchError(e, data); 13944 } 13945 }) 13946 .fail(function (xhr) { 13947 OrganizrApiError(xhr); 13948 }); 13949 var timeoutTitle = "Netdata-Homepage"; 13950 if (typeof timeouts[timeoutTitle] !== "undefined") { 13951 clearTimeout(timeouts[timeoutTitle]); 13952 } 13953 timeouts[timeoutTitle] = setTimeout(function () { 13954 homepageNetdata(timeout); 13955 }, timeout); 13956 delete timeout; 13957} 13958function tryUpdateNetdata(array) { 13959 var existing = false;
13960 array.forEach((e, i) => { 13961 var id = i + 1; 13962 if (e.chart == "easypiechart") { 13963 if ($("#easyPieChart" + id).length) { 13964 $("#easyPieChart" + id) 13965 .data("easyPieChart") 13966 .update(e.percent); 13967 $("#easyPieChart" + id + "Value").html(parseFloat(e.value).toFixed(1)); 13968 existing = true; 13969 } 13970 } else if (e.chart == "gauge") { 13971 if (window.netdata) { 13972 if (window.netdata[i + 1]) { 13973 window.netdata[i + 1].set(e.percent); // set actual value 13974 $("#gaugeChart" + (i + 1) + "Value").html( 13975 parseFloat(e.value).toFixed(1) 13976 ); 13977 existing = true; 13978 } 13979 } else { 13980 existing = false; 13981 } 13982 } else { 13983 existing = false; 13984 } 13985 }); 13986 return existing; 13987} 13988function homepageJackett() { 13989 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 13990 var header = ` 13991 <div class="col-md-12"> 13992 <h2 class="text-white m-0 pull-left text-uppercase"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/jackett.png"> <span lang="en">Jackett</span> </h2> 13993 <hr class="hidden-xs"><div class="clearfix"></div> 13994 </div> 13995 <div class="clearfix"></div> 13996 <script>$('.jackett-panel').removeClass('panel panel-default');</script> 13997 `; 13998 } else { 13999 var header = ` 14000 <div class="panel-heading bg-info p-t-10 p-b-10"> 14001 <span class="pull-left m-t-5 text-white"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/jackett.png" > <span lang="en">Jackett</span></span> 14002 <div class="clearfix"></div> 14003 </div> 14004 `; 14005 } 14006 let html = 14007 ` 14008 <div id="jackettSearch" class="row"> 14009 <div class="col-lg-12"> 14010 <div class="jackett-panel panel panel-default"> 14011 ` + 14012 header + 14013 ` 14014 <div class="panel-wrapper p-b-0 collapse in"> 14015 <div class="white-box"> 14016 <h3 class="box-title m-b-0" lang="en">Search</h3> 14017 14018 <form onsubmit="searchJackett();return false;"> 14019 <div class="input-group m-b-30"> 14020 <span class="input-group-btn hidden"> 14021 <button type="button" class="btn waves-effect waves-light btn-primary clearJackett" onclick="clearJackett();"><i class="fa fa-eraser"></i></button> 14022 </span> 14023 <input id="jackett-search-query" class="form-control" placeholder="Search for..." lang="en"> 14024 <span class="input-group-btn"> 14025 <button type="submit" class="btn waves-effect waves-light btn-info"><i class="fa fa-search"></i></button> 14026 </span> 14027 </div> 14028 14029 </form> 14030 14031 <div class="jackettDataTable hidden"> 14032 <h3 class="box-title m-b-0" lang="en">Results</h3> 14033 <div class="table-responsive"> 14034 <table id="jackettDataTable" class="table table-striped"> 14035 <thead> 14036 <tr> 14037 <th lang="en">Date</th> 14038 <th lang="en">Tracker</th> 14039 <th lang="en">Name</th> 14040 <th lang="en">Size</th> 14041 <th lang="en">Files</th> 14042 <th lang="en">Grabs</th> 14043 <th lang="en">Seeds</th> 14044 <th lang="en">Leechers</th> 14045 <th lang="en">Download</th> 14046 </tr> 14047 </thead> 14048 <tbody></tbody> 14049 </table> 14050 </div> 14051 </div> 14052 </div> 14053 14054 </div> 14055 </div> 14056 </div> 14057 </div> 14058 `; 14059 $("#homepageOrderJackett").html(html); 14060} 14061function clearJackett() { 14062 $("#jackett-search-query").val(""); 14063 $(".clearJackett").parent().addClass("hidden"); 14064 $("#jackettDataTable").DataTable().destroy(); 14065 $(".jackettDataTable").addClass("hidden"); 14066} 14067function searchJackett() { 14068 let query = $("#jackett-search-query").val(); 14069 if (query !== "") { 14070 $(".jackettDataTable").removeClass("hidden"); 14071 //ajaxloader('#jackettSearch .panel-wrapper', 'in'); 14072 ajaxblocker(".jackett-panel .white-box", "in", "Searching..."); 14073 } else { 14074 return false;
14075 } 14076 $.fn.dataTable.ext.errMode = "none"; 14077 $("#jackettDataTable").DataTable().destroy(); 14078 let preferBlackholeDownload = 14079 activeInfo.settings.homepage.jackett.homepageJackettBackholeDownload; 14080 let jackettTable = $("#jackettDataTable") 14081 .on("error.dt", function (e, settings, techNote, message) { 14082 console.log("An error has been reported by DataTables: ", message); 14083 $("#jackettDataTable").DataTable().destroy(); 14084 ajaxblocker(".jackett-panel .white-box"); 14085 $(".clearJackett").parent().removeClass("hidden"); 14086 window.message( 14087 "Jackett Connection Error", 14088 "", 14089 activeInfo.settings.notifications.position, 14090 "#FFF", 14091 "error", 14092 "5000" 14093 ); 14094 }) 14095 .DataTable({ 14096 ajax: { 14097 url: "api/v2/homepage/jackett/" + query, 14098 dataSrc: function (json) { 14099 return json.response.data.content.Results; 14100 }, 14101 }, 14102 columns: [ 14103 { 14104 data: "PublishDate", 14105 render: function (data, type, row) { 14106 if (type === "display" || type === "filter") { 14107 var m = moment.tz(data, activeInfo.timezone); 14108 return moment.utc(m, "YYYY-MM-DD hh:mm[Z]").local().fromNow(); 14109 } 14110 return data; 14111 }, 14112 }, 14113 { data: "Tracker" }, 14114 { 14115 data: "Title", 14116 render: function (data, type, row) { 14117 if (row.Details !== null) { 14118 return ( 14119 '<a href="' + row.Details + '" target="_blank">' + data + "</a>" 14120 ); 14121 } else { 14122 return data; 14123 } 14124 }, 14125 }, 14126 { 14127 data: "Size", 14128 render: function (data, type, row) { 14129 if (type === "display" || type === "filter") { 14130 return humanFileSize(data, false); 14131 } 14132 return humanFileSize(data, false); 14133 }, 14134 }, 14135 { data: "Files" }, 14136 { data: "Grabs" }, 14137 { data: "Seeders" }, 14138 { data: "Peers" }, 14139 { 14140 data: "MagnetUri", 14141 render: function (data, type, row) { 14142 if (type === "display" || type === "filter") { 14143 if ( 14144 preferBlackholeDownload === true && 14145 row.BlackholeLink !== null 14146 ) { 14147 return ( 14148 "<a onclick=\"jackettDownload('" + 14149 row.BlackholeLink + 14150 '\');return false;" href="#"><i class="fa fa-cloud-download"></i></a>' 14151 ); 14152 } else if (data !== null) { 14153 return ( 14154 '<a href="' + 14155 data + 14156 '" target="_blank"><i class="fa fa-magnet"></i></a>' 14157 ); 14158 } else if (row.Details !== null) { 14159 return ( 14160 '<a href="' + 14161 row.Details + 14162 '" target="_blank"><i class="fa fa-cloud-download"></i></a>' 14163 ); 14164 } else if (row.Guid !== null) { 14165 return ( 14166 '<a href="' + 14167 row.Guid + 14168 '" target="_blank"><i class="fa fa-cloud-download"></i></a>' 14169 ); 14170 } else if (row.Link !== null) { 14171 return ( 14172 '<a href="' + 14173 row.Link + 14174 '" target="_blank"><i class="fa fa-download"></i></a>' 14175 ); 14176 } else { 14177 return "No Download Link"; 14178 } 14179 } 14180 return data; 14181 }, 14182 }, 14183 ], 14184 order: [[0, "desc"]], 14185 initComplete: function (settings, json) { 14186 //ajaxloader(); 14187 ajaxblocker(".jackett-panel .white-box"); 14188 $(".clearJackett").parent().removeClass("hidden"); 14189 }, 14190 }); 14191} 14192function jackettDownload(url) { 14193 let blackholeLink = url.substring(url.indexOf("/bh/")); 14194 var post = { 14195 url: blackholeLink, 14196 }; 14197 organizrAPI2("POST", "api/v2/homepage/jackett/download/", post, true) 14198 .success(function () { 14199 message( 14200 "Torrent downloaded", 14201 "", 14202 activeInfo.settings.notifications.position, 14203 "#FFF", 14204 "success", 14205 "5000" 14206 ); 14207 }) 14208 .fail(function (xhr) { 14209 OrganizrApiError(xhr, "Error downloading torrent"); 14210 }); 14211} 14212function homepageProwlarr() { 14213 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 14214 var header = ` 14215 <div class="col-md-12"> 14216 <h2 class="text-white m-0 pull-left text-uppercase"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/prowlarr.png"> <span lang="en">Prowlarr</span> </h2> 14217 <hr class="hidden-xs"><div class="clearfix"></div> 14218 </div> 14219 <div class="clearfix"></div> 14220 <script>$('.prowlarr-panel').removeClass('panel panel-default');</script> 14221 `; 14222 } else { 14223 var header = ` 14224 <div class="panel-heading bg-info p-t-10 p-b-10"> 14225 <span class="pull-left m-t-5 text-white"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/prowlarr.png" > <span lang="en">Prowlarr</span></span> 14226 <div class="clearfix"></div> 14227 </div> 14228 `; 14229 } 14230 let html = 14231 ` 14232 <div id="prowlarrSearch" class="row"> 14233 <div class="col-lg-12"> 14234 <div class="prowlarr-panel panel panel-default"> 14235 ` + 14236 header + 14237 ` 14238 <div class="panel-wrapper p-b-0 collapse in"> 14239 <div class="white-box"> 14240 <h3 class="box-title m-b-0" lang="en">Search</h3> 14241 14242 <form onsubmit="searchProwlarr();return false;"> 14243 <div class="input-group m-b-30"> 14244 <span class="input-group-btn hidden"> 14245 <button type="button" class="btn waves-effect waves-light btn-primary clearProwlarr" onclick="clearProwlarr();"><i class="fa fa-eraser"></i></button> 14246 </span> 14247 <input id="prowlarr-search-query" class="form-control" placeholder="Search for..." lang="en">
14248 <span class="input-group-btn"> 14249 <button type="submit" class="btn waves-effect waves-light btn-info"><i class="fa fa-search"></i></button> 14250 </span> 14251 </div> 14252 14253 </form> 14254 14255 <div class="prowlarrDataTable hidden"> 14256 <h3 class="box-title m-b-0" lang="en">Results</h3> 14257 <div class="table-responsive"> 14258 <table id="prowlarrDataTable" class="table table-striped"> 14259 <thead> 14260 <tr> 14261 <th lang="en">Date</th> 14262 <th lang="en">Indexer</th> 14263 <th lang="en">Title</th> 14264 <th lang="en">Size</th> 14265 <th lang="en">Grabs</th> 14266 <th lang="en">Seeders</th> 14267 <th lang="en">Leechers</th> 14268 <th lang="en">Download</th> 14269 </tr> 14270 </thead> 14271 <tbody></tbody> 14272 </table> 14273 </div> 14274 </div> 14275 </div> 14276 14277 </div> 14278 </div> 14279 </div> 14280 </div> 14281 `; 14282 $("#homepageOrderProwlarr").html(html); 14283} 14284function clearProwlarr() { 14285 $("#prowlarr-search-query").val(""); 14286 $(".clearProwlarr").parent().addClass("hidden"); 14287 $("#prowlarrDataTable").DataTable().destroy(); 14288 $(".prowlarrDataTable").addClass("hidden"); 14289} 14290function searchProwlarr() { 14291 let query = $("#prowlarr-search-query").val(); 14292 if (query !== "") { 14293 $(".prowlarrDataTable").removeClass("hidden"); 14294 ajaxloader("#prowlarrSearch .panel-wrapper", "in"); 14295 } else { 14296 return false; 14297 } 14298 $.fn.dataTable.ext.errMode = "none"; 14299 $("#prowlarrDataTable").DataTable().destroy(); 14300 let preferBlackholeDownload = 14301 activeInfo.settings.homepage.prowlarr.homepageProwlarrBackholeDownload; 14302 let prowlarrTable = $("#prowlarrDataTable") 14303 .on("error.dt", function (e, settings, techNote, message) { 14304 console.log("An error has been reported by DataTables: ", message); 14305 }) 14306 .DataTable({ 14307 ajax: { 14308 url: "api/v2/homepage/prowlarr/" + query, 14309 dataSrc: function (json) { 14310 return json.response.data.content; 14311 }, 14312 }, 14313 columns: [ 14314 { 14315 data: "publishDate", 14316 render: function (data, type, row) { 14317 if (type === "display" || type === "filter") { 14318 var m = moment.tz(data, activeInfo.timezone); 14319 return moment.utc(m, "YYYY-MM-DD hh:mm[Z]").local().fromNow(); 14320 } 14321 return data; 14322 }, 14323 }, 14324 { data: "indexer" }, 14325 { 14326 data: "title", 14327 render: function (data, type, row) { 14328 if (row.Details !== null) { 14329 return ( 14330 '<a href="' + 14331 row["infoUrl"] + 14332 '" target="_blank">' + 14333 data + 14334 "</a>" 14335 ); 14336 } else { 14337 return data; 14338 } 14339 }, 14340 }, 14341 { 14342 data: "size", 14343 render: function (data) { 14344 return humanFileSize(data, false); 14345 }, 14346 }, 14347 { data: "grabs" }, 14348 { data: "seeders" }, 14349 { data: "leechers" }, 14350 { 14351 data: "downloadUrl", 14352 render: function (data, type, row) { 14353 if (type === "display" || type === "filter") { 14354 if (data !== null) { 14355 if (preferBlackholeDownload === true && row.guid !== null) { 14356 return ( 14357 "<a onclick=\"prowlarrDownload('" + 14358 row.guid + 14359 "," + 14360 row.indexerId + 14361 '\');return false;" href="#"><i class="fa fa-cloud-download"></i></a>' 14362 ); 14363 } else { 14364 return ( 14365 '<a href="' + 14366 data + 14367 '" target="_blank"><i class="fa fa-download"></i></a>' 14368 ); 14369 } 14370 } else { 14371 return "No Download Link"; 14372 } 14373 } 14374 return data; 14375 }, 14376 }, 14377 ], 14378 order: [[5, "desc"]], 14379 initComplete: function (settings, json) { 14380 ajaxloader(); 14381 //ajaxblocker('.prowlarr-panel .white-box'); 14382 $(".clearProwlarr").parent().removeClass("hidden"); 14383 }, 14384 }); 14385} 14386function prowlarrDownload(url) { 14387 const args = url.split(","); 14388 var post = { 14389 guid: args[0], 14390 indexerId: args[1], 14391 };
14392 organizrAPI2("POST", "api/v2/homepage/prowlarr/download/", post, true) 14393 .success(function () { 14394 message( 14395 "Torrent downloaded", 14396 "", 14397 activeInfo.settings.notifications.position, 14398 "#FFF", 14399 "success", 14400 "5000" 14401 ); 14402 }) 14403 .fail(function (xhr) { 14404 OrganizrApiError(xhr, "Error downloading torrent"); 14405 }); 14406} 14407function homepageOctoprint(timeout) { 14408 var timeout = 14409 typeof timeout !== "undefined" 14410 ? timeout 14411 : activeInfo.settings.homepage.refresh.homepageOctoprintRefresh; 14412 organizrAPI2("GET", "api/v2/homepage/octoprint/data") 14413 .success(function (data) { 14414 try { 14415 let response = data.response; 14416 document.getElementById("homepageOrderOctoprint").innerHTML = ""; 14417 if (response.data !== null) { 14418 $("#homepageOrderOctoprint").html(buildOctoprint(response.data)); 14419 } 14420 } catch (e) { 14421 organizrCatchError(e, data); 14422 } 14423 }) 14424 .fail(function (xhr) { 14425 OrganizrApiError(xhr); 14426 }); 14427 let timeoutTitle = "Octoprint-Homepage"; 14428 if (typeof timeouts[timeoutTitle] !== "undefined") { 14429 clearTimeout(timeouts[timeoutTitle]); 14430 } 14431 timeouts[timeoutTitle] = setTimeout(function () { 14432 homepageOctoprint(timeout); 14433 }, timeout); 14434 delete timeout; 14435} 14436function buildOctoprint(array) { 14437 var menu = `<ul class="nav customtab nav-tabs pull-right" role="tablist">`; 14438 var headerAlt = ""; 14439 var header = ""; 14440 var content = ""; 14441 var webcamUrl = ""; 14442 var webcamHtml = ""; 14443 var css = ` 14444 <style> 14445 .octoprint-webcam { 14446 max-height: 400px; 14447 max-width: 100%; 14448 float: right; 14449 } 14450 .octoprint-block { 14451 margin-left: 0px; 14452 margin-right: 0px; 14453 } 14454 .octoprint-button-spacer { 14455 padding-right: 46px; 14456 } 14457 </style> 14458 `; 14459 menu += ` 14460 <li role="presentation" class="active" ><a href="" aria-controls="home" role="tab" data-toggle="tab" aria-expanded="true" onclick="homepageOctoprint();"><span class="visible-xs"><i class="ti-download"></i></span><span class="hidden-xs">REFRESH</span></a></li> 14461 `; 14462 menu += "</ul>"; 14463 if (activeInfo.settings.homepage.options.alternateHomepageHeaders) { 14464 var headerAlt = 14465 ` 14466 <div class="col-md-12"> 14467 <h2 class="text-white m-0 pull-left text-uppercase"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/octoprint.png"> </h2> 14468 ` + 14469 menu + 14470 ` 14471 <hr class="hidden-xs"><div class="clearfix"></div> 14472 </div> 14473 <div class="clearfix"></div> 14474 `; 14475 } else { 14476 var header = 14477 ` 14478 <div class="white-box bg-info m-b-0 p-b-0 p-t-10 mailbox-widget"> 14479 <h2 class="text-white m-0 pull-left text-uppercase"><img class="lazyload homepageImageTitle" data-src="plugins/images/tabs/octoprint.png"> </h2> 14480 ` + 14481 menu + 14482 ` 14483 <div class="clearfix"></div> 14484 </div> 14485 `; 14486 } 14487 content = "<p>State: " + array.data.job.state + "</p>"; 14488 if (array.data.job.state == "Printing") { 14489 content += "<p>File: " + array.data.job.job.file.display + "</p>"; 14490 content += 14491 "<p>Progress: " + 14492 parseFloat(array.data.job.progress.completion).toFixed(0) + 14493 "%</p>"; 14494 content += 14495 "<p>Approx. Total Print Time: " + 14496 octoprintFormatTime(array.data.job.job.estimatedPrintTime) + 14497 "</p>"; 14498 content += 14499 "<p>Print Time Left: " + 14500 octoprintFormatTime(array.data.job.progress.printTimeLeft) + 14501 "</p>"; 14502 } 14503 if (array.data.settings.webcam.webcamEnabled) { 14504 webcamUrl = array.data.settings.webcam.streamUrl; 14505 if (webcamUrl[0] == "/") { 14506 webcamUrl = array.data.url + webcamUrl; 14507 } 14508 } 14509 if (webcamUrl) { 14510 var webcamHtml = 14511 `<div class="col-lg-4"><img class="octoprint-webcam" src="` + 14512 webcamUrl + 14513 `"></div>`; 14514 } 14515 return ( 14516 css + 14517 ` 14518 <div class="row"> 14519 ` + 14520 headerAlt + 14521 ` 14522 <div class="col-lg-12"> 14523 ` + 14524 header + 14525 ` 14526 <div class="row octoprint-block white-box"> 14527 <div class="col-lg-8 text-white"> 14528 <div class="tab-content m-t-0">` + 14529 content + 14530 `</div> 14531 </div> 14532 ` + 14533 webcamHtml + 14534 ` 14535 </div> 14536 </div> 14537 </div> 14538 ` 14539 ); 14540} 14541function octoprintFormatTime(seconds) { 14542 var format = ""; 14543 var days = Math.floor(moment.duration(seconds, "seconds").asDays()); 14544 var hours = Math.floor(moment.duration(seconds, "seconds").asHours()); 14545 var minutes = moment.duration(seconds, "seconds").minutes(); 14546 var seconds = moment.duration(seconds, "seconds").seconds(); 14547 if (days > 0) { 14548 format += days + " " + octoprintPluralize("day", days) + " "; 14549 } 14550 if (hours > 0) { 14551 format += hours + " " + octoprintPluralize("hour", hours) + " "; 14552 } 14553 if (minutes > 0) { 14554 format += minutes + " " + octoprintPluralize("minute", minutes) + " "; 14555 } 14556 if (seconds > 0) { 14557 format += seconds + " " + octoprintPluralize("second", seconds) + " "; 14558 } 14559 return format; 14560} 14561 14562function octoprintPluralize(s, n) { 14563 if (n > 1) { 14564 return s + "s"; 14565 } 14566 return s; 14567} 14568function pad(n, width, z) { 14569 z = z || "0"; 14570 n = n + ""; 14571 return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; 14572} 14573// Thanks Swifty! 14574function PopupCenter(url, title, w, h) { 14575 // Fixes dual-screen position Most browsers Firefox 14576 var dualScreenLeft = 14577 window.screenLeft != undefined ? window.screenLeft : window.screenX; 14578 var dualScreenTop = 14579 window.screenTop != undefined ? window.screenTop : window.screenY; 14580 var width = window.innerWidth 14581 ? window.innerWidth 14582 : document.documentElement.clientWidth 14583 ? document.documentElement.clientWidth 14584 : screen.width; 14585 var height = window.innerHeight 14586 ? window.innerHeight 14587 : document.documentElement.clientHeight 14588 ? document.documentElement.clientHeight 14589 : screen.height; 14590 var left = width / 2 - w / 2 + dualScreenLeft; 14591 var top = height / 2 - h / 2 + dualScreenTop; 14592 var newWindow = window.open( 14593 url, 14594 title,
14595 "scrollbars=yes, width=" + 14596 w + 14597 ", height=" + 14598 h + 14599 ", top=" + 14600 top + 14601 ", left=" + 14602 left 14603 ); 14604 // Puts focus on the newWindow 14605 if (window.focus) { 14606 newWindow.focus(); 14607 } 14608 return newWindow; 14609} 14610function getPlexHeaders() { 14611 let plexTitle = 14612 activeInfo.appearance.title == "" 14613 ? "Organizr" 14614 : cleanClass(activeInfo.appearance.title); 14615 return { 14616 Accept: "application/json", 14617 "X-Plex-Product": plexTitle, 14618 "X-Plex-Version": "2.0", 14619 "X-Plex-Client-Identifier": activeInfo.settings.misc.uuid, 14620 "X-Plex-Model": "Plex OAuth", 14621 "X-Plex-Platform": activeInfo.osName, 14622 "X-Plex-Platform-Version": activeInfo.osVersion, 14623 "X-Plex-Device": activeInfo.browserName, 14624 "X-Plex-Device-Name": activeInfo.browserVersion, 14625 "X-Plex-Device-Screen-Resolution": 14626 window.screen.width + "x" + window.screen.height, 14627 "X-Plex-Language": "en", 14628 }; 14629} 14630var plex_oauth_window = null; 14631const plex_oauth_loader = 14632 "<style>" + 14633 ".login-loader-container {" + 14634 'font-family: "Open Sans", Arial, sans-serif;' + 14635 "position: absolute;" + 14636 "top: 0;" + 14637 "right: 0;" + 14638 "bottom: 0;" + 14639 "left: 0;" + 14640 "}" + 14641 ".login-loader-message {" + 14642 "color: #282A2D;" + 14643 "text-align: center;" + 14644 "position: absolute;" + 14645 "left: 50%;" + 14646 "top: 25%;" + 14647 "transform: translate(-50%, -50%);" + 14648 "}" + 14649 ".login-loader {" + 14650 "border: 5px solid #ccc;" + 14651 "-webkit-animation: spin 1s linear infinite;" + 14652 "animation: spin 1s linear infinite;" + 14653 "border-top: 5px solid #282A2D;" + 14654 "border-radius: 50%;" + 14655 "width: 50px;" + 14656 "height: 50px;" + 14657 "position: relative;" + 14658 "left: calc(50% - 25px);" + 14659 "}" + 14660 "@keyframes spin {" + 14661 "0% { transform: rotate(0deg); }" + 14662 "100% { transform: rotate(360deg); }" + 14663 "}" + 14664 "</style>" + 14665 '<div class="login-loader-container">' + 14666 '<div class="login-loader-message">' + 14667 '<div class="login-loader"></div>' + 14668 "<br>" + 14669 "Redirecting to the login page..." + 14670 "</div>" + 14671 "</div>"; 14672function closePlexOAuthWindow() { 14673 if (plex_oauth_window) { 14674 plex_oauth_window.close(); 14675 } 14676} 14677getPlexOAuthPin = function () { 14678 var x_plex_headers = getPlexHeaders(); 14679 var deferred = $.Deferred(); 14680 $.ajax({ 14681 url: "https://plex.tv/api/v2/pins?strong=true", 14682 type: "POST", 14683 headers: x_plex_headers, 14684 success: function (data) { 14685 deferred.resolve({ pin: data.id, code: data.code }); 14686 }, 14687 error: function () { 14688 closePlexOAuthWindow(); 14689 deferred.reject(); 14690 }, 14691 }); 14692 return deferred; 14693}; 14694var polling = null; 14695function PlexOAuth( 14696 successCallback, 14697 errorCallback, 14698 maxRetryCallback, 14699 pollingCallback, 14700 preFunction, 14701 clientID = null 14702) { 14703 if (typeof preFunction === "function") { 14704 preFunction(); 14705 } 14706 closePlexOAuthWindow(); 14707 plex_oauth_window = PopupCenter("", "Plex-OAuth", 600, 700); 14708 $(plex_oauth_window.document.body).html(plex_oauth_loader); 14709 getPlexOAuthPin().then( 14710 function (data) { 14711 var x_plex_headers = getPlexHeaders(); 14712 const pin = data.pin; 14713 const code = data.code; 14714 var oauth_params = { 14715 clientID: x_plex_headers["X-Plex-Client-Identifier"], 14716 "context[device][product]": x_plex_headers["X-Plex-Product"], 14717 "context[device][version]": x_plex_headers["X-Plex-Version"], 14718 "context[device][platform]": x_plex_headers["X-Plex-Platform"], 14719 "context[device][platformVersion]": 14720 x_plex_headers["X-Plex-Platform-Version"], 14721 "context[device][device]": x_plex_headers["X-Plex-Device"], 14722 "context[device][deviceName]": x_plex_headers["X-Plex-Device-Name"], 14723 "context[device][model]": x_plex_headers["X-Plex-Model"], 14724 "context[device][screenResolution]": 14725 x_plex_headers["X-Plex-Device-Screen-Resolution"], 14726 "context[device][layout]": "desktop", 14727 code: code, 14728 }; 14729 plex_oauth_window.location = 14730 "https://app.plex.tv/auth/#!?" + encodeData(oauth_params); 14731 polling = pin; 14732 let maxPollCount = 120; 14733 (function poll() { 14734 maxPollCount--; 14735 $.ajax({ 14736 url: "https://plex.tv/api/v2/pins/" + pin, 14737 type: "GET", 14738 headers: x_plex_headers, 14739 success: function (data) { 14740 if (data.authToken) { 14741 polling = null; 14742 closePlexOAuthWindow(); 14743 if (typeof successCallback === "function") { 14744 successCallback("plex", data.authToken, clientID); 14745 } 14746 } 14747 }, 14748 complete: function () { 14749 if (maxPollCount <= 0) { 14750 closePlexOAuthWindow(); 14751 if (typeof maxRetryCallback === "function") { 14752 maxRetryCallback(); 14753 } 14754 } else if (polling === pin) { 14755 setTimeout(function () { 14756 poll(); 14757 }, 1000); 14758 if (typeof pollingCallback === "function") { 14759 pollingCallback(maxPollCount); 14760 } 14761 } 14762 }, 14763 timeout: 1000, 14764 }); 14765 })(); 14766 }, 14767 function () { 14768 closePlexOAuthWindow(); 14769 if (typeof errorCallback === "function") { 14770 errorCallback(); 14771 } 14772 } 14773 ); 14774} 14775function openOAuth(provider) { 14776 // will actually fix this later 14777 closePlexOAuthWindow(); 14778 plex_oauth_window = PopupCenter("", "OAuth", 600, 700); 14779 $(plex_oauth_window.document.body).html(plex_oauth_loader);
14780 plex_oauth_window.location = "api/v2/oauth/trakt"; 14781} 14782function encodeData(data) { 14783 return Object.keys(data) 14784 .map(function (key) { 14785 return [key, data[key]].map(encodeURIComponent).join("="); 14786 }) 14787 .join("&"); 14788} 14789function oAuthSuccess(type, token, id = null) { 14790 switch (type) { 14791 case "plex": 14792 if (id) { 14793 $(id).val(token); 14794 $(id).change(); 14795 messageSingle( 14796 "", 14797 window.lang.translate("Grabbed Token - Please Save"), 14798 activeInfo.settings.notifications.position, 14799 "#FFF", 14800 "success", 14801 "5000" 14802 ); 14803 } else { 14804 $("#oAuth-Input").val(token); 14805 $("#oAuthType-Input").val(type); 14806 $("#login-username-Input").addClass("hidden"); 14807 $("#login-password-Input").addClass("hidden"); 14808 $("#oAuth-div").removeClass("hidden"); 14809 $(".login-button").first().trigger("click"); 14810 } 14811 break; 14812 default: 14813 break; 14814 } 14815} 14816function oAuthError() { 14817 messageSingle( 14818 "", 14819 window.lang.translate("Error Connecting to oAuth Provider"), 14820 activeInfo.settings.notifications.position, 14821 "#FFF", 14822 "error", 14823 "5000" 14824 ); 14825} 14826function oAuthMaxRetry() { 14827 messageSingle( 14828 "", 14829 window.lang.translate("Max Retry Error Connecting to oAuth Provider"), 14830 activeInfo.settings.notifications.position, 14831 "#FFF", 14832 "error", 14833 "5000" 14834 ); 14835} 14836function oAuthStart(type) { 14837 switch (type) { 14838 case "plex": 14839 PlexOAuth(oAuthSuccess, oAuthError, oAuthMaxRetry, null, null); 14840 break; 14841 default: 14842 break; 14843 } 14844} 14845function oidcStart(provider) { 14846 // Redirect in same window to OIDC provider 14847 window.location.href = 14848 "api/v2/oidc/" + encodeURIComponent(provider) + "/authorize"; 14849} 14850function testOIDCConnection(provider) { 14851 organizrAPI2( 14852 "GET", 14853 "api/v2/oidc/" + encodeURIComponent(provider) + "/test", 14854 "" 14855 ) 14856 .success(function (data) { 14857 if (data.response.result === "success") { 14858 messageSingle( 14859 "OIDC Test", 14860 data.response.message || "Connection successful", 14861 activeInfo.settings.notifications.position, 14862 "#FFF", 14863 "success", 14864 "5000" 14865 ); 14866 } else { 14867 messageSingle( 14868 "OIDC Test", 14869 data.response.message || "Connection failed", 14870 activeInfo.settings.notifications.position, 14871 "#FFF", 14872 "error", 14873 "5000" 14874 ); 14875 } 14876 }) 14877 .fail(function (xhr) { 14878 var msg = "Connection failed"; 14879 try { 14880 var resp = JSON.parse(xhr.responseText); 14881 msg = resp.response.message || msg; 14882 } catch (e) {} 14883 messageSingle( 14884 "OIDC Test", 14885 msg, 14886 activeInfo.settings.notifications.position, 14887 "#FFF", 14888 "error", 14889 "5000" 14890 ); 14891 }); 14892} 14893function clearAJAX(id = "all") { 14894 if (id == "all") { 14895 $.each(timeouts, function (i, v) { 14896 clearTimeout(timeouts[i]); 14897 }); 14898 } else if (id == "homepage") { 14899 $.each(timeouts, function (i, v) { 14900 if (i.indexOf("-Homepage") > 0) { 14901 clearTimeout(timeouts[i]); 14902 } 14903 }); 14904 } else { 14905 clearTimeout(timeouts[id]); 14906 } 14907} 14908//Generate API 14909function generateCode() { 14910 var code = ""; 14911 var possible = "abcdefghijklmnopqrstuvwxyz0123456789"; 14912 for (var i = 0; i < 20; i++) 14913 code += possible.charAt(Math.floor(Math.random() * possible.length)); 14914 return code; 14915} 14916// uppercase word 14917function toUpper(str) { 14918 return str 14919 .toLowerCase() 14920 .split(" ") 14921 .map(function (word) { 14922 return word[0].toUpperCase() + word.substr(1); 14923 }) 14924 .join(" "); 14925} 14926// human filesize 14927function humanFileSize(bytes, si) { 14928 var thresh = si ? 1000 : 1024; 14929 if (Math.abs(bytes) < thresh) { 14930 return bytes + " B"; 14931 } 14932 var units = si 14933 ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] 14934 : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; 14935 var u = -1; 14936 do { 14937 bytes /= thresh; 14938 ++u; 14939 } while (Math.abs(bytes) >= thresh && u < units.length - 1); 14940 return bytes.toFixed(1) + " " + units[u]; 14941} 14942//youtube search 14943function youtubeSearch(searchQuery) { 14944 return $.ajax({
14945 url: "api/v2/homepage/youtube/" + searchQuery, 14946 }); 14947} 14948function youtubeCheck(title, link) { 14949 youtubeSearch(title) 14950 .success(function (data) { 14951 var response = data.response; 14952 if (response.data) { 14953 inlineLoad(); 14954 var id = response.data.items["0"].id.videoId; 14955 var div = 14956 ` 14957 <div id="player-` + 14958 link + 14959 `" data-plyr-provider="youtube" data-plyr-embed-id="` + 14960 id + 14961 `" 14962 ></div> 14963 <div class="clearfix"></div> 14964 `; 14965 $(".youtube-div").html(div); 14966 $("." + link).trigger("click"); 14967 player = new Plyr("#player-" + link); 14968 } 14969 }) 14970 .fail(function (xhr) { 14971 OrganizrApiError(xhr, "YouTube API Error"); 14972 // Fallback: open YouTube search in a new tab/window 14973 var q = ""; 14974 try { 14975 q = decodeURIComponent(title); 14976 } catch (e1) { 14977 try { 14978 q = unescape(title); 14979 } catch (e2) { 14980 q = title; 14981 } 14982 } 14983 var url = 14984 "https://www.youtube.com/results?search_query=" + 14985 encodeURIComponent(q + " trailer"); 14986 window.open(url, "_blank"); 14987 }); 14988} 14989function requestSearch(title, page = 1) { 14990 return $.ajax({ 14991 url: 14992 "https://api.themoviedb.org/3/search/multi?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 14993 activeInfo.language + 14994 "&query=" + 14995 title + 14996 "&page=" + 14997 page + 14998 "&include_adult=false", 14999 }); 15000} 15001function requestSearchList(list, page = 1) { 15002 var url = ""; 15003 switch (list) { 15004 case "top-movie": 15005 url = 15006 "https://api.themoviedb.org/3/movie/top_rated?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15007 activeInfo.language + 15008 "®ion=US&page=" + 15009 page; 15010 break; 15011 case "pop-movie": 15012 url = 15013 "https://api.themoviedb.org/3/movie/popular?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15014 activeInfo.language + 15015 "®ion=US&page=" + 15016 page; 15017 break; 15018 case "up-movie": 15019 url = 15020 "https://api.themoviedb.org/3/movie/upcoming?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15021 activeInfo.language + 15022 "®ion=US&page=" + 15023 page; 15024 break; 15025 case "theatre-movie": 15026 url = 15027 "https://api.themoviedb.org/3/movie/now_playing?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15028 activeInfo.language + 15029 "®ion=US&page=" + 15030 page; 15031 break; 15032 case "top-tv": 15033 url = 15034 "https://api.themoviedb.org/3/tv/top_rated?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15035 activeInfo.language + 15036 "®ion=US&page=" + 15037 page; 15038 break; 15039 case "pop-tv": 15040 url = 15041 "https://api.themoviedb.org/3/tv/popular?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15042 activeInfo.language + 15043 "®ion=US&page=" + 15044 page; 15045 break; 15046 case "today-tv": 15047 url = 15048 "https://api.themoviedb.org/3/tv/airing_today?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15049 activeInfo.language + 15050 "®ion=US&page=" + 15051 page; 15052 break; 15053 case "org-mod": 15054 url = 15055 "https://api.themoviedb.org/4/list/64438?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=" + 15056 activeInfo.language + 15057 "&page=" + 15058 page; 15059 break; 15060 default: 15061 } 15062 return $.ajax({ 15063 url: url, 15064 }); 15065} 15066function requestNewID(id) { 15067 return $.ajax({ 15068 url: 15069 "https://api.themoviedb.org/3/tv/" + 15070 id + 15071 "/external_ids?api_key=83cf4ee97bb728eeaf9d4a54e64356a1&language=en-US", 15072 }); 15073} 15074function getTmdbImages(id, type) { 15075 return $.ajax({ 15076 url: `https://api.themoviedb.org/3/${type}/${id}/images?api_key=83cf4ee97bb728eeaf9d4a54e64356a1`, 15077 }); 15078} 15079function inlineLoad() { 15080 $(".inline-popups").magnificPopup({ 15081 removalDelay: 500, //delay removal by X to allow out-animation 15082 closeOnBgClick: true, 15083 //closeOnContentClick: true, 15084 callbacks: { 15085 beforeOpen: function () { 15086 this.st.mainClass = this.st.el.attr("data-effect"); 15087 this.st.focus = "#request-input"; 15088 }, 15089 close: function () { 15090 if (typeof player !== "undefined") { 15091 player.destroy(); 15092 } 15093 }, 15094 }, 15095 midClick: true, // allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source. 15096 }); 15097} 15098//Import Users 15099function importUsers(type) { 15100 $(".importUsersButton").attr("disabled", true); 15101 messageSingle( 15102 "", 15103 window.lang.translate("Importing Users"), 15104 activeInfo.settings.notifications.position, 15105 "#FFF", 15106 "success", 15107 "5000" 15108 ); 15109 organizrAPI2("POST", "api/v2/users/import/" + type, { type: type }) 15110 .success(function (data) {
15111 try { 15112 var response = data.response; 15113 message( 15114 "User Import", 15115 response.message, 15116 activeInfo.settings.notifications.position, 15117 "#FFF", 15118 "success", 15119 "5000" 15120 ); 15121 $(".importUsersButton").attr("disabled", false); 15122 } catch (e) { 15123 organizrCatchError(e, data); 15124 } 15125 }) 15126 .fail(function (xhr) { 15127 OrganizrApiError(xhr, "Import Error"); 15128 }); 15129} 15130//Settings change auth 15131function changeAuth() { 15132 var type = $("#authSelect").val(); 15133 var service = $("#authBackendSelect").val(); 15134 switch (service) { 15135 case "plex": 15136 $(".switchAuth").parent().parent().parent().hide(); 15137 $(".backendAuth").parent().parent().parent().show(); 15138 $(".plexAuth").parent().parent().parent().show(); 15139 break; 15140 case "emby_local": 15141 case "emby_connect": 15142 case "emby_all": 15143 $(".switchAuth").parent().parent().parent().hide(); 15144 $(".backendAuth").parent().parent().parent().show(); 15145 $(".embyAuth").parent().parent().parent().show(); 15146 break; 15147 case "jellyfin": 15148 $(".switchAuth").parent().parent().parent().hide(); 15149 $(".backendAuth").parent().parent().parent().show(); 15150 $(".jellyfinAuth").parent().parent().parent().show(); 15151 break; 15152 case "ftp": 15153 $(".switchAuth").parent().parent().parent().hide(); 15154 $(".backendAuth").parent().parent().parent().show(); 15155 $(".ftpAuth").parent().parent().parent().show(); 15156 break; 15157 case "ldap": 15158 $(".switchAuth").parent().parent().parent().hide(); 15159 $(".backendAuth").parent().parent().parent().show(); 15160 $(".ldapAuth").parent().parent().parent().show(); 15161 break; 15162 default: 15163 $(".switchAuth").parent().parent().parent().hide(); 15164 $(".backendAuth").parent().parent().parent().show(); 15165 } 15166 if (type == "internal") { 15167 $(".switchAuth").parent().parent().parent().hide(); 15168 } 15169} 15170function organizrSpecialSettings(array) { 15171 //media search 15172 if ( 15173 array.settings.homepage.search.enabled == true && 15174 typeof array.settings.homepage.search.type !== "undefined" 15175 ) { 15176 var htmlDOM = ` 15177 <li class=""><a class="waves-effect waves-light inline-popups" href="#mediaSearch-area" data-effect="mfp-zoom-out"> <i class="ti-search"></i></a></li> 15178 `; 15179 var searchBoxResults = 15180 ` 15181 <div id="mediaSearch-area" class="white-popup mfp-with-anim mfp-hide"> 15182 <div class="col-md-8 col-md-offset-2"> 15183 <div class="white-box m-b-0 resultBox-outside"> 15184 <div class="form-group m-b-0"> 15185 15186 <input id="mediaSearchQuery" data-server="` + 15187 array.settings.homepage.search.type + 15188 `" lang="en" placeholder="Search My Media" type="text" class="form-control inline-focus"> 15189 15190 <div class="clearfix"></div> 15191 </div> 15192 <div class="row el-element-overlay mediaSearch-div resultBox-inside"></div> 15193 </div> 15194 </div> 15195 </div> 15196 `; 15197 $(htmlDOM).prependTo(".navbar-right"); 15198 $(searchBoxResults).appendTo($(".organizr-area")); 15199 } 15200} 15201function checkLocalForwardStatus(array) { 15202 if ( 15203 array.settings.login.enableLocalAddressForward == true && 15204 typeof array.settings.login.enableLocalAddressForward !== "undefined" 15205 ) { 15206 if ( 15207 array.settings.login.wanDomain !== "" && 15208 array.settings.login.localAddress !== "" 15209 ) { 15210 organizrConsole("Organizr Function", "Local Login Enabled"); 15211 organizrConsole("Organizr Function", "Local Login Testing..."); 15212 let remoteSite = array.settings.login.wanDomain; 15213 let localSite = array.settings.login.localAddress;
15214 try { 15215 let currentURL = decodeURI(window.location.href); 15216 let currentSite = window.location.host; 15217 if ( 15218 activeInfo.settings.user.local && 15219 currentSite.indexOf(remoteSite) !== -1 && 15220 currentURL.indexOf("override") === -1 15221 ) { 15222 organizrConsole( 15223 "Organizr Function", 15224 "Local Login Status: Local | Forwarding Now" 15225 ); 15226 window.location = localSite; 15227 } else { 15228 organizrConsole( 15229 "Organizr Function", 15230 "Local Login Status: Not Local or Override was set - Ignoring Forward Request" 15231 ); 15232 } 15233 } catch (e) { 15234 console.error(e); 15235 } 15236 } 15237 } 15238} 15239function forceSearch(term) { 15240 $.magnificPopup.close(); 15241 let tabInfo = findTab("api/v2/page/homepage", "access_url"); 15242 if (tabInformation[tabInfo.id]["loaded"]) { 15243 if (tabInformation[tabInfo.id]["active"]) { 15244 setTimeout(function () { 15245 $("#newRequestButton").trigger("click"); 15246 $("#request-input").val(term); 15247 doneTyping(); 15248 }, 500); 15249 } else { 15250 tabActions("click", tabInfo.id); 15251 setTimeout(function () { 15252 $("#newRequestButton").trigger("click"); 15253 $("#request-input").val(term); 15254 doneTyping(); 15255 }, 1000); 15256 } 15257 } else { 15258 tabActions("click", tabInfo.id); 15259 setTimeout(function () { 15260 $("#newRequestButton").trigger("click"); 15261 $("#request-input").val(term); 15262 doneTyping(); 15263 }, 3000); 15264 } 15265} 15266function splitPoster(str) { 15267 var words = str.split(" "); 15268 var newWord = ""; 15269 $.each(words, function (i, v) { 15270 newWord += v + "<br/>"; 15271 }); 15272 return newWord; 15273} 15274function buildMediaResults(array, source, term) { 15275 if (array.content.length == 0) { 15276 var none = 15277 '<h2 class="text-center" lang="en">No Results for:</h2><h3 class="text-center" lang="en">' + 15278 term + 15279 "</h3>"; 15280 none += 15281 activeInfo.settings.homepage.ombi.enabled == true || 15282 activeInfo.settings.homepage.overseerr.enabled == true 15283 ? `<button onclick="forceSearch('` + 15284 term + 15285 `')" class="btn btn-block btn-info" lang="en">Would you like to Request it?</button>` 15286 : ""; 15287 return none; 15288 } 15289 var results = ""; 15290 var tv = 0; 15291 var movie = 0; 15292 var music = 0; 15293 var total = 0; 15294 $.each(array.content, function (i, v) { 15295 total = total + 1; 15296 tv = v.type == "tv" ? tv + 1 : tv; 15297 movie = v.type == "movie" ? movie + 1 : movie; 15298 music = v.type == "music" ? music + 1 : music; 15299 var bg = v.imageURL; 15300 var top = v.title; 15301 var bottom = v.metadata.originallyAvailableAt; 15302 results += 15303 ` 15304 <div id="` + 15305 v.uid + 15306 `-metadata-div" class="white-popup mfp-with-anim mfp-hide"> 15307 <div class="col-md-8 col-md-offset-2 ` + 15308 v.uid + 15309 `-metadata-info"></div> 15310 </div> 15311 <a class="inline-popups ` + 15312 v.uid + 15313 ` hidden" href="#` + 15314 v.uid + 15315 `-metadata-div" data-effect="mfp-zoom-out"></a> 15316 15317 <div class="col-lg-3 col-md-4 col-sm-6 col-xs-12 m-t-20 request-result-item request-result-` + 15318 v.type + 15319 ` metadata-get mouse" data-source="` + 15320 source + 15321 `" data-key="` + 15322 v.metadataKey + 15323 `" data-uid="` + 15324 v.uid + 15325 `"> 15326 <div class="white-box m-b-10"> 15327 <div class="el-card-item p-b-0"> 15328 <div class="el-card-avatar el-overlay-1 m-b-5"> <img class="lazyload resultImages" data-src="` + 15329 bg + 15330 `"></div> 15331 <div class="el-card-content bg-org"> 15332 <h3 class="box-title elip">` + 15333 top + 15334 `</h3> <small>` + 15335 bottom + 15336 `</small> 15337 <br> 15338 </div> 15339 </div> 15340 </div> 15341 </div> 15342 `; 15343 }); 15344 //requests setup? 15345 if ( 15346 activeInfo.settings.homepage.ombi.enabled == true || 15347 activeInfo.settings.homepage.overseerr.enabled == true 15348 ) { 15349 results += 15350 ` 15351 <div class="col-lg-3 col-md-4 col-sm-6 col-xs-12 m-t-20 request-result-item request-result-movie mouse" onclick="forceSearch('` + 15352 term + 15353 `')"> 15354 <div class="white-box m-b-10"> 15355 <div class="el-card-item p-b-0"> 15356 <div class="el-card-avatar el-overlay-1 m-b-5"> <img class="lazyload resultImages mouse" data-src="plugins/images/homepage/no-request.png"> 15357 <div class="customPoster"> 15358 <a href="javascript:void(0);">` + 15359 splitPoster(term) + 15360 `</a> 15361 </div> 15362 </div> 15363 <div class="el-card-content bg-org"> 15364 <h3 class="box-title elip">` + 15365 term + 15366 `</h3> <small lang="en">Request Me!</small> 15367 <br> 15368 </div>
15369 </div> 15370 </div> 15371 </div> 15372 `; 15373 } 15374 var buttons = 15375 ` 15376 <div class="button-box p-20 text-center p-b-0"> 15377 <button class="btn btn-inverse waves-effect waves-light filter-request-result" data-filter="request-result-all"><span>` + 15378 total + 15379 `</span> <i class="fa fa-th-large m-l-5 fa-fw"></i></button> 15380 <button class="btn btn-primary waves-effect waves-light filter-request-result" data-filter="request-result-movie"><span>` + 15381 movie + 15382 `</span> <i class="fa fa-film m-l-5 fa-fw"></i></button> 15383 <button class="btn btn-info waves-effect waves-light filter-request-result" data-filter="request-result-tv"><span>` + 15384 tv + 15385 `</span> <i class="fa fa-tv m-l-5 fa-fw"></i></button> 15386 <button class="btn btn-info waves-effect waves-light filter-request-result" data-filter="request-result-music"><span>` + 15387 music + 15388 `</span> <i class="fa fa-music m-l-5 fa-fw"></i></button> 15389 </div> 15390 `; 15391 results = '<div class="media-results">' + results + "</div>"; 15392 return buttons + results; 15393} 15394function getPingList(arrayItems) { 15395 var pingList = []; 15396 var timeout = 15397 activeInfo.user.groupID <= 1 15398 ? activeInfo.settings.homepage.refresh.adminPingRefresh 15399 : activeInfo.settings.homepage.refresh.otherPingRefresh; 15400 if ( 15401 Array.isArray(arrayItems["data"]["tabs"]) && 15402 arrayItems["data"]["tabs"].length > 0 15403 ) { 15404 $.each(arrayItems["data"]["tabs"], function (i, v) { 15405 if (v.ping && v.ping_url !== null) { 15406 pingList.push(v.ping_url); 15407 } 15408 }); 15409 } 15410 return pingList.length > 0 ? pingUpdate(pingList, timeout) : false; 15411} 15412function pingUpdateItem(ping) { 15413 if (activeInfo.user.groupID > activeInfo.settings.ping.auth) { 15414 return false; 15415 } 15416 organizrAPI2("GET", "api/v2/ping/" + ping) 15417 .success(function (data) { 15418 try { 15419 var response = data.response; 15420 } catch (e) { 15421 organizrCatchError(e, data); 15422 } 15423 var i = ping; 15424 var v = response.data; 15425 var elm = $(".menu-" + cleanClass(i) + "-ping"); 15426 var elmMs = $(".menu-" + cleanClass(i) + "-ping-ms"); 15427 var catElm = elm 15428 .parent() 15429 .parent() 15430 .parent() 15431 .parent() 15432 .children("a") 15433 .find(".menu-category-ping"); 15434 var error = 15435 '<div class="ping"><span class="heartbit"></span><span class="point"></span></div>'; 15436 var success = ""; 15437 var badCount = 0; 15438 var goodCount = 0; 15439 var previousState = 15440 elm.attr("data-previous-state") == "" 15441 ? "" 15442 : elm.attr("data-previous-state"); 15443 var tabName = elm.attr("data-tab-name"); 15444 var status = v == null ? "down" : "up"; 15445 var ms = v == null ? "down" : v + "ms"; 15446 var sendMessage = 15447 previousState !== status && 15448 previousState !== "" && 15449 activeInfo.user.groupID <= activeInfo.settings.ping.authMessage 15450 ? true 15451 : false; 15452 var audioDown = sendMessage 15453 ? new Audio(activeInfo.settings.ping.offlineSound) 15454 : ""; 15455 var audioUp = sendMessage 15456 ? new Audio(activeInfo.settings.ping.onlineSound) 15457 : ""; 15458 elm.attr("data-previous-state", status); 15459 let listing = elm 15460 .parent() 15461 .parent() 15462 .parent() 15463 .parent() 15464 .children("a") 15465 .find(".menu-category-ping") 15466 .parent() 15467 .parent() 15468 .find("li") 15469 .find("div[class$='-ping']"); 15470 $.each(listing, function (i, v) { 15471 let state = $(v).attr("data-previous-state"); 15472 if (state == "up") { 15473 goodCount = goodCount + 1; 15474 } else if (state == "down") { 15475 badCount = badCount + 1; 15476 } 15477 }); 15478 if (catElm.length > 0) { 15479 catElm.attr("data-bad", badCount); 15480 catElm.attr("data-good", goodCount); 15481 if (badCount == 0) { 15482 catElm.html(success); 15483 } 15484 } 15485 if ( 15486 activeInfo.user.groupID <= activeInfo.settings.ping.authMs && 15487 activeInfo.settings.ping.ms 15488 ) { 15489 elmMs.removeClass("hidden").html(ms); 15490 } 15491 switch (status) { 15492 case "down": 15493 elm.html(error); 15494 catElm.html(error); 15495 elm.parent().find("img").addClass("grayscale"); 15496 var msg = sendMessage 15497 ? message( 15498 tabName, 15499 "Server Down", 15500 activeInfo.settings.notifications.position, 15501 "#FFF", 15502 "error", 15503 "600000" 15504 ) 15505 : ""; 15506 var audio = 15507 sendMessage && activeInfo.settings.ping.statusSounds 15508 ? audioDown.play() 15509 : ""; 15510 break; 15511 default: 15512 elm.html(success); 15513 elm.parent().find("img").removeClass("grayscale"); 15514 var msg = sendMessage 15515 ? message( 15516 tabName, 15517 "Server Back Online", 15518 activeInfo.settings.notifications.position, 15519 "#FFF", 15520 "success", 15521 "600000" 15522 ) 15523 : ""; 15524 var audio = 15525 sendMessage && activeInfo.settings.ping.statusSounds 15526 ? audioUp.play() 15527 : ""; 15528 } 15529 }) 15530 .fail(function (xhr) { 15531 OrganizrApiError(xhr); 15532 }); 15533} 15534function pingUpdate(pingList, timeout) { 15535 $.each(pingList, function (i, v) { 15536 pingUpdateItem(v); 15537 }); 15538 var timeoutTitle = "ping"; 15539 if (typeof timeouts[timeoutTitle] !== "undefined") { 15540 clearTimeout(timeouts[timeoutTitle]); 15541 } 15542 timeouts[timeoutTitle] = setTimeout(function () { 15543 pingUpdate(pingList, timeout); 15544 }, timeout); 15545} 15546function include(filename) { 15547 var type = filename.split(".").pop(); 15548 switch (type) { 15549 case "js": 15550 var body = document.getElementsByTagName("body")[0]; 15551 var script = document.createElement("script"); 15552 script.src = filename; 15553 script.type = "text/javascript"; 15554 body.appendChild(script); 15555 break; 15556 case "css": 15557 var head = document.getElementById("style"); 15558 var script = document.createElement("link"); 15559 script.href = filename; 15560 script.type = "text/css"; 15561 script.rel = "stylesheet"; 15562 head.appendChild(script); 15563 break; 15564 default: 15565 return false;
15566 } 15567 return false; 15568} 15569function defineNotification() { 15570 var bb = 15571 typeof activeInfo !== "undefined" 15572 ? activeInfo.settings.notifications.backbone 15573 : "izi"; 15574 switch (bb) { 15575 case "toastr": 15576 include("plugins/bower_components/toast-master/css/jquery.toast.css"); 15577 include("plugins/bower_components/toast-master/js/jquery.toast.js"); 15578 window.notificationFunction = "$.toast"; 15579 break; 15580 case "izi": 15581 include("plugins/bower_components/iziToast/css/iziToast.min.css"); 15582 include("plugins/bower_components/iziToast/js/iziToast.min.js"); 15583 window.notificationFunction = "iziToast"; 15584 break; 15585 case "alertify": 15586 include("plugins/bower_components/alertify/alertify.min.css"); 15587 include("plugins/bower_components/alertify/default.min.css"); 15588 include("plugins/bower_components/alertify/alertify.min.js"); 15589 window.notificationFunction = "alertify"; 15590 break; 15591 case "noty": 15592 include("plugins/bower_components/noty/noty.min.js"); 15593 include("plugins/bower_components/noty/mo.min.js"); 15594 include("plugins/bower_components/noty/noty.css"); 15595 include("plugins/bower_components/noty/mint.css"); 15596 window.notificationFunction = "Noty"; 15597 break; 15598 default: 15599 return false; 15600 } 15601 window.notificationsReady = true; 15602} 15603function messagePositions() { 15604 return { 15605 br: { 15606 toastr: "bottom-right", 15607 alertify: "bottom-right", 15608 izi: "bottomRight", 15609 noty: "bottomRight", 15610 }, 15611 bl: { 15612 toastr: "bottom-left", 15613 alertify: "bottom-left", 15614 izi: "bottomLeft", 15615 noty: "bottomLeft", 15616 }, 15617 bc: { 15618 toastr: "bottom-center", 15619 alertify: "bottom-center", 15620 izi: "bottomCenter", 15621 noty: "bottomCenter", 15622 }, 15623 tr: { 15624 toastr: "top-right", 15625 alertify: "top-right", 15626 izi: "topRight", 15627 noty: "topRight", 15628 }, 15629 tl: { 15630 toastr: "top-left", 15631 alertify: "top-left", 15632 izi: "topLeft", 15633 noty: "topLeft", 15634 }, 15635 tc: { 15636 toastr: "top-center", 15637 alertify: "top-center", 15638 izi: "topCenter", 15639 noty: "topCenter", 15640 }, 15641 c: { 15642 toastr: "center", 15643 alertify: "bottom-center", 15644 izi: "center", 15645 noty: "center", 15646 }, 15647 }; 15648} 15649function message( 15650 heading, 15651 text, 15652 position, 15653 color, 15654 icon, 15655 timeout, 15656 single = false 15657) { 15658 let bb = 15659 typeof activeInfo !== "undefined" 15660 ? activeInfo.settings.notifications.backbone 15661 : "izi"; 15662 let activePosition = 15663 typeof activeInfo !== "undefined" 15664 ? activeInfo.settings.notifications.position 15665 : "bc"; 15666 position = typeof position !== "undefined" ? position : activePosition; 15667 text = typeof text !== "undefined" ? text : ""; 15668 color = typeof color !== "undefined" ? color : "#FFF"; 15669 icon = typeof icon !== "undefined" ? icon : "info"; 15670 timeout = typeof timeout !== "undefined" ? timeout : 10000; 15671 switch (bb) { 15672 case "toastr": 15673 var ready = eval(notificationFunction) !== undefined ? true : false; 15674 break; 15675 case "izi": 15676 case "alertify": 15677 case "noty": 15678 try { 15679 var ready = 15680 typeof eval(notificationFunction) !== undefined ? true : false; 15681 } catch (e) { 15682 if (e instanceof SyntaxError) { 15683 setTimeout(function () { 15684 message(heading, text, position, color, icon, timeout, single); 15685 }, 100); 15686 } 15687 } 15688 break; 15689 default: 15690 var ready = false; 15691 } 15692 if (notificationsReady && ready) { 15693 oldPosition = position; 15694 position = messagePositions()[position][bb]; 15695 if (typeof activeInfo === "undefined") { 15696 setTimeout(function () { 15697 message(heading, text, oldPosition, color, icon, timeout, single); 15698 }, 100); 15699 return false; 15700 } 15701 if (single) { 15702 switch (bb) { 15703 case "toastr": 15704 $.toast().reset("all"); 15705 break; 15706 case "izi": 15707 iziToast.destroy(); 15708 break; 15709 case "alertify": 15710 alertify.dismissAll(); 15711 break; 15712 case "noty": 15713 Noty.closeAll(); 15714 break; 15715 default: 15716 return false; 15717 } 15718 } 15719 switch (bb) { 15720 case "toastr": 15721 $.toast({ 15722 heading: heading, 15723 text: text, 15724 position: position, 15725 loaderBg: color, 15726 icon: icon, 15727 hideAfter: timeout, 15728 stack: 6, 15729 showHideTransition: "slide", 15730 }); 15731 break; 15732 case "izi": 15733 switch (icon) { 15734 case "success": 15735 var msg = { 15736 icon: "mdi mdi-check-circle-outline", 15737 }; 15738 break; 15739 case "info": 15740 var msg = { 15741 icon: "mdi mdi-information-outline", 15742 }; 15743 break; 15744 case "error": 15745 var msg = { 15746 icon: "mdi mdi-close-circle-outline", 15747 }; 15748 break; 15749 case "warning": 15750 var msg = { 15751 icon: "mdi mdi-alert-circle-outline", 15752 }; 15753 break; 15754 case "update": 15755 var msg = { 15756 icon: "mdi mdi-webpack", 15757 }; 15758 break; 15759 default: 15760 var msg = { 15761 icon: "mdi mdi-alert-circle-outline", 15762 }; 15763 } 15764 iziToast.show({ 15765 close: true, 15766 progressBar: true, 15767 progressBarEasing: "ease", 15768 class: icon + "-notify", 15769 title: heading, 15770 message: text, 15771 position: position, 15772 timeout: timeout, 15773 layout: 2, 15774 transitionIn: "flipInX", 15775 transitionOut: "flipOutX", 15776 balloon: false, 15777 icon: msg["icon"], 15778 }); 15779 break; 15780 case "alertify": 15781 var msgFull = heading !== "" ? heading + "<br/>" + text : text; 15782 timeout = timeout / 1000; 15783 alertify.set("notifier", "position", position); 15784 alertify.notify(msgFull, icon + "-alertify", timeout); 15785 break; 15786 case "noty": 15787 if (typeof mojs == "undefined") { 15788 setTimeout(function () { 15789 message(heading, text, oldPosition, color, icon, timeout); 15790 }, 100); 15791 return false;
15792 } 15793 var msgFull = heading !== "" ? heading + "<br/>" + text : text; 15794 new Noty({ 15795 type: icon + "-noty", 15796 layout: position, 15797 text: msgFull, 15798 progressBar: true, 15799 timeout: timeout, 15800 animation: { 15801 open: function (promise) { 15802 var n = this; 15803 var Timeline = new mojs.Timeline(); 15804 var body = new mojs.Html({ 15805 el: n.barDom, 15806 x: { 500: 0, delay: 0, duration: 500, easing: "elastic.out" }, 15807 isForce3d: true, 15808 onComplete: function () { 15809 promise(function (resolve) { 15810 resolve(); 15811 }); 15812 }, 15813 }); 15814 15815 var parent = new mojs.Shape({ 15816 parent: n.barDom, 15817 width: 200, 15818 height: n.barDom.getBoundingClientRect().height, 15819 radius: 0, 15820 x: { [150]: -150 }, 15821 duration: 1.2 * 500, 15822 isShowStart: true, 15823 }); 15824 15825 n.barDom.style["overflow"] = "visible"; 15826 parent.el.style["overflow"] = "hidden"; 15827 15828 var burst = new mojs.Burst({ 15829 parent: parent.el, 15830 count: 10, 15831 top: n.barDom.getBoundingClientRect().height + 75, 15832 degree: 90, 15833 radius: 75, 15834 angle: { [-90]: 40 }, 15835 children: { 15836 fill: "#EBD761", 15837 delay: "stagger(500, -50)", 15838 radius: "rand(8, 25)", 15839 direction: -1, 15840 isSwirl: true, 15841 }, 15842 }); 15843 15844 var fadeBurst = new mojs.Burst({ 15845 parent: parent.el, 15846 count: 2, 15847 degree: 0, 15848 angle: 75, 15849 radius: { 0: 100 }, 15850 top: "90%", 15851 children: { 15852 fill: "#EBD761", 15853 pathScale: [0.65, 1], 15854 radius: "rand(12, 15)", 15855 direction: [-1, 1], 15856 delay: 0.8 * 500, 15857 isSwirl: true, 15858 }, 15859 }); 15860 15861 Timeline.add(body, burst, fadeBurst, parent); 15862 Timeline.play(); 15863 }, 15864 close: function (promise) { 15865 var n = this; 15866 new mojs.Html({ 15867 el: n.barDom, 15868 x: { 0: 500, delay: 10, duration: 500, easing: "cubic.out" }, 15869 skewY: { 0: 10, delay: 10, duration: 500, easing: "cubic.out" }, 15870 isForce3d: true, 15871 onComplete: function () { 15872 promise(function (resolve) { 15873 resolve(); 15874 }); 15875 }, 15876 }).play(); 15877 }, 15878 }, 15879 }).show(); 15880 break; 15881 default: 15882 organizrConsole("Organizr Function", "Message case not setup"); 15883 } 15884 } else { 15885 setTimeout(function () { 15886 message(heading, text, position, color, icon, timeout, single); 15887 }, 100); 15888 } 15889} 15890function messageSingle(heading, text, position, color, icon, timeout) { 15891 let activePosition = 15892 typeof activeInfo !== "undefined" 15893 ? activeInfo.settings.notifications.position 15894 : "bc"; 15895 position = typeof position !== "undefined" ? position : activePosition; 15896 text = typeof text !== "undefined" ? text : ""; 15897 color = typeof color !== "undefined" ? color : "#FFF"; 15898 icon = typeof icon !== "undefined" ? icon : "info"; 15899 timeout = typeof timeout !== "undefined" ? timeout : 10000; 15900 message(heading, text, position, color, icon, timeout, true); 15901} 15902 15903function blockDev(e) { 15904 var evtobj = window.event ? event : e; 15905 if (evtobj.keyCode == 73 && evtobj.shiftKey && evtobj.ctrlKey) { 15906 evtobj.preventDefault(); 15907 } 15908} 15909function authDebugCheck() { 15910 if (activeInfo.settings.misc.authDebug == true) { 15911 message( 15912 "REMINDER", 15913 "Auth Debug is still enabled", 15914 activeInfo.settings.notifications.position, 15915 "#FFF", 15916 "warning", 15917 "20000" 15918 ); 15919 } 15920} 15921function lock() { 15922 if (activeInfo.settings.user.oAuthLogin == true) { 15923 message( 15924 "Lock Disabled", 15925 "Lock function disabled if logged in via oAuth", 15926 activeInfo.settings.notifications.position, 15927 "#FFF", 15928 "warning", 15929 "5000" 15930 ); 15931 return false;
15932 } 15933 organizrAPI2("POST", "api/v2/users/lock", "") 15934 .success(function (data) { 15935 try { 15936 let html = data.response; 15937 location.reload(); 15938 } catch (e) { 15939 organizrCatchError(e, data); 15940 } 15941 }) 15942 .fail(function (xhr) { 15943 OrganizrApiError(xhr, "Lock Error"); 15944 }); 15945} 15946function openSettings() { 15947 let tabInfo = findTab("api/v2/page/settings", "access_url"); 15948 tabActions("click", tabInfo.id); 15949} 15950function openHomepage() { 15951 let tabInfo = findTab("api/v2/page/homepage", "access_url"); 15952 tabActions("click", tabInfo.id); 15953} 15954function toggleFullScreenIcon() { 15955 $(".fullscreen-icon") 15956 .toggleClass("ti-fullscreen") 15957 .toggleClass("mdi mdi-fullscreen-exit"); 15958} 15959function toggleFullScreen() { 15960 toggleFullScreenIcon(); 15961 if ( 15962 !document.fullscreenElement && // alternative standard method 15963 !document.mozFullScreenElement && 15964 !document.webkitFullscreenElement && 15965 !document.msFullscreenElement 15966 ) { 15967 // current working methods 15968 if (document.documentElement.requestFullscreen) { 15969 document.documentElement.requestFullscreen(); 15970 } else if (document.documentElement.msRequestFullscreen) { 15971 document.documentElement.msRequestFullscreen(); 15972 } else if (document.documentElement.mozRequestFullScreen) { 15973 document.documentElement.mozRequestFullScreen(); 15974 } else if (document.documentElement.webkitRequestFullscreen) { 15975 document.documentElement.webkitRequestFullscreen( 15976 Element.ALLOW_KEYBOARD_INPUT 15977 ); 15978 } 15979 } else { 15980 if (document.exitFullscreen) { 15981 document.exitFullscreen(); 15982 } else if (document.msExitFullscreen) { 15983 document.msExitFullscreen(); 15984 } else if (document.mozCancelFullScreen) { 15985 document.mozCancelFullScreen(); 15986 } else if (document.webkitExitFullscreen) { 15987 document.webkitExitFullscreen(); 15988 } 15989 } 15990} 15991function orgErrorCode(code) { 15992 switch (code) { 15993 case "upgrading": 15994 window.location.href = "./plugins/static/upgrade.html"; 15995 default: 15996 } 15997} 15998function clickPath(type, path = null) { 15999 switch (type) { 16000 case "c": 16001 case "custom": 16002 if (path !== null) { 16003 if (typeof path == "object") { 16004 $.each(path, function (i, v) { 16005 $(v).trigger("click"); 16006 }); 16007 } else { 16008 $(path).trigger("click"); 16009 } 16010 } else { 16011 return null; 16012 } 16013 break; 16014 case "update": 16015 $("#settings-main-system-settings-anchor").trigger("click"); 16016 $("#settings-settings-updates-anchor").trigger("click"); 16017 break; 16018 case "sso": 16019 $("#settings-main-system-settings-anchor").trigger("click"); 16020 $("#settings-settings-sso-anchor").trigger("click"); 16021 break; 16022 default: 16023 return null; 16024 } 16025} 16026function toggleWritableFolders() { 16027 $(".folders-writable").toggleClass("hidden"); 16028} 16029function getAllTabNames() { 16030 var allTabs = $(".tabEditor"); 16031 var tabList = []; 16032 $.each(allTabs, function (i, v) { 16033 tabList[i] = v.getAttribute("data-name").toLowerCase(); 16034 }); 16035 return tabList; 16036} 16037function checkIfTabNameExists(tabName) { 16038 if (getAllTabNames().indexOf(tabName.toLowerCase()) == -1) { 16039 return false; 16040 } else { 16041 return true; 16042 } 16043} 16044function getLatestBlackberryThemes() { 16045 return $.ajax({ 16046 url: "https://api.github.com/repos/Archmonger/Blackberry-Themes/contents/Themes", 16047 }); 16048} 16049function getBlackberryTheme(theme) { 16050 return $.ajax({ 16051 url: 16052 "https://api.github.com/repos/Archmonger/Blackberry-Themes/contents/Themes/" + 16053 theme + 16054 "/Icons", 16055 }); 16056} 16057function showBlackberryThemes(target) { 16058 getLatestBlackberryThemes() 16059 .success(function (data) { 16060 try { 16061 let themes = ""; 16062 $.each(data, function (i, v) { 16063 if (v.name !== "Beta") { 16064 themes += `<a href="javascript:selectBlackberryTheme('${v.name}','${target}');" class="list-group-item"><span><img class="themeIcon pull-right" src="https://raw.githubusercontent.com/Archmonger/Blackberry-Themes/master/Themes/${v.name}/Icons/preview.png"></span>${v.name}</a>`; 16065 } 16066 }); 16067 themes = `<div class="list-group">${themes}</div>`; 16068 let html = ` 16069 <div class="panel"> 16070 <div class="bg-org2"> 16071 <div class="panel-heading">Choose a Theme</div> 16072 <div class="panel-body text-left">${themes}</div>
16073 </div> 16074 </div> 16075 `; 16076 swal({ 16077 content: createElementFromHTML(html), 16078 button: "Close", 16079 className: "orgErrorAlert", 16080 dangerMode: true, 16081 }); 16082 } catch (e) { 16083 organizrCatchError(e, data); 16084 } 16085 }) 16086 .fail(function (xhr) { 16087 OrganizrApiError(xhr); 16088 }); 16089} 16090function selectBlackberryTheme(theme, target) { 16091 getBlackberryTheme(theme) 16092 .success(function (data) { 16093 try { 16094 let icons = ""; 16095 $.each(data, function (i, v) { 16096 v.name = v.name.split(".")[0]; 16097 v.name = cleanClass(v.name); 16098 icons += `<a href="#" onclick="javascript:swal.close();$('#${target}').val('${v.download_url}')"><img alt="${v.name}" data-toggle="tooltip" data-placement="top" title="" data-original-title="${v.name}"src="${v.download_url}" ></a>`; 16099 }); 16100 icons = `<div id="gallery-content-center">${icons}</div>`; 16101 let html = ` 16102 <div class="panel"> 16103 <div class="bg-org2"> 16104 <div class="panel-heading">Choose an Icon</div> 16105 <div class="panel-body text-left">${icons}</div> 16106 </div> 16107 </div> 16108 `; 16109 swal({ 16110 content: createElementFromHTML(html), 16111 buttons: { 16112 back: { 16113 text: "Back To Themes", 16114 value: "back", 16115 dangerMode: true, 16116 className: "bg-org-alt", 16117 }, 16118 }, 16119 className: "orgErrorAlert", 16120 dangerMode: true, 16121 }).then((value) => { 16122 switch (value) { 16123 case "back": 16124 showBlackberryThemes(); 16125 break; 16126 } 16127 }); 16128 } catch (e) { 16129 organizrCatchError(e, data); 16130 } 16131 }) 16132 .fail(function (xhr) { 16133 OrganizrApiError(xhr); 16134 }); 16135} 16136function orgErrorAlert(error) { 16137 let showError = false; 16138 if (typeof activeInfo === "undefined") { 16139 showError = true; 16140 } else { 16141 if (activeInfo.settings.misc.debugErrors) { 16142 showError = true; 16143 } 16144 } 16145 if (showError) { 16146 let div = ` 16147 <div class="panel"> 16148 <div class="bg-org2"> 16149 <div class="panel-heading">ERROR</div> 16150 <div class="panel-body text-left">${error}</div> 16151 </div> 16152 </div> 16153 `; 16154 swal({ 16155 content: createElementFromHTML(div), 16156 button: "OK", 16157 className: "orgErrorAlert", 16158 dangerMode: true, 16159 }); 16160 } 16161} 16162function toggleDebug() { 16163 var div = ` 16164 <div class="white-box m-0"> 16165 <div class="steamline"> 16166 <div class="sl-item"> 16167 <div class="sl-left bg-success"><i class="mdi mdi-code-tags"></i></div> 16168 <div class="sl-right"> 16169 <div class="form-group"> 16170 <div id="" class="input-group"> 16171 <input id="debug-input" lang="en" placeholder="Input Command" type="text" 16172 class="form-control inline-focus"> 16173 <div class="input-group-btn"> 16174 <button type="button" 16175 class="btn waves-effect waves-light btn-info dropdown-toggle" 16176 data-toggle="dropdown" aria-expanded="false"><span lang="en">Commands</span> 16177 <span class="caret"></span></button> 16178 <ul class="dropdown-menu dropdown-menu-right"> 16179 <li><a onclick="orgDebugList('activeInfo.settings.sso');" 16180 href="javascript:void(0)" 16181 lang="en">SSO</a></li> 16182 <li><a onclick="orgDebugList('activeInfo.settings.sso.plex');" 16183 href="javascript:void(0)" 16184 lang="en">Plex SSO</a></li> 16185 <li><a onclick="orgDebugList('activeInfo.settings.sso.tautulli');" 16186 href="javascript:void(0)" 16187 lang="en">Tautulli SSO</a></li> 16188 <li><a onclick="orgDebugList('activeInfo.settings.sso.overseerr');" 16189 href="javascript:void(0)" 16190 lang="en">
16190Overseerr SSO</a></li> 16191 <li><a onclick="orgDebugList('activeInfo.settings.sso.petio');" 16192 href="javascript:void(0)" 16193 lang="en">Petio SSO</a></li> 16194 <li><a onclick="orgDebugList('activeInfo.settings.sso.ombi');" 16195 href="javascript:void(0)" 16196 lang="en">Ombi SSO</a></li> 16197 <li><a onclick="orgDebugList('activeInfo.settings.sso.jellyfin');" 16198 href="javascript:void(0)" 16199 lang="en">Jellyfin SSO</a></li> 16200 <li><a onclick="orgDebugList('activeInfo.settings.sso.komga');" 16201 href="javascript:void(0)" 16202 lang="en">Komga SSO</a></li> 16203 <li><a onclick="orgDebugList('activeInfo.settings.sso.misc');" 16204 href="javascript:void(0)" 16205 lang="en">Misc SSO</a></li> 16206 <li><a onclick="orgDebugList('activeInfo.settings.misc.schema');" 16207 href="javascript:void(0)" 16208 lang="en">DB Schema</a></li> 16209 </ul> 16210 </div> 16211 </div> 16212 <div class="clearfix"></div> 16213 </div> 16214 </div> 16215 </div> 16216 <div id="debugPreInfoBox" class="sl-item text-left"> 16217 <div class="sl-left bg-info"><i class="mdi mdi-package-variant-closed"></i></div> 16218 <div class="sl-right"> 16219 <div> 16220 <span lang="en">Organizr Information:</span> 16221 </div> 16222 <div id="debugPreInfo" class="desc"></div> 16223 </div> 16224 </div> 16225 <div id="debugResultsBox" class="sl-item hidden text-left"> 16226 <div class="sl-left bg-info"><i class="mdi mdi-receipt"></i></div> 16227 <div class="sl-right"> 16228 <div><span lang="en">Results For cmd:</span> <span class="cmdName"></span> 16229 </div> 16230 <div id="debugResults" class="desc"></div> 16231 </div> 16232 </div>
16233 </div> 16234 </div> 16235 `; 16236 swal({ 16237 content: createElementFromHTML(div), 16238 button: "OK", 16239 className: "orgErrorAlert", 16240 }); 16241 getDebugPreInfo(); 16242} 16243function toggleCalendarFilter() { 16244 var div = ` 16245 <div id="calendar-filter-modal" class="panel panel-inverse"> 16246 <div class="panel-heading"><span class="text-uppercase" lang="en">Filter Calendar</span></div> 16247 <div class="panel-wrapper collapse in" aria-expanded="true"> 16248 <div class="panel-body"> 16249 <div class="row"> 16250 <div class="col-md-12"> 16251 <label class="control-label" lang="en">Choose Media Type</label> 16252 <select class="form-control form-white" data-placeholder="Choose media type" id="choose-calender-filter"> 16253 <option value="all" lang="en">All</option> 16254 <option value="tv" lang="en">TV</option> 16255 <option value="film" lang="en">Movie</option> 16256 <option value="music" lang="en">Music</option> 16257 </select> 16258 </div> 16259 <div class="col-md-12"> 16260 <label class="control-label" lang="en">Choose Media Status</label> 16261 <select class="form-control form-white" data-placeholder="Choose media status" id="choose-calender-filter-status"> 16262 <option value="all" lang="en">All</option> 16263 <option value="text-success" lang="en">Downloaded</option> 16264 <option value="text-info" lang="en">Unaired</option> 16265 <option value="text-danger" lang="en">Missing</option> 16266 <option value="text-primary animated flash" lang="en">Premier</option> 16267 </select> 16268 </div> 16269 </div> 16270 </div> 16271 </div> 16272 </div> 16273 `; 16274 swal({ 16275 content: createElementFromHTML(div), 16276 className: "bg-org", 16277 button: false, 16278 }); 16279} 16280function closeOrgError() { 16281 $("#main-org-error-container").removeClass("show"); 16282 $("#main-org-error").html(""); 16283} 16284function isJSON(data) { 16285 if (typeof data != "string") { 16286 data = JSON.stringify(data); 16287 } 16288 try { 16289 JSON.parse(data); 16290 return true; 16291 } catch (e) { 16292 return false; 16293 } 16294} 16295function createElementFromHTML(htmlString) { 16296 var div = document.createElement("div"); 16297 div.innerHTML = htmlString.trim(); 16298 return div.firstChild; 16299} 16300function addCoordinatesToInput(latitude, longitude) { 16301 $("#homepage-Weather-Air-form [name=homepageWeatherAndAirLatitude]") 16302 .val(latitude) 16303 .change(); 16304 $("#homepage-Weather-Air-form [name=homepageWeatherAndAirLongitude]") 16305 .val(longitude) 16306 .change(); 16307 swal.close(); 16308 message( 16309 "Coordinates Added", 16310 "Please Save", 16311 activeInfo.settings.notifications.position, 16312 "#FFF", 16313 "success", 16314 "10000" 16315 ); 16316} 16317function searchCoordinatesAPI(query) { 16318 messageSingle( 16319 "Submitting Query", 16320 "", 16321 activeInfo.settings.notifications.position, 16322 "#FFF", 16323 "info", 16324 "5000" 16325 ); 16326 organizrAPI2("POST", "api/v2/homepage/weather/coordinates", { query: query }) 16327 .success(function (data) { 16328 try { 16329 let html = data.response; 16330 if (html.data.type == "FeatureCollection") { 16331 var entries = ""; 16332 $.each(html.data.features, function (i, v) { 16333 entries += 16334 '<li class="text-left"><i class="fa fa-caret-right text-info"></i><span class="mouse" onclick="addCoordinatesToInput(\'' + 16335 v.center[1] + 16336 "','" + 16337 v.center[0] + 16338 "')\">" + 16339 v.place_name + 16340 "</span></li>"; 16341 }); 16342 var div = 16343 ` 16344 <div class="row"> 16345 <div class="col-12"> 16346 <div class="card m-b-0"> 16347 <div class="form-horizontal"> 16348 <div class="card-body"> 16349 <h4 class="card-title" lang="en">Select Place</h4> 16350 <div class="form-group row"> 16351 <div class="col-sm-12"> 16352 <ul class="list-icons"> 16353 ` +
16354 entries + 16355 ` 16356 </ul> 16357 </div> 16358 </div> 16359 </div> 16360 </div> 16361 </div> 16362 </div> 16363 </div> 16364 `; 16365 if (entries !== "") { 16366 swal.close(); 16367 swal({ 16368 content: createElementFromHTML(div), 16369 buttons: false, 16370 className: "bg-org", 16371 }); 16372 } else { 16373 message( 16374 "API Error", 16375 "No results found...", 16376 activeInfo.settings.notifications.position, 16377 "#FFF", 16378 "warning", 16379 "10000" 16380 ); 16381 } 16382 } else { 16383 message( 16384 "API Error", 16385 "", 16386 activeInfo.settings.notifications.position, 16387 "#FFF", 16388 "warning", 16389 "10000" 16390 ); 16391 console.error("Organizr Function: API failed"); 16392 } 16393 } catch (e) { 16394 organizrCatchError(e, data); 16395 } 16396 }) 16397 .fail(function (xhr) { 16398 OrganizrApiError(xhr, "API Error"); 16399 }); 16400} 16401function showLookupCoordinatesModal() { 16402 var div = ` 16403 <div class="row"> 16404 <div class="col-12"> 16405 <div class="card m-b-0"> 16406 <div class="form-horizontal"> 16407 <div class="card-body"> 16408 <h4 class="card-title" lang="en">Enter City or Address</h4> 16409 <div class="form-group row"> 16410 <div class="col-sm-12"> 16411 <input type="text" class="form-control" id="coordinatesModalCityInput" placeholder="Enter City or Address..."> 16412 </div> 16413 </div> 16414 <div class="form-group mb-0 p-r-10 text-right"> 16415 <button type="submit" onclick="searchCoordinatesAPI($('#coordinatesModalCityInput').val())" class="btn btn-info waves-effect waves-light">Submit</button> 16416 </div> 16417 </div> 16418 </div> 16419 </div> 16420 </div> 16421 </div> 16422 `; 16423 swal({ 16424 content: createElementFromHTML(div),
16425 buttons: false, 16426 className: "bg-org", 16427 }); 16428} 16429function showLDAPLoginTest() { 16430 var div = ` 16431 <div class="row"> 16432 <div class="col-12"> 16433 <div class="card m-b-0"> 16434 <div class="form-horizontal"> 16435 <div class="card-body"> 16436 <h4 class="card-title" lang="en">LDAP User Info</h4> 16437 <div class="form-group row"> 16438 <div class="col-sm-12"> 16439 <input type="text" class="form-control" id="ldapUsernameTest" placeholder="Username"> 16440 </div> 16441 </div> 16442 <div class="form-group row"> 16443 <div class="col-sm-12"> 16444 <input type="password" class="form-control" id="ldapPasswordTest" placeholder="Password"> 16445 </div> 16446 </div> 16447 <div class="form-group mb-0 p-r-10 text-right"> 16448 <button type="submit" onclick="testAPIConnection('ldap/login', {'username':$('#ldapUsernameTest').val(),'password':$('#ldapPasswordTest').val()})" class="btn btn-info waves-effect waves-light">Test Login</button> 16449 </div> 16450 </div> 16451 </div> 16452 </div> 16453 </div> 16454 </div> 16455 `; 16456 swal({ 16457 content: createElementFromHTML(div),
16458 buttons: false, 16459 className: "bg-org", 16460 }); 16461} 16462 16463function showPlexTokenForm(selector = null) { 16464 var div = 16465 ` 16466 <form id="get-plex-token-form"> 16467 <h1 lang="en">Get Plex Token</h1> 16468 <div class="panel plexTokenHeader"> 16469 <div class="panel-heading plexTokenMessage" lang="en">Enter Plex Details</div> 16470 </div> 16471 <fieldset style="border:0;"> 16472 <div class="form-group"> 16473 <label class="control-label" for="plex-token-form-username" lang="en">Plex Username</label> 16474 <input type="text" class="form-control" id="plex-token-form-username" name="username" required="" autofocus> 16475 </div> 16476 <div class="form-group"> 16477 <label class="control-label" for="plex-token-form-password" lang="en">Plex Password</label> 16478 <input type="password" class="form-control" id="plex-token-form-password" name="password" required=""> 16479 </div> 16480 <div class="form-group"> 16481 <label class="control-label" for="plex-token-form-tfa" lang="en">Plex 2FA (if applicable)</label> 16482 <input type="text" class="form-control" id="plex-token-form-tfa" name="tfa" > 16483 </div> 16484 </fieldset> 16485 <button class="btn btn-sm btn-info btn-rounded waves-effect waves-light pull-right row b-none" onclick="getPlexToken('` + 16486 selector + 16487 `')" type="button"><span class="btn-label"><i class="fa fa-ticket"></i></span><span lang="en">Grab It</span></button> 16488 <div class="clearfix"></div> 16489 </form> 16490 `; 16491 swal({ 16492 content: createElementFromHTML(div),
16493 buttons: false, 16494 className: "bg-org", 16495 }); 16496} 16497function getPlexToken(selector) { 16498 $(".plexTokenMessage").text("Grabbing Token"); 16499 $(".plexTokenHeader") 16500 .addClass("panel-info") 16501 .removeClass("panel-warning") 16502 .removeClass("panel-danger"); 16503 var plex_username = $("#get-plex-token-form [name=username]").val().trim(); 16504 var plex_password = $("#get-plex-token-form [name=password]").val().trim(); 16505 var plex_tfa = $("#get-plex-token-form [name=tfa]").val().trim(); 16506 if (plex_password !== "" && plex_password !== "") { 16507 $.ajax({ 16508 type: "POST", 16509 headers: { 16510 "X-Plex-Product": "Organizr", 16511 "X-Plex-Version": "2.0", 16512 "X-Plex-Client-Identifier": "01010101-10101010", 16513 }, 16514 url: "https://plex.tv/users/sign_in.json", 16515 data: { 16516 "user[login]": plex_username, 16517 "user[password]": plex_password + plex_tfa, 16518 force: true, 16519 }, 16520 cache: false, 16521 async: true, 16522 complete: function (xhr, status) { 16523 var result = $.parseJSON(xhr.responseText); 16524 if (xhr.status === 201) { 16525 $(".plexTokenMessage").text(xhr.statusText); 16526 $(".plexTokenHeader") 16527 .addClass("panel-success") 16528 .removeClass("panel-info") 16529 .removeClass("panel-warning") 16530 .removeClass("panel-danger"); 16531 $(selector).val(result.user.authToken); 16532 $(selector).change(); 16533 messageSingle( 16534 "Token created", 16535 "Please save...", 16536 activeInfo.settings.notifications.position, 16537 "#FFF", 16538 "success", 16539 "5000" 16540 ); 16541 } else { 16542 $(".plexTokenMessage").text(xhr.statusText); 16543 $(".plexTokenHeader") 16544 .addClass("panel-danger") 16545 .removeClass("panel-info") 16546 .removeClass("panel-warning"); 16547 } 16548 }, 16549 }); 16550 } else { 16551 $(".plexTokenMessage").text("Enter Username and Password"); 16552 $(".plexTokenHeader") 16553 .addClass("panel-warning") 16554 .removeClass("panel-info") 16555 .removeClass("panel-danger"); 16556 } 16557} 16558function showPlexMachineForm(selector = null) { 16559 var div = ` 16560 <form id="get-plex-machine-form"> 16561 <h1 lang="en">Get Plex Machine</h1> 16562 <div class="panel plexMachineHeader"> 16563 <div class="panel-heading plexMachineMessage" lang="en">Contacting server...</div> 16564 </div> 16565 <fieldset style="border:0;"> 16566 <div class="form-group"> 16567 <label class="control-label" for="plex-machine-form-machine" lang="en">Plex Machine</label> 16568 <div class="plexMachineListing"></div> 16569 </div> 16570 </fieldset> 16571 <div class="clearfix"></div> 16572 </form> 16573 `; 16574 swal({ 16575 content: createElementFromHTML(div),
16576 buttons: false, 16577 className: "bg-org", 16578 }).then( 16579 organizrAPI2("GET", "api/v2/plex/servers?owned") 16580 .success(function (data) { 16581 try { 16582 let response = data.response; 16583 $(".plexMachineMessage").text("Choose Plex Server"); 16584 $(".plexMachineHeader") 16585 .addClass("panel-success") 16586 .removeClass("panel-info") 16587 .removeClass("panel-warning"); 16588 let machines = '<option lang="en">Choose Plex Machine</option>'; 16589 $.each(response.data, function (i, v) { 16590 let name = v.name; 16591 let machine = v.machineIdentifier; 16592 name = name + " [" + machine + "]"; 16593 machines += '<option value="' + machine + '">' + name + "</option>"; 16594 }); 16595 let listing = 16596 '<select class="form-control" id="plexMachineSelector" data-selector="' + 16597 selector + 16598 '" data-type="select">' + 16599 machines + 16600 "</select>"; 16601 $(".plexMachineListing").html(listing); 16602 } catch (e) { 16603 organizrCatchError(e, data); 16604 } 16605 }) 16606 .fail(function (xhr) { 16607 OrganizrApiError(xhr, "API Error"); 16608 $(".plexMachineMessage").text("Plex Token Needed First"); 16609 $(".plexMachineHeader") 16610 .addClass("panel-warning") 16611 .removeClass("panel-info") 16612 .removeClass("panel-danger"); 16613 }) 16614 ); 16615} 16616function bypassLocalLogin() { 16617 if (activeInfo.settings.user.bypass !== true) { 16618 return false; 16619 } 16620 const bypass = $.urlParam("bypassDisable"); 16621 if (bypass) { 16622 return false; 16623 } 16624 OAuthLoginNeeded = true; 16625 oAuthLoginNeededCheck("Bypass"); 16626} 16627function oAuthLoginNeededCheck(type = "OAuth") { 16628 if (OAuthLoginNeeded == false) { 16629 return false; 16630 } else { 16631 if (activeInfo.user.loggedin == true) { 16632 return false; 16633 } 16634 } 16635 let data = ""; 16636 if (type === "Bypass") { 16637 const bypass = $.urlParam("bypassDisable"); 16638 if (bypass) { 16639 data = "bypass"; 16640 } 16641 } 16642 message( 16643 type, 16644 " Proceeding to login", 16645 activeInfo.settings.notifications.position, 16646 "#FFF", 16647 "info", 16648 "10000" 16649 ); 16650 organizrAPI2("POST", "api/v2/login", data) 16651 .success(function (data) { 16652 local("set", "message", "Welcome|Login Successful|success"); 16653 local("r", "loggingIn"); 16654 location.reload(); 16655 }) 16656 .fail(function (xhr) { 16657 $("div.login-box").unblock({}); 16658 switch (xhr.status) { 16659 case 401: 16660 if (xhr.responseJSON.response.message == "2FA Code incorrect") { 16661 $("div.login-box").unblock({}); 16662 $("#tfa-div").removeClass("hidden"); 16663 $("#loginform [name=tfaCode]").focus(); 16664 } 16665 break; 16666 case 403: 16667 $("div.login-box").block({ 16668 message: '<h5><i class="fa fa-close"></i> Locked Out!</h4>', 16669 css: { 16670 color: "#fff", 16671 border: "1px solid #e91e63", 16672 backgroundColor: "#f44336", 16673 }, 16674 }); 16675 setTimeout(function () { 16676 local("r", "loggingIn"); 16677 location.reload(); 16678 }, 10000); 16679 break; 16680 case 422: 16681 $("div.login-box").unblock({}); 16682 $("#tfa-div").removeClass("hidden"); 16683 $("#loginform [name=tfaCode]").focus(); 16684 break; 16685 default: 16686 message( 16687 "Login Error", 16688 "API Connection Failed", 16689 activeInfo.settings.notifications.position, 16690 "#FFF", 16691 "error", 16692 "10000" 16693 ); 16694 console.error("Organizr Function: API Connection Failed"); 16695 } 16696 message( 16697 "Login Error", 16698 xhr.responseJSON.response.message, 16699 activeInfo.settings.notifications.position, 16700 "#FFF", 16701 "warning", 16702 "10000" 16703 ); 16704 console.error("Organizr Function: " + xhr.responseJSON.response.message); 16705 local("r", "loggingIn"); 16706 }); 16707} 16708function ipInfoSpan(ip) { 16709 return '<span class="ipInfo mouse">' + ip + "</span>"; 16710} 16711function jsFriendlyJSONStringify(s) { 16712 return JSON.stringify(s) 16713 .replace("'", "") 16714 .replace(/\u2028/g, "\\u2028") 16715 .replace(/\u2029/g, "\\u2029"); 16716} 16717function exportLogs() { 16718 const query = "api/v2/log/0?filter=NONE&pageSize=1000&offset=0"; 16719 $.get(query, function (data) { 16720 const logs = data.response.data.results;
16721 let csvContent = 16722 "data:text/csv;charset=utf-8,Date,Severity,Function,Message,IP Address,User\n"; 16723 logs.forEach(function (log) { 16724 const row = [ 16725 log.datetime, 16726 log.log_level, 16727 log.channel, 16728 log.message, 16729 log.remote_ip_address, 16730 log.username, 16731 ].join(","); 16732 csvContent += row + "\n"; 16733 }); 16734 const encodedUri = encodeURI(csvContent); 16735 const link = document.createElement("a"); 16736 link.setAttribute("href", encodedUri); 16737 link.setAttribute("download", "organizr_logs.csv"); 16738 document.body.appendChild(link); 16739 link.click(); 16740 document.body.removeChild(link); 16741 }); 16742} 16743function logContext(row) { 16744 let buttons = ""; 16745 buttons += 16746 Object.keys(row).length > 0 16747 ? '<button data-toggle="tooltip" title="" data-original-title="View Details" class="btn btn-xs btn-primary waves-effect waves-light log-details m-r-5" data-trace="' + 16748 row.trace_id + 16749 '"><i class="mdi mdi-file-find"></i></button>' 16750 : ""; 16751 buttons += 16752 Object.keys(row).length > 0 16753 ? '<button data-toggle="tooltip" title="" data-original-title="Copy Log" class="btn btn-xs btn-info waves-effect waves-light log-details m-r-5" data-trace="' + 16754 row.trace_id + 16755 '" data-clipboard="true"><i class="mdi mdi-content-copy"></i></button>' 16756 : ""; 16757 return buttons; 16758} 16759function formatLogDetails(details) { 16760 if (!details) { 16761 return false; 16762 } 16763 let m = moment.tz(details.datetime + "Z", activeInfo.timezone); 16764 details.datetime = moment(m).format("LLL"); 16765 let items = ""; 16766 items += `<li><div class="bg-inverse"><i class="mdi mdi-calendar-text text-white"></i></div> ${details.datetime}<span class="text-muted" lang="en">Date</span></li>`; 16767 items += `<li><div class="bg-warning"><i class="mdi mdi-robot text-white"></i></div> ${details.trace_id}<span class="text-muted" lang="en">Trace ID</span></li>`; 16768 items += `<li><div class="bg-primary"><i class="mdi mdi-account-box-outline text-white"></i></div> ${details.username}<span class="text-muted" lang="en">User</span></li>`; 16769 items += `<li><div class="bg-info"><i class="mdi mdi-function text-white"></i></div> ${details.channel}<span class="text-muted" lang="en">Function</span></li>`; 16770 items += `<li><div class="bg-plex"><i class="mdi mdi-language-php text-white"></i></div> ${details.file}<code>#L${details.line}</code><span class="text-muted" lang="en">File</span></li>`; 16771 let items2 = ""; 16772 items2 += 16773 Object.keys(details.context).length > 0 16774 ? `<div class="sl-item"><div class="sl-left bg-inverse"> <i class="mdi mdi-json"></i></div><div class="sl-right"><div class="p-t-10 desc" lang="en">Context</div></div><pre class="m-5 fc-scroller">${JSON.stringify( 16775 details.context, 16776 null, 16777 5 16778 )}</pre></div>` 16779 : ""; 16780 items2 += 16781 typeof details.errors !== "undefined" 16782 ? `<div class="sl-item"><div class="sl-left bg-danger"> <i class="mdi mdi-code-braces"></i></div><div class="sl-right"><div class="p-t-10 desc" lang="en">Errors</div></div><pre class="m-5 fc-scroller">${JSON.stringify( 16783 details.errors, 16784 null, 16785 5 16786 )}</pre></div>` 16787 : ""; 16788 var div = ` 16789 <div class="col-lg-12"> 16790 <div class="panel panel-default text-left"> 16791 <div class="panel-heading"><i class="mdi mdi-file-find fa-lg fa-2x"></i> <span lang="en">Log Details</span> <span class="pull-right">${logIcon( 16792 details.log_level, 16793 true 16794 )}</span></div> 16795 <div class="panel-wrapper collapse in"> 16796 <div class="panel-body bg-org"> 16797 <h3>${details.message}</h3> 16798 <div class="white-box"> 16799 <ul class="feeds"> 16800 ${items} 16801 </ul> 16802 </div> 16803 <div class="steamline"> 16804 ${items2} 16805 </div> 16806 </div> 16807 </div> 16808 </div> 16809 </div>`; 16810 swal({ 16811 content: createElementFromHTML(div),
16812 buttons: false, 16813 className: "orgAlertTransparent", 16814 }); 16815 pageLoad(); 16816} 16817function checkToken(activate = false) { 16818 if (typeof activeInfo !== "undefined") { 16819 if (typeof activeInfo.settings.misc.uuid !== "undefined") { 16820 var token = getCookie("organizr_token_" + activeInfo.settings.misc.uuid); 16821 if (token) { 16822 setTimeout(function () { 16823 checkToken(true); 16824 }, 5000); 16825 } else { 16826 if (activate) { 16827 local( 16828 "set", 16829 "message", 16830 "Token Expired|You have been logged out|error" 16831 ); 16832 location.reload(); 16833 } 16834 } 16835 } 16836 } 16837} 16838function objDiff(obj1, obj2) { 16839 // Make sure an object to compare is provided 16840 if (!obj2 || Object.prototype.toString.call(obj2) !== "[object Object]") { 16841 return obj1; 16842 } 16843 16844 // 16845 // Variables 16846 // 16847 16848 var diffs = {}; 16849 var key; 16850 16851 // 16852 // Methods 16853 // 16854 16855 /** 16856 * Check if two arrays are equal 16857 * @param {Array} arr1 The first array 16858 * @param {Array} arr2 The second array 16859 * @return {Boolean} If true, both arrays are equal 16860 */ 16861 var arraysMatch = function (arr1, arr2) { 16862 // Check if the arrays are the same length 16863 if (arr1.length !== arr2.length) return false; 16864 16865 // Check if all items exist and are in the same order 16866 for (var i = 0; i < arr1.length; i++) { 16867 if (arr1[i] !== arr2[i]) return false; 16868 } 16869 16870 // Otherwise, return true 16871 return true; 16872 }; 16873 16874 /** 16875 * Compare two items and push non-matches to object 16876 * @param {*} item1 The first item 16877 * @param {*} item2 The second item 16878 * @param {String} key The key in our object 16879 */ 16880 var compare = function (item1, item2, key) { 16881 // Get the object type 16882 var type1 = Object.prototype.toString.call(item1); 16883 var type2 = Object.prototype.toString.call(item2); 16884 16885 // If type2 is undefined it has been removed 16886 if (type2 === "[object Undefined]") { 16887 diffs[key] = null; 16888 return; 16889 } 16890 16891 // If items are different types 16892 if (type1 !== type2) { 16893 diffs[key] = item2; 16894 return; 16895 } 16896 16897 // If an object, compare recursively 16898 if (type1 === "[object Object]") { 16899 var objDifference = objDiff(item1, item2); 16900 if (Object.keys(objDifference).length > 1) { 16901 diffs[key] = objDifference; 16902 } 16903 return; 16904 } 16905 16906 // If an array, compare 16907 if (type1 === "[object Array]") { 16908 if (!arraysMatch(item1, item2)) { 16909 diffs[key] = item2; 16910 } 16911 return; 16912 } 16913 16914 // Else if it's a function, convert to a string and compare 16915 // Otherwise, just compare 16916 if (type1 === "[object Function]") { 16917 if (item1.toString() !== item2.toString()) { 16918 diffs[key] = item2; 16919 } 16920 } else { 16921 if (item1 !== item2) { 16922 diffs[key] = item2; 16923 } 16924 } 16925 }; 16926 16927 // 16928 // Compare our objects 16929 // 16930 16931 // Loop through the first object 16932 for (key in obj1) { 16933 if (obj1.hasOwnProperty(key)) { 16934 compare(obj1[key], obj2[key], key); 16935 } 16936 } 16937 16938 // Loop through the second object and find missing items 16939 for (key in obj2) { 16940 if (obj2.hasOwnProperty(key)) { 16941 if (!obj1[key] && obj1[key] !== obj2[key]) { 16942 diffs[key] = obj2[key]; 16943 } 16944 } 16945 } 16946 16947 // Return the object of differences 16948 return diffs; 16949} 16950function organizrConsole(subject, msg, type = "info") { 16951 let color; 16952 switch (type) { 16953 case "error": 16954 color = "#ed2e72"; 16955 break; 16956 case "warning": 16957 color = "#272361"; 16958 break; 16959 default: 16960 color = "#2cabe3"; 16961 break; 16962 } 16963 16964 console.info( 16965 "%c " + subject + " %c ".concat(msg, " "), 16966 "color: white; background: " + color + "; font-weight: 700;", 16967 "color: " + color + "; background: white; font-weight: 700;" 16968 ); 16969} 16970function organizrCatchError(e, data) { 16971 organizrConsole("Organizr API Function", data, "warning"); 16972 orgErrorAlert( 16973 "<h4>" + 16974 e + 16975 '</h4><p><mark lang="en">Trace Log has been outputted to Browser Console</mark></p><h5 lang="en">Output of last API call</h5>' + 16976 formatDebug(data) 16977 ); 16978 console.trace(); 16979 return false; 16980} 16981function OrganizrApiError(xhr, secondaryMessage = null) { 16982 let msg = ""; 16983 if (typeof xhr.responseJSON !== "undefined") { 16984 msg = xhr.responseJSON.response.message; 16985 } else if (typeof xhr.statusText !== "undefined") { 16986 msg = xhr.statusText; 16987 } else if (typeof xhr.responseText !== "undefined") { 16988 msg = xhr.responseText; 16989 } else {
16990 msg = "Connection Error"; 16991 } 16992 organizrConsole("Organizr API Function", msg, "error"); 16993 16994 if (msg !== "abort") { 16995 if (secondaryMessage) { 16996 messageSingle( 16997 secondaryMessage, 16998 msg, 16999 activeInfo.settings.notifications.position, 17000 "#FFF", 17001 "error", 17002 "10000" 17003 ); 17004 } 17005 console.trace(); 17006 } 17007 return false; 17008} 17009function checkForUpdates() { 17010 if ( 17011 activeInfo.user.loggedin && 17012 activeInfo.user.groupID <= 1 && 17013 activeInfo.settings.misc.checkForUpdate 17014 ) { 17015 updateCheck(); 17016 checkCommitLoad(); 17017 checkPluginUpdates(); 17018 } 17019} 17020 17021function loadJavascript(script = null, defer = false) { 17022 if (script) { 17023 organizrConsole("JS Loader", script); 17024 organizrConsole("JS Loader", "Checking if script is loaded..."); 17025 let loaded = $('script[src="' + script + '"]').length; 17026 if (!loaded) { 17027 organizrConsole("JS Loader", "Script is NOT loaded... Loading now..."); 17028 let head = document.getElementsByTagName("head")[0]; 17029 let scriptEl = document.createElement("script"); 17030 scriptEl.type = "text/javascript"; 17031 scriptEl.src = script; 17032 scriptEl.defer = false; 17033 head.appendChild(scriptEl); 17034 } else { 17035 organizrConsole("JS Loader", "Script already loaded"); 17036 } 17037 } 17038} 17039 17040function tabShit() {} 17041 17042function msToTime(s) { 17043 let pad = (n, z = 2) => ("00" + n).slice(-z); 17044 let hours = pad((s / 3.6e6) | 0) !== "00" ? pad((s / 3.6e6) | 0) + ":" : ""; 17045 let mins = pad(((s % 3.6e6) / 6e4) | 0) + ":"; 17046 let secs = pad(((s % 6e4) / 1000) | 0); 17047 let ms = pad(s % 1000, 3); 17048 if (ms >= "500") { 17049 secs = pad(parseFloat(secs) + 1, 2); 17050 } 17051 return hours + mins + secs; 17052} 17053function clickSettingsTab() { 17054 let tabs = $(".allTabsList"); 17055 $.each(tabs, function (i, v) { 17056 let tab = $(v); 17057 if (tab.attr("data-url") == "api/v2/page/settings") { 17058 tab.find("a").trigger("click"); 17059 } 17060 }); 17061} 17062function clickMenuItem(selector) { 17063 if ($(selector).length >= 1) { 17064 $(selector).click(); 17065 } else { 17066 $("body").arrive(selector, { onceOnly: true }, function () { 17067 $(selector).click(); 17068 }); 17069 } 17070} 17071function shortcut(selectors = "") { 17072 let timeout = 200; 17073 if (typeof selectors == "string") { 17074 if (selectors == "") { 17075 selectors = []; 17076 } else { 17077 switch (selectors) { 17078 case "log-settings": 17079 clickSettingsTab(); 17080 selectors = [ 17081 "#settings-main-system-settings-anchor", 17082 "#settings-settings-main-anchor", 17083 'a[href$="Logs"]', 17084 ]; 17085 break; 17086 case "plugin-marketplace": 17087 clickSettingsTab(); 17088 selectors = [ 17089 "#settings-main-plugins-anchor", 17090 "#settings-plugins-marketplace-anchor", 17091 ]; 17092 break; 17093 case "custom-cert": 17094 clickSettingsTab(); 17095 selectors = [ 17096 "#settings-main-system-settings-anchor", 17097 "#settings-settings-main-anchor", 17098 'a[href$="Certificate"]', 17099 ]; 17100 break; 17101 default: 17102 clickSettingsTab(); 17103 selectors = ["#settings-main-system-settings-anchor"]; 17104 } 17105 } 17106 } 17107 selectors.forEach(function (selector) { 17108 timeout = timeout + 200; 17109 setTimeout(function () { 17110 clickMenuItem(selector); 17111 }, timeout); 17112 }); 17113} 17114function getJournalMode() { 17115 organizrAPI2("GET", "api/v2/database/journal") 17116 .success(function (data) { 17117 try { 17118 let response = data.response; 17119 $(".journal-mode").html(response.data.journal_mode); 17120 } catch (e) { 17121 organizrCatchError(e, data); 17122 } 17123 }) 17124 .fail(function (xhr) { 17125 OrganizrApiError(xhr); 17126 }); 17127} 17128function setJournalMode(mode) { 17129 messageSingle( 17130 "Setting New Journal Mode", 17131 "", 17132 activeInfo.settings.notifications.position, 17133 "#FFF", 17134 "info", 17135 "1500" 17136 ); 17137 organizrAPI2("PUT", "api/v2/database/journal/" + mode, {}) 17138 .success(function (data) { 17139 try { 17140 getJournalMode(); 17141 let response = data.response; 17142 message( 17143 "Set New Journal Mode", 17144 response.data.journal_mode, 17145 activeInfo.settings.notifications.position, 17146 "#FFF", 17147 "success", 17148 "5000" 17149 ); 17150 } catch (e) { 17151 organizrCatchError(e, data); 17152 } 17153 }) 17154 .fail(function (xhr) { 17155 OrganizrApiError(xhr); 17156 }); 17157} 17158function toggleSideMenuClasses() { 17159 $("#page-wrapper").toggleClass("sidebar-hidden"); 17160 $(".sidebar").toggleClass("sidebar-hidden"); 17161 $(".navbar").toggleClass("sidebar-hidden"); 17162} 17163function sideMenuCollapsed() { 17164 if (activeInfo.settings.misc.sideMenuCollapsed) { 17165 toggleSideMenuClasses(); 17166 } 17167} 17168function toggleSideMenu() { 17169 toggleSideMenuClasses(); 17170 $(".sidebar-head .open-close i") 17171 .first() 17172 .toggleClass("ti-menu ti-shift-left mouse"); 17173 $(".toggle-side-menu").toggleClass("hidden"); 17174} 17175 17176function toggleTopBarHamburger() { 17177 toggleSideMenuClasses(); 17178 $(".sidebar-head .hide-menu.hidden-xs").text("Hide Menu"); 17179 $(".sidebar-head .open-close i") 17180 .first() 17181 .toggleClass("ti-menu ti-shift-left mouse"); 17182 $(".toggle-side-menu").toggleClass("hidden"); 17183} 17184function toggleLogFilter(filter = "INFO") { 17185 //choose-organizr-log
17186 filter = filter.toUpperCase(); 17187 $.each($(".choose-organizr-log").children(), function (i, v) { 17188 let url = $(v).val(); 17189 let newURL = updateUrlParameter(url, "filter", filter); 17190 $(v).val(newURL); 17191 }); 17192 $(".log-filter-text").text(filter); 17193 $(".log-filter-text").text(filter); 17194 let currentURL = organizrLogTable.ajax.url(); 17195 let updatedURL = updateUrlParameter(currentURL, "filter", filter); 17196 organizrLogTable.ajax.url(updatedURL); 17197 organizrLogTable.clear().draw().ajax.reload(null, false); 17198} 17199function updateUrlParameter(uri, key, value) { 17200 // remove the hash part before operating on the uri 17201 var i = uri.indexOf("#"); 17202 var hash = i === -1 ? "" : uri.substr(i); 17203 uri = i === -1 ? uri : uri.substr(0, i); 17204 var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"); 17205 var separator = uri.indexOf("?") !== -1 ? "&" : "?"; 17206 if (value === null) { 17207 // remove key-value pair if value is specifically null 17208 uri = uri.replace(new RegExp("([?&]?)" + key + "=[^&]*", "i"), ""); 17209 if (uri.slice(-1) === "?") { 17210 uri = uri.slice(0, -1); 17211 } 17212 // replace first occurrence of & by ? if no ? is present 17213 if (uri.indexOf("?") === -1) uri = uri.replace(/&/, "?"); 17214 } else if (uri.match(re)) { 17215 uri = uri.replace(re, "$1" + key + "=" + value + "$2"); 17216 } else { 17217 uri = uri + separator + key + "=" + value; 17218 } 17219 return uri + hash; 17220} 17221function launch() { 17222 console.info( 17223 "https://docs.organizr.app/help/faq/migration-guide#version-2-0-greater-than-version-2-1" 17224 ); 17225 organizrConsole( 17226 "API V2 API", 17227 "If you see a 404 Error for api/v2/launch below this line, you have not setup the new location block... See URL above this line", 17228 "error" 17229 ); 17230 organizrConnect("api/v2/launch") 17231 .success(function (data) { 17232 try { 17233 let json = data.response; 17234 if (json.data.user == false) { 17235 location.reload(); 17236 } 17237 currentVersion = json.data.version; 17238 activeInfo = { 17239 tabs: json.data.tabs, 17240 categories: json.data.categories, 17241 timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, 17242 offest: new Date().getTimezoneOffset(), 17243 language: language(moment.locale(navigator.languages[0])), 17244 browserVersion: bowser.name, 17245 browserName: bowser.version, 17246 mobile: bowser.mobile, 17247 tablet: bowser.tablet, 17248 osName: bowser.osname, 17249 osVersion: bowser.osversion, 17250 serverOS: json.data.status.os, 17251 phpVersion: json.data.status.php, 17252 token: json.data.user.token, 17253 user: json.data.user, 17254 plugins: json.data.plugins, 17255 branch: json.data.branch, 17256 sso: json.data.sso, 17257 settings: json.data.settings, 17258 appearance: json.data.appearance, 17259 theme: json.data.theme, 17260 style: json.data.style, 17261 version: json.data.version, 17262 }; 17263 // Add element to signal activeInfo Ready 17264 $("#wrapper").after('<div id="activeInfo"></div>'); 17265 console.info( 17266 "%c Organizr %c ".concat(currentVersion, " "), 17267 "color: white; background: #66D9EF; font-weight: 700; font-size: 24px; font-family: Monospace;", 17268 "color: #66D9EF; background: white; font-weight: 700; font-size: 24px; font-family: Monospace;" 17269 ); 17270 console.info( 17271 "%c Status %c ".concat("Starting Up...", " "), 17272 "color: white; background: #F92671; font-weight: 700;", 17273 "color: #F92671; background: white; font-weight: 700;" 17274 ); 17275 //local('set','initial',true); 17276 //setTimeout(function(){ local('r','initial'); }, 300); 17277 defineNotification(); 17278 checkMessage(); 17279 errorPage(); 17280 uriRedirect(); 17281 changeStyle(activeInfo.style); 17282 //changeTheme(activeInfo.theme); 17283 setSSO(); 17284 checkToken(); 17285 switch (json.data.status.status) { 17286 case "wizard": 17287 buildWizard(); 17288 buildLanguage("wizard"); 17289 break; 17290 case "dependencies": 17291 buildDependencyCheck(json); 17292 break; 17293 case "ok": 17294 loadAppearance(json.data.appearance); 17295 sideMenuCollapsed(); 17296 if (activeInfo.user.locked == 1) { 17297 buildLockscreen(); 17298 } else { 17299 userMenu(json); 17300 categoryProcess(json); 17301 tabProcess(json); 17302 buildSplashScreen(json); 17303 accountManager(json); 17304 organizrSpecialSettings(json.data); 17305 getPingList(json); 17306 checkLocalForwardStatus(json.data); 17307 checkForUpdates(); 17308 } 17309 loadCustomJava(json.data.appearance); 17310 if (getCookie("lockout")) { 17311 $(".show-login").click(); 17312 setTimeout(function () { 17313 $("div.login-box").block({ 17314 message: '<h5><i class="fa fa-close"></i> Locked Out!</h4>', 17315 css: { 17316 color: "#fff", 17317 border: "1px solid #e91e63", 17318 backgroundColor: "#f44336", 17319 }, 17320 }); 17321 }, 1000); 17322 setTimeout(function () { 17323 location.reload(); 17324 }, 60000); 17325 } 17326 break; 17327 default: 17328 console.error("Organizr Function: Action not set or defined"); 17329 } 17330 console.info( 17331 "%c Organizr %c ".concat("DOM Fully loaded", " "), 17332 "color: white; background: #AD80FD; font-weight: 700;", 17333 "color: #AD80FD; background: white; font-weight: 700;" 17334 ); 17335 oAuthLoginNeededCheck(); 17336 bypassLocalLogin(); 17337 } catch (e) { 17338 orgErrorCode(data); 17339 defineNotification(); 17340 message("FATAL ERROR", data, "br", "#FFF", "error", "60000"); 17341 console.warn(data); 17342 console.warn(e); 17343 return false;
17344 } 17345 }) 17346 .fail(function (xhr) { 17347 defineNotification(); 17348 if (xhr.status == 404) { 17349 orgErrorAlert( 17350 '<h2>Webserver not setup for Organizr v2.1</h2><h4>Please goto <a href="https://docs.organizr.app/help/faq/migration-guide#version-2-0-greater-than-version-2-1">Migration guide to complete the changes...</a></h4><h3>Webserver Error:</h3>' + 17351 xhr.responseText 17352 ); 17353 message( 17354 "FATAL ERROR", 17355 "You need to update webserver location block... check browser console for migration URL", 17356 "br", 17357 "#FFF", 17358 "error", 17359 "60000" 17360 ); 17361 } else { 17362 orgErrorAlert("<h3>Webserver Error:</h3>" + xhr.responseText); 17363 } 17364 }); 17365} 17366 17367function homepageBookmarks(timeout) { 17368 var timeout = 17369 typeof timeout !== "undefined" 17370 ? timeout 17371 : activeInfo.settings.homepage.refresh.homepageBookmarksRefresh; 17372 organizrAPI2("GET", "api/v2/plugins/bookmark/page") 17373 .success(function (data) { 17374 try { 17375 let response = data.response; 17376 document.getElementById("homepageOrderBookmarks").innerHTML = ""; 17377 if (response.data !== null) {
17378 $("#homepageOrderBookmarks").html(buildBookmarks(response.data)); 17379 } 17380 } catch (e) { 17381 organizrCatchError(e, data); 17382 } 17383 }) 17384 .fail(function (xhr) { 17385 OrganizrApiError(xhr); 17386 }); 17387 let timeoutTitle = "Bookmarks-Homepage"; 17388 if (typeof timeouts[timeoutTitle] !== "undefined") { 17389 clearTimeout(timeouts[timeoutTitle]); 17390 } 17391 timeouts[timeoutTitle] = setTimeout(function () { 17392 homepageBookmarks(timeout); 17393 }, timeout); 17394 delete timeout; 17395} 17396 17397function buildBookmarks(data) { 17398 var returnData = data; 17399 return returnData; 17400}
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.