openpanel/templates/admini/base.html

1249 lines
51 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link rel="icon" type="image/x-icon" href="https://openpanel.com/img/favicon.svg">
<!-- page meta -->
<meta name="description" content="OpenPanel - Control Panel" />
<meta name="author" content="Stefan Pejcic" />
<meta name="keywords" content="openpanel, openadmin, opencli, docker, hosting, control, panel" />
<meta name="robots" content="noindex,nofollow">
<!-- performance -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- page title & icon -->
<link rel="icon" type="image/x-icon" href="/static/assets/img/favicon.svg">
<title>{{ title }} - {% if brand_name %}{{brand_name}}{% else %}{{brand}}{% endif %}</title>
<!-- styles -->
<link href="/static/css3/admini.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap" rel="stylesheet" />
<!-- scripts -->
<script src="/static/lib/jquery/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
{% if current_route == "/server/webserver_conf" or title == "PHP.INI Editor" %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.css">
<!-- Include CodeMirror JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.js"></script>
<!-- Include CodeMirror mode for the desired language -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/mode/clike/clike.min.js"></script>
<!-- Include CodeMirror theme -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/theme/dracula.min.css">
<style>
.CodeMirror {
min-height: 50vh;
height: auto;
}
</style>
{% endif %}
<!-- icons -->
<!--script src="/static/js3/last-icon.min.js"></script-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Two+Tone" rel="stylesheet" />
<!-- scripts -->
<script type="module" src="/static/js3/admini.min.js"></script>
{% if current_route.startswith('/usage') %}
<!-- Include Raphael Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.3.0/raphael.min.js"></script>
<!-- Include JustGage Library -->
<script src="https://cdn.jsdelivr.net/npm/justgage@1.4.0/justgage.min.js"></script>
{% endif %}
<style>
.main-header { border-bottom: 1px solid #f3f5f9;
background-color: #fff;}
.container-fluid {
background-color: #fbfcfe;}
.h6.card-title { color: rgba(233,236,239,.7);}
.nije-link {text-decoration: none;color: #212830;}
button svg path {stroke: white;}
.table>:not(caption)>*>* {
padding: 0.5rem 0.5rem; }
.card-header {
padding: 1.25em 1em 0 1em; }
/* dark side */
[data-bs-theme="dark"] .nije-link {color: unset;}
[data-bs-theme="dark"] .dash-links {color: unset;}
[data-bs-theme="dark"] .container-fluid {background-color: unset;}
[data-bs-theme="dark"] div.sidebar-storage.mb-2 i {color: #939ba2!important;}
[data-bs-theme="dark"] .card .card-title {font-size: .925rem; color: #939ba2!important;}
[data-bs-theme="dark"] .bg-light {background: #0b1a22!important; color: white !important;}
[data-bs-theme="dark"] .icon {color: #0b1a22!important;}
[data-bs-theme="dark"] .no_link { color:unset;}
[data-bs-theme="dark"] .sidebar {background: black;}
[data-bs-theme="dark"] .sidebar-brand {background: black;}
/* */
.bg-light {background: white!important; color: #000 !important;}
/*.sidebar {background-image: linear-gradient(to bottom, #212830, black);}*/
body.minimenu .sidebar_open {display:none;}
.sidebar-storage { display: flex;}
a:hover {text-decoration: none;}
.sidebar-footer, .sidebar-profile-mini {display: flex;flex: 0 0 30px;}
.minimenu .sidebar .sidebar-link l-i {font-size: x-large;}
.h1 > .card-title {font-size: x-large;}
li.breadcrumb-item.smaller, .smaller {font-size: 0.8em!important;}
.card .card-title {font-size: .925rem; color: #495057;}
div.card-header{display: inline-flex;}
.container-fluid {padding-top: calc(var(--bs-gutter-x));}
.sidebar-profile .dropdown-menu {left: 1px;width: -webkit-fill-available;bottom: 4rem; top:auto;}
.dropdown-menu.dropdown-menu-dark.show { background: #020c11; border-top: 1px solid rgba(255,255,255,.15);}
.dropdown-item:hover {color: #e9ecef; background: #020c11; border-left-color: rgba(0,0,0,0);}
/* Styles for mobile */
@media (max-width: 767px) {
.desktop-only {
display: none;
}
}
/* Styles for desktop */
@media (min-width: 768px) {
.mobile-only {
display: none;
}
}
</style>
{% block custom_header %}
<!-- custom code in header: https://dev.openpanel.com/customize.html#Code-in-Header -->
{% include 'custom_code/in_header.html' %}
{% endblock %}
<!-- custom css code: https://dev.openpanel.com/customize.html#Custom-CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/custom.css') }}">
</head>
<!-- minimenu class should be applied on render -->
<body>
<div class="wrapper">
<sco-pe id="sidebar-scope">{% include 'partials/sidebar.html' %}</sco-pe>
{% set applications_available_for_install = 0 %}
{% if 'wordpress' in enabled_modules %}
{% set applications_available_for_install = applications_available_for_install + 1 %}
{% endif %}
{% if 'pm2' in enabled_modules %}
{% set applications_available_for_install = applications_available_for_install + 1 %}
{% endif %}
{% if 'mautic' in enabled_modules %}
{% set applications_available_for_install = applications_available_for_install + 1 %}
{% endif %}
{% if 'flarum' in enabled_modules %}
{% set applications_available_for_install = applications_available_for_install + 1 %}
{% endif %}
<div class="modal fade" id="cardModal" tabindex="-1" role="dialog" aria-labelledby="cardModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header text-center">
<h5 class="modal-title" id="cardModalLabel">{{ _('What kind of site would you like to create?') }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row row-cols-1 row-cols-md-2 g-4">
<div class="col">
<div class="card h-100" style="margin-botton:0;">
<div class="row g-0">
<div class="col-md-4">
<img src="/static/images/install_site.avif" class="img-fluid rounded-start" alt="Install an Application">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">Install an Application</h5>
<p class="card-text">Create your site by installing a web app, such as WordPress or Mautic.</p>
<p class="card-text"><small class="text-body-secondary"><b>{{ applications_available_for_install }}</b> Applications Available</small></p>
</div>
</div>
</div>
<div class="card-footer">
<a href="/auto-installer" class="btn btn-outline-primary w-100">Install Apps</a>
</div>
</div>
</div>
<div class="col">
<div class="card h-100" style="margin-botton:0;">
<div class="row g-0">
<div class="col-md-4">
<img src="/static/images/upload_site.avif" class="img-fluid rounded-start" alt="Create a Custom Website">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">Create a Custom Website</h5>
<p class="card-text">Upload your web content and add databases.</p>
<p class="card-text"><small class="text-body-secondary">&nbsp;</small></p>
</div>
</div>
</div>
<div class="card-footer">
<div class="btn-group w-100" role="group" aria-label="Actions">
<a class="btn btn-outline-primary w-50" href="/files">Files</a>
<a class="btn btn-outline-primary btn-mobile-collapse w-50" href="/databases#wizard">
<span>Databases</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<sco-pe id="main-scope">
<main class="main">
{% if current_route.startswith('/website') %}
<!-- optional selector -->
{% if user_websites %}
{% if 'wordpress' in enabled_modules or 'pm2' in enabled_modules or 'mautic' in enabled_modules or 'flarum' in enabled_modules %}
<!--div class="sidemenu offcanvas-lg offcanvas-end d-none" style="width: 320px" id="my-scroll-panel">
<header class="sidemenu-header">
<strong>{{ _('Websites') }}</strong>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" data-bs-target="#my-scroll-panel" aria-label="Close"></button>
</header>
<section class="scroller">
<div class="p-3">
{% for site in user_websites %}
<span class="">
<a class="btn btn-outline-primary mb-3 d-block text-start" href="/{% if site[1] == 'NodeJS' %}pm2{% elif site[1] == 'Python' %}pm2{% else %}website?domain={{ site[0] }}{% endif %}" style="text-overflow: ellipsis; overflow: hidden;white-space: nowrap;line-break: anywhere;"><img src="https://www.google.com/s2/favicons?domain={{ site[0] }}" alt="{{ site[0] }} Favicon" style="width: 16px; height: 16px; margin-right:10px;">{{ site[0] }}</a>
</span>
{% endfor %}
</div>
</section>
<footer class="d-none sidemenu-footer">
<div>
<span class="badge bg-dark">X</span>
websites
</div>
<div class="dropup dropend">
<button class="btn btn-default" id="custom-dropdown-btn" data-bs-toggle="dropdown">
<l-i name="insert_comment"><i class="material-icons-two-tone">hey you</i></l-i>
</button>
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="custom-dropdown-btn">
<li><a class="dropdown-item" href="#">want a job?</a></li>
<li><a class="dropdown-item" href="#">info at openpanel dot com</a></li>
<li>
<hr class="dropdown-divider">
</li>
<p class="m-3 mb-0">
<small>Soon..</small>
</p>
</ul>
</div>
</footer>
</div-->
{% endif %}
{% endif %}
{% endif %}
<div class="main-container">
{% if current_route.startswith('/website') %}
{% endif %}
{% if session.get('impersonate') %}
<div class="main-header" id="impersonate-banner" style="display:table; background: rgb(255, 208, 62);justify-content: space-around;height: 35px;">
<div class="main-header-info row">
<p class="mb-0 col">{{ _("You are currently impersonating user") }} '{{current_username}}'</p>
<a id="admin-return-link" href="#" class="col-md-2 btn rounded-0 btn-dark">Return to admin</a>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var currentHost = window.location.hostname;
var newPort = '2087';
var currentUsername = '{{current_username}}';
var newUrl = 'http://' + currentHost + ':' + newPort + '/users/' + encodeURIComponent(currentUsername);
var link = document.getElementById('admin-return-link');
link.href = newUrl;
});
</script>
{% endif %}
{% if current_route.startswith('/files') %}
<script>
$(document).ready(function(){
var breadcrumbContainer = document.querySelector(".breadcrumb");
if (breadcrumbContainer) {
var breadcrumbItems = breadcrumbContainer.querySelectorAll("li");
var maxVisibleItems = 13;
// Create "Copy Path to Clipboard" button
var copyButton = document.createElement("li");
copyButton.innerHTML = '<a class="black-white" href="#" data-toggle="tooltip" data-placement="bottom" title="{{ _('Copy Path to Clipboard') }}" id="copy-button"><i class="bi bi-copy"></i></a>';
if (breadcrumbItems.length > maxVisibleItems) {
copyButton.className = "breadcrumb-item";
}
if (breadcrumbItems.length <= maxVisibleItems) {
var spaceItem = document.createElement("li");
spaceItem.innerHTML = '<a>&nbsp;</a>';
breadcrumbContainer.appendChild(spaceItem);
}
breadcrumbContainer.appendChild(copyButton);
if (breadcrumbItems.length > maxVisibleItems) {
for (var i = 1; i < breadcrumbItems.length - 1; i++) {
breadcrumbItems[i].style.display = "none";
}
// Create ellipsis link
var ellipsis = document.createElement("li");
ellipsis.className = "breadcrumb-item";
ellipsis.innerHTML = '<a href="#" data-toggle="tooltip" data-placement="bottom" title="{{ _('Click to display the full path') }}" id="breadcrumb-ellipsis"><i class="bi bi-three-dots"></i></a>';
breadcrumbItems[0].parentNode.insertBefore(ellipsis, breadcrumbItems[1]);
var ellipsisLink = document.getElementById("breadcrumb-ellipsis");
ellipsisLink.addEventListener("click", function(event) {
event.preventDefault();
for (var i = 1; i < breadcrumbItems.length - 1; i++) {
breadcrumbItems[i].style.display = (breadcrumbItems[i].style.display === "none") ? "" : "none";
}
// Toggle the visibility of the ellipsis link
ellipsis.style.display = (ellipsis.style.display === "none") ? "" : "none";
});
}
// Event listener for the "Copy Path to Clipboard" button
var copyButtonLink = document.getElementById("copy-button");
copyButtonLink.addEventListener("click", function(event) {
event.preventDefault();
// Get the full path and strip brackets from the first part
var fullPath = breadcrumbItems[0].textContent.trim().replace(/^\((.*?)\)/, '$1');
for (var i = 1; i < breadcrumbItems.length; i++) {
fullPath += '/' + breadcrumbItems[i].textContent.trim();
}
// Strip out everything before and including the first `(`, then remove `)`
fullPath = fullPath.replace(/.*\((.*?)\)/, '$1');
// Replace double slashes `//` with a single slash `/`
fullPath = fullPath.replace(/\/\//g, '/');
// Use Clipboard API if available, otherwise fallback
if (navigator.clipboard && navigator.clipboard.writeText) {
// Use Clipboard API
navigator.clipboard.writeText(fullPath)
.then(function() {
console.log('Path copied to clipboard: ' + fullPath);
var copyButton = document.getElementById('copy-button');
if (copyButton) {
var originalTitle = copyButton.getAttribute('data-bs-original-title');
copyButton.setAttribute('data-bs-original-title', 'Copied to Clipboard!');
// Manually show the tooltip to update the text
var tooltip = bootstrap.Tooltip.getInstance(copyButton);
if (tooltip) {
tooltip.update(); // Update the tooltip to reflect the new title
} else {
// Initialize tooltip if it doesn't exist
new bootstrap.Tooltip(copyButton);
}
// Optionally show the tooltip immediately
copyButton.setAttribute('data-bs-toggle', 'tooltip');
bootstrap.Tooltip.getInstance(copyButton).show();
// Revert tooltip text after 2 seconds
setTimeout(function() {
copyButton.setAttribute('data-bs-original-title', originalTitle);
var tooltip = bootstrap.Tooltip.getInstance(copyButton);
if (tooltip) {
tooltip.update(); // Update the tooltip to reflect the reverted title
}
}, 2000);
}
})
.catch(function(err) {
console.error('Unable to copy path to clipboard', err);
});
} else {
// Fallback to document.execCommand('copy')
var tempTextarea = document.createElement("textarea");
tempTextarea.value = fullPath;
tempTextarea.style.position = "absolute";
tempTextarea.style.left = "-9999px";
document.body.appendChild(tempTextarea);
tempTextarea.select();
try {
document.execCommand('copy');
console.log('Path copied to clipboard (fallback): ' + fullPath);
var copyButton = document.getElementById('copy-button');
if (copyButton) {
var originalTitle = copyButton.getAttribute('data-bs-original-title');
copyButton.setAttribute('data-bs-original-title', 'Copied to Clipboard!');
// Manually show the tooltip to update the text
var tooltip = bootstrap.Tooltip.getInstance(copyButton);
if (tooltip) {
tooltip.update(); // Update the tooltip to reflect the new title
} else {
// Initialize tooltip if it doesn't exist
new bootstrap.Tooltip(copyButton);
}
// Optionally show the tooltip immediately
copyButton.setAttribute('data-bs-toggle', 'tooltip');
bootstrap.Tooltip.getInstance(copyButton).show();
// Revert tooltip text after 2 seconds
setTimeout(function() {
copyButton.setAttribute('data-bs-original-title', originalTitle);
var tooltip = bootstrap.Tooltip.getInstance(copyButton);
if (tooltip) {
tooltip.update(); // Update the tooltip to reflect the reverted title
}
}, 2000);
}
} catch (err) {
console.error('Fallback: Unable to copy', err);
}
document.body.removeChild(tempTextarea);
}
});
}
});
</script>
<header class="main-header">
<div class="main-header-sidebar">
<button type="button" class="btn btn-primary btn-flex btn-square rounded-0" data-bs-toggle="offcanvas"
data-bs-target="#sidebar">
<svg xmlns="http://www.w3.org/2000/svg" width="28.418" height="16.333" viewBox="0 0 28.418 16.333"><g id="Group_1778" data-name="Group 1778" transform="translate(-306.83 -126.235)"><path id="Path_19286" data-name="Path 19286" d="M0,0,4.693,3.713,9.324-.044,14.13,3.669l5.285-3.76,4.513,3.715" transform="matrix(1, -0.017, 0.017, 1, 308.973, 128.797)" fill="none" stroke="#03040a" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"></path><path id="Path_19287" data-name="Path 19287" d="M0,0,4.693,3.713,9.324-.044,14.13,3.669l5.285-3.76,4.513,3.715" transform="matrix(1, -0.017, 0.017, 1, 309.113, 136.796)" fill="none" stroke="#03040a" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"></path></g></svg>
</button>
</div>
<div class="main-header-info">
<!--a class="btn btn-default btn-square btn-flex rounded-0 main-header-info-back" href="/">
<l-i name="navigate_before"></l-i>
<span class="visually-hidden">Navigate up a folder</span>
</a-->
<nav aria-label="breadcrumb">
<div class="breadcrumb">
<li class="breadcrumb-item active" aria-current="page">{% if wp_name %}{{ wp_name }}{% else %}{{ title }}{% endif %}</li>
<li class="breadcrumb-break"></li>
<li class="breadcrumb-item smaller"><a href="{{ url_for('files') }}"><i class="bi bi-house-fill"></i> (/home/{{ current_username }})</a></li>
{% set path_parts = path_param.split('/') %}
{% for index in range(path_parts|length) %}
{% set part = path_parts[index] %}
{% set breadcrumb_path = path_parts[:index+1]|join('/') %}
<li class="breadcrumb-item smaller active"><a aria-current="page" href="{{ url_for('files', path_param=breadcrumb_path) }}">{{ part }}</a>/</li>
{% endfor %}
</div>
</nav>
</div>
<div class="main-header-nav">
<div class="btn-group" aria-label="{{ _('Navigation') }}">
<input type="text" class="form-control search-bar" id="searchInput" style="display: none;" placeholder="{{ _('Search Files & Folders') }}">
<ul class="dropdown-menu scroller" style="top: 100%; width: 100%; right: 0px; overflow-x: hidden; overflow-y: overlay; max-height: 90vh;" aria-labelledby="searchInput" id="filteredDropdown">
</ul>
<button class="btn rounded-0 btn-primary-outlined" id="refresh-button">
<span class="desktop-text"><i class="bi bi-arrow-clockwise"></i> {{ _('Reload') }}</span>
<i class="mobile-icon bi bi-arrow-clockwise"></i>
</button>
<script>
// Use 'shown.bs.modal' event to autofocus inputs
window.onload = function() {
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('createFileModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('fileName').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('MmoveModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('MmoveDestination').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('McopyModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('McopyDestination').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('MextractModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('MextractPath').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('McompressModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('McompressArchiveName').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('renameModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('newRenameFileName').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('createFolderModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('folderName').focus();
});
var createfilemodal_shown = new bootstrap.Modal(document.getElementById('uploadModal'));
createfilemodal_shown._element.addEventListener('shown.bs.modal', function () {
document.getElementById('fileUpload').focus();
});
});
</script>
<button class="btn rounded-0 btn-dark" id="newFileButton" data-bs-toggle="modal" data-bs-target="#createFileModal">
<span class="desktop-text"><i class="bi bi-plus-lg"></i> {{ _('New File') }}</span>
<i class="mobile-icon bi bi-file-earmark-plus"></i>
</button>
<button class="btn rounded-0 btn-dark" id="newFolderButton" data-bs-toggle="modal" data-bs-target="#createFolderModal">
<span class="desktop-text"><i class="bi bi-folder-plus"></i> {{ _('New Folder') }}</span>
<i class="mobile-icon bi bi-folder-plus"></i>
</button>
<button class="btn rounded-0 btn-dark" id="uploadButton" data-bs-toggle="modal" data-bs-target="#uploadModal">
<span class="desktop-text"><i class="bi bi-upload"></i> {{ _('Upload') }}</span>
<i class="mobile-icon bi bi-upload"></i>
</button>
<button class="btn" id="searchIcon" onclick="toggleSearchBar()">
<i class="bi bi-search" style="font-size: large;"></i>
</button>
</div>
</div>
</header>
{% else %}
<header class="main-header">
<div class="main-header-sidebar">
<button type="button" class="btn btn-primary btn-flex btn-square rounded-0" data-bs-toggle="offcanvas"
data-bs-target="#sidebar" aria-controls="sidebar">
<svg xmlns="http://www.w3.org/2000/svg" width="28.418" height="16.333" viewBox="0 0 28.418 16.333"><g id="Group_1778" data-name="Group 1778" transform="translate(-306.83 -126.235)"><path id="Path_19286" data-name="Path 19286" d="M0,0,4.693,3.713,9.324-.044,14.13,3.669l5.285-3.76,4.513,3.715" transform="matrix(1, -0.017, 0.017, 1, 308.973, 128.797)" fill="none" stroke="#03040a" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"></path><path id="Path_19287" data-name="Path 19287" d="M0,0,4.693,3.713,9.324-.044,14.13,3.669l5.285-3.76,4.513,3.715" transform="matrix(1, -0.017, 0.017, 1, 309.113, 136.796)" fill="none" stroke="#03040a" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"></path></g></svg>
</button>
</div>
<div class="main-header-info">
<nav aria-label="breadcrumb">
<div class="breadcrumb">
<li class="breadcrumb-item active" aria-current="page">{{ title }}</li>
{% if current_route == '/dashboard' or current_route == '/' %}
{% else %}
<li class="breadcrumb-break"></li>
{% if current_route.startswith('/databases') %}
<li class="breadcrumb-item smaller"><a href="/databases">MySQL</a></li>
{% elif current_route.startswith('/backups') or current_route.startswith('/inodes') or current_route.startswith('/disk') or current_route.startswith('files') or current_route.startswith('/ftp') or current_route.startswith('/malware-scanner') or current_route.startswith('/fix-permissions') %}
<li class="breadcrumb-item smaller"><a href="/files">Files</a></li>
{% elif current_route.startswith('/emails')%}
<li class="breadcrumb-item smaller"><a href="/emails">Emails</a></li>
{% elif current_route.startswith('/website') or current_route.startswith('/pm2') or current_route.startswith('/wordpress') or current_route.startswith('website') or current_route.startswith('/auto-installer') or current_route.startswith('auto-installer') %}
<li class="breadcrumb-item smaller"><a href="/sites">Applications</a></li>
{% elif current_route.startswith('/cache') or current_route.startswith('/search')%}
<li class="breadcrumb-item smaller"><a href="/">Cache & Search</a></li>
{% elif current_route.startswith('/php')%}
<li class="breadcrumb-item smaller"><a href="/php">PHP</a></li>
{% elif current_route.startswith('/domains/log/') or current_route.startswith('/activity') or current_route.startswith('/usage')%}
<li class="breadcrumb-item smaller"><a href="/">Analytics</a></li>
{% elif current_route.startswith('/domains') or current_route.startswith('/ssl')%}
<li class="breadcrumb-item smaller"><a href="/domains">Domains</a></li>
{% elif current_route.startswith('/cronjobs') or current_route.startswith('/ssh') or current_route.startswith('/terminal') or current_route.startswith('/process-manager')%}
<li class="breadcrumb-item smaller"><a href="/">Advanced</a></li>
{% elif current_route.startswith('/settings')%}
<li class="breadcrumb-item smaller"><a href="/account">Account</a></li>
{% elif current_route.startswith('/server')%}
<li class="breadcrumb-item smaller"><a href="/server/settings">Server</a></li>
{% endif %}
<i class="bi bi-chevron-compact-right"></i>
<li class="breadcrumb-item smaller active">
<a aria-current="page" href="{{ current_route }}">
{% if wp_name %}{{ wp_name }}
{% elif domain_name %}
{{ title }}</a> <i class="bi bi-chevron-compact-right"></i> {{ domain_name }}
{% elif domain %}
{{ title }}</a> <i class="bi bi-chevron-compact-right"></i> {{ domain }}
{% else %}
{{ title }}</a>
{% endif %}
</a></li>
{% endif %}
</div>
</nav>
</div>
<div class="main-header-nav">
{% if current_route.startswith('/files') or title == "j" %}
{% else %}
<script>
$(document).ready(function(){
$('#searchInput').on('input', function() {
var searchText = $(this).val().toLowerCase();
var dropdownItems = '';
$.when(
$.get('/core/search_filter'),
$.get('/core/search_websites')
).done(function(jsonData, websiteData) {
jsonData = jsonData[0];
websiteData = websiteData[0];
$.each(jsonData, function(index, item) {
var itemName = item.name || '';
var linkTarget = '';
if (itemName.toLowerCase().includes(searchText)) {
if (item.link.includes('/phpmyadmin')) {
linkTarget = 'target="_blank"'; // Open in a new tab
}
dropdownItems += '<li style="border-bottom: 1px solid #e2e5ec;"><h5><a class="dropdown-item" href="' + item.link + '" ' + linkTarget + '>' + item.name + '<br><p class="dropdown-item-description" style="font-size: 0.7em;margin-bottom: 0px;">' + item.description + '</p></a></h5></li>';
}
});
$.each(websiteData, function(index, item) {
var itemName = item[0] || ''; // Get the site name from the first element
var itemLink = '/sites'; // The link for all websites
if (itemName.toLowerCase().includes(searchText)) {
dropdownItems += '<li><h5><a class="dropdown-item" href="' + itemLink + '"><i class="bi bi-globe"></i> ' + itemName + '</a></h5></li>';
}
});
if (dropdownItems) {
$('#filteredDropdown').html(dropdownItems).show();
} else {
$('#filteredDropdown').html('').hide();
}
});
});
// Hide dropdown when clicking outside
$(document).on('click', function(event) {
if (!$(event.target).closest('#searchGroup').length) {
$('#filteredDropdown').hide();
}
});
});
</script>
{% endif %}
<div class="btn-group" aria-label="Navigation">
{% if 'favorites' in enabled_modules %}
<div class="project-favorite_item__wcDLn">
<span aria-hidden="true">
<div class="project-favorite_container__9W5Nt">
<button class="btn" id="addFavoriteBtn"><l-i class="bi bi-star" value="light" style="font-size: large;"></l-i>
<div class="project-favorite_sparklesContainer__K_v7d" data-toggle="tooltip" data-placement="bottom" title="{{ _('Left-click to add to Favorites') }}"> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 6px; --starting-position-y: 6px; --starting-scale: 0; --ending-position-x: 1px; --ending-position-y: 1px; --ending-scale: 1; --color: var(--ds-purple-700); --delay: 100ms; --duration: 150ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 13px; --starting-position-y: 6px; --starting-scale: 0; --ending-position-x: 16px; --ending-position-y: 0px; --ending-scale: 0.7; --color: var(--ds-amber-700); --delay: 50ms; --duration: 260ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 2px; --starting-position-y: 13px; --starting-scale: 0; --ending-position-x: 0px; --ending-position-y: 13px; --ending-scale: 0.5; --color: var(--ds-pink-700); --delay: 80ms; --duration: 200ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 9px; --starting-position-y: 15px; --starting-scale: 0; --ending-position-x: 9px; --ending-position-y: 18px; --ending-scale: 0.7; --color: var(--ds-teal-700); --delay: 120ms; --duration: 340ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 15px; --starting-position-y: 12px; --starting-scale: 0; --ending-position-x: 18px; --ending-position-y: 13px; --ending-scale: 0.5; --color: var(--ds-blue-700); --delay: 0ms; --duration: 180ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> </div>
</button>
</div>
</span>
</div>
<script>
var addFavoriteBtn = document.getElementById("addFavoriteBtn");
if (addFavoriteBtn) {
// RIGHT CLICK - Remove from favorites
addFavoriteBtn.addEventListener("contextmenu", function(event) {
// Prevent the default context menu from appearing
event.preventDefault();
// Check if the current page is already NOT a favorite
if (addFavoriteBtn.dataset.isFavorite === 'false') {
// Show a message that it's already in favorites
const toastMessage = "{{ _('This page is not in your favorites! Left-click to add it.') }}";
const toast = toaster({
body: toastMessage,
className: 'border-0 text-white bg-warning',
});
return; // prevent DELETE
}
var currentPagePathFull = new URL(window.location.href);
var currentPagePath = currentPagePathFull.pathname + currentPagePathFull.search + currentPagePathFull.hash;
// Prepare the data
var data = {
link: currentPagePath
};
let btnClass, toastMessage;
// Send the DELETE request to remove from favorites
fetch('/favorites', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
btnClass = 'success';
toastMessage = "{{ _('Successfully removed from favorites!') }}";
const toast = toaster({
body: toastMessage,
className: `border-0 text-white bg-${btnClass}`,
});
document.getElementById('addFavoriteBtn').innerHTML = `
<l-i class="bi bi-star" value="light" style="color:gray;font-size: large;"></l-i><div class="project-favorite_sparklesContainer__K_v7d"> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 6px; --starting-position-y: 6px; --starting-scale: 0; --ending-position-x: 1px; --ending-position-y: 1px; --ending-scale: 1; --color: var(--ds-purple-700); --delay: 100ms; --duration: 150ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 13px; --starting-position-y: 6px; --starting-scale: 0; --ending-position-x: 16px; --ending-position-y: 0px; --ending-scale: 0.7; --color: var(--ds-amber-700); --delay: 50ms; --duration: 260ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 2px; --starting-position-y: 13px; --starting-scale: 0; --ending-position-x: 0px; --ending-position-y: 13px; --ending-scale: 0.5; --color: var(--ds-pink-700); --delay: 80ms; --duration: 200ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 9px; --starting-position-y: 15px; --starting-scale: 0; --ending-position-x: 9px; --ending-position-y: 18px; --ending-scale: 0.7; --color: var(--ds-teal-700); --delay: 120ms; --duration: 340ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> <div class="project-favorite_sparkleContainer__qTghH" style=" --starting-position-x: 15px; --starting-position-y: 12px; --starting-scale: 0; --ending-position-x: 18px; --ending-position-y: 13px; --ending-scale: 0.5; --color: var(--ds-blue-700); --delay: 0ms; --duration: 180ms; " > <svg fill="none" height="6" viewBox="0 0 6 6" width="6" xmlns="http://www.w3.org/2000/svg"> <path d="M2.5 0.5V0H3.5V0.5C3.5 1.60457 4.39543 2.5 5.5 2.5H6V3V3.5H5.5C4.39543 3.5 3.5 4.39543 3.5 5.5V6H3H2.5V5.5C2.5 4.39543 1.60457 3.5 0.5 3.5H0V3V2.5H0.5C1.60457 2.5 2.5 1.60457 2.5 0.5Z" fill="currentColor" ></path> </svg> </div> </div>
`;
loadFavorites();
})
.catch((error) => {
console.error('Error:', error);
btnClass = 'danger';
toastMessage = "{{ _('Failed to remove favorite.') }}";
const toast = toaster({
body: toastMessage,
className: `border-0 text-white bg-${btnClass}`,
});
});
});
// LEFT CLICK - Add to favorites
addFavoriteBtn.addEventListener("click", function(event) {
// Check if the current page is already a favorite
if (addFavoriteBtn.dataset.isFavorite === 'true') {
// Show a message that it's already in favorites
const toastMessage = "{{ _('This page is already in your favorites! Right-click to remove it.') }}";
const toast = toaster({
body: toastMessage,
className: 'border-0 text-white bg-warning',
});
return; // prevent PUT
}
// Get the link
var currentPagePathFull = new URL(window.location.href);
var currentPagePath = currentPagePathFull.pathname + currentPagePathFull.search + currentPagePathFull.hash;
// Get the page title
var currentPageTitle = document.title;
if (currentPageTitle.includes(" - ")) {
currentPageTitle = currentPageTitle.split(" - ")[0];
}
// Prepare the data
var data = {
link: currentPagePath,
title: currentPageTitle
};
let btnClass, toastMessage;
// Send the PUT request using fetch API
fetch('/favorites', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
let btnClass;
let toastMessage;
if (data.error) {
// Error case
btnClass = 'danger'; // Red or other error color
toastMessage = data.error; // Use the error message from the response
} else {
// Success case
btnClass = 'success'; // Green or other success color
toastMessage = "{{ _('Successfully added to favorites!') }}";
// Update the button HTML to show the filled star icon
document.getElementById('addFavoriteBtn').innerHTML = `
<l-i class="bi bi-star-fill" value="light" style="color:orange;font-size: large;"></l-i>
`;
// Optionally load favorites if needed
loadFavorites();
}
// Show the toast message
const toast = toaster({
body: toastMessage,
className: `border-0 text-white bg-${btnClass}`,
});
})
.catch((error) => {
console.error('Error:', error);
btnClass = 'danger';
toastMessage = "{{ _('Failed to add favorite.') }}";
const toast = toaster({
body: toastMessage,
className: `border-0 text-white bg-${btnClass}`,
});
});
});
}
</script>
<style>
.nested-link-block_block__JdHXp.nested-link-block_block__JdHXp {
display: grid;
color: inherit;
cursor: pointer;
outline: none;
overflow: visible;
pointer-events: none;
text-decoration: none
}
.nested-link-block_block__JdHXp [role=button],.nested-link-block_block__JdHXp [role=link],.nested-link-block_block__JdHXp a,.nested-link-block_block__JdHXp button {
pointer-events: auto
}
.nested-link-block_block__JdHXp>* {
grid-area: 1/1;
min-width: 0
}
.project-favorite_item__wcDLn {
display: flex;
align-items: center;
justify-content: space-between
}
.project-favorite_item__wcDLn:focus-visible svg {
transform: translate(var(--ending-position-x),var(--ending-position-y)) scale(var(--ending-scale))!important;
transition: transform .1s ease-out 0
}
@media (hover: hover) {
.project-favorite_item__wcDLn:hover svg {
transform:translate(var(--ending-position-x),var(--ending-position-y)) scale(var(--ending-scale))!important;
transition: transform .1s ease-out 0
}
}
.project-favorite_container__9W5Nt {
position: relative
}
.project-favorite_container__9W5Nt .project-favorite_sparklesContainer__K_v7d {
height: 24px;
width: 24px;
display: block;
position: absolute;
top: 5px;
left: 8px;
}
.project-favorite_container__9W5Nt .project-favorite_sparkleContainer__qTghH {
position: absolute;
height: 6px;
width: 6px;
color: var(--color)
}
.project-favorite_container__9W5Nt .project-favorite_sparkleContainer__qTghH svg {
display: block;
transition: transform var(--duration,.2s) ease-out var(--delay);
transform: translate(var(--starting-position-x),var(--starting-position-y)) scale(var(--starting-scale))
}
.styles_gitInfo__SZNNj {
flex-grow: 1;
min-height: 4rem
}
.styles_projectCard__eGrlb {
display: block;
background: var(--ds-background-100);
border-radius: var(--geist-marketing-radius);
overflow: hidden;
min-height: 168px;
min-width: 300px;
box-shadow: var(--ds-shadow-border),0 4px 6px rgba(0,0,0,.04);
transition: box-shadow .15s ease,background .15s ease
}
@media (hover: hover) {
.styles_projectCardWrapper__vds4q:hover:not([data-placeholder]) .styles_projectCard__eGrlb {
box-shadow:var(--ds-shadow-border),0 6px 14px rgba(0,0,0,.08)
}
.dark-theme .styles_projectCardWrapper__vds4q:hover:not([data-placeholder]) .styles_projectCard__eGrlb {
background: var(--ds-gray-100)
}
}
.styles_projectCardDetails__Fm3po {
display: flex;
height: 100%;
padding: 20px 16px 20px 24px
}
.styles_minWidth0__gVCVc {
min-width: 0
}
.styles_maxWidth100__KxVhj {
max-width: 100%
}
.styles_branch__uOEEI {
max-width: calc(100% - 36px);
vertical-align: middle;
white-space: nowrap
}
.styles_projectCardWrapper__vds4q {
position: relative;
box-sizing: border-box
}
.styles_visitButton__RSHut {
position: absolute;
right: 0;
top: 0;
transform: translate(25%,-25%);
opacity: 0;
pointer-events: none;
transition: .15s ease;
transition-property: opacity,transform
}
@media (hover: hover) {
.styles_projectCardWrapper__vds4q:hover:not([data-placeholder]) .styles_visitButton__RSHut {
opacity:1;
pointer-events: unset;
transform: translate(25%,-35%)
}
}
@media (max-width: 600px) {
.styles_visitButton__RSHut {
display:none
}
}
.styles_stale__V3sb9>.styles_projectCard__eGrlb {
box-shadow: inset 0 4px 0 var(--geist-warning),var(--ds-shadow-border),0 4px 6px rgba(0,0,0,.04)
}
@media (hover: hover) {
.styles_projectCardWrapper__vds4q.styles_stale__V3sb9:hover:not([data-placeholder]) .styles_projectCard__eGrlb {
box-shadow:inset 0 4px 0 var(--geist-warning),var(--ds-shadow-border),0 6px 14px rgba(0,0,0,.08)
}
.dark-theme .styles_projectCardWrapper__vds4q.styles_stale__V3sb9:hover:not([data-placeholder]) .styles_projectCard__eGrlb {
box-shadow: inset 0 4px 0 var(--geist-warning),0 0 0 1px var(--geist-foreground)
}
}
/*# sourceMappingURL=bd4237834785bd8d.css.map*/
</style>
{% endif %}
<button class="btn js-darkmode-toggle" id="toggleDarkModeIcon">
<l-i class="bi bi-moon" hidden value="light" style="font-size: large;"></l-i>
<l-i class="bi bi-sun" hidden value="dark" style="color:orange;font-size: large;"></l-i>
</button>
<input type="text" class="form-control search-bar" id="searchInput" style="display: none;" placeholder="{{ _('Search') }}">
<ul class="dropdown-menu scroller" style="top: 100%; width: 100%; right: 0px; overflow-x: hidden; overflow-y: overlay; max-height: 90vh;" aria-labelledby="searchInput" id="filteredDropdown">
</ul>
<button class="btn" id="searchIcon" onclick="toggleSearchBar()">
<i class="bi bi-search" style="font-size: large;"></i>
</button>
</div>
</div>
</header>
{% endif %}
<section class="scroller">
<div class="container-fluid">
{% block content %}{% endblock %}
</div>
</section>
</div>
</main>
</sco-pe>
</div>
<!-- templates/partials/notifications.html -->
{% include 'partials/notifications.html' %}
<!-- templates/partials/_shortcuts.html -->
{% include 'partials/_shortcuts.html' %}
<script>
function toggleSearchBar() {
var searchBar = document.querySelector('.search-bar');
var searchIcon = document.getElementById('searchIcon');
var refreshbutton = document.getElementById('refresh-button');
var newFileButton = document.getElementById('newFileButton');
var favoritesButton = document.getElementById('addFavoriteBtn');
var newFolderButton = document.getElementById('newFolderButton');
var uploadButton = document.getElementById('uploadButton');
var searchInput = document.getElementById('searchInput');
var toggleDarkModeIcon = document.getElementById('toggleDarkModeIcon');
if (searchBar.style.display === 'none' || searchBar.style.display === '') {
// Show the search bar and change the icon to "x-lg"
searchBar.style.display = 'block';
searchIcon.innerHTML = '<i class="bi bi-x-lg" style="font-size: large;"></i>';
// Set focus on the input field
if (searchInput) {
searchInput.style.display = 'block'; // Make sure the input field is visible
searchInput.focus();
}
if (toggleDarkModeIcon) {
toggleDarkModeIcon.style.display = 'none';
}
if (favoritesButton) {
favoritesButton.style.display = 'none';
}
if (refreshbutton) {
refreshbutton.style.display = 'none';
newFileButton.style.display = 'none';
newFolderButton.style.display = 'none';
uploadButton.style.display = 'none';
}
} else {
// Hide the search bar and change the icon back to "search"
searchBar.style.display = 'none';
searchIcon.innerHTML = '<i class="bi bi-search" style="font-size: large;"></i>';
if (toggleDarkModeIcon) {
toggleDarkModeIcon.style.display = 'block';
}
if (favoritesButton) {
favoritesButton.style.display = 'block';
}
if (refreshbutton) {
refreshbutton.style.display = 'block';
newFileButton.style.display = 'block';
newFolderButton.style.display = 'block';
uploadButton.style.display = 'block';
}
}
}
</script>
</body>
<script>
$(document).ready(function() {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
{% block custom_footer %}
<!-- custom code in footer: https://dev.openpanel.com/customize.html#Code-in-Footer -->
{% include 'custom_code/in_footer.html' %}
{% endblock %}
{% if url_for('static', filename='js/custom.js') %}
<!-- custom js code: https://dev.openpanel.com/customize.html#Custom-JS -->
<script src="{{ url_for('static', filename='js/custom.js') }}"></script>
{% endif %}
</html>