Revert style for further dev

This commit is contained in:
MCHost
2025-07-06 12:13:20 -04:00
parent 1d3d02ee5f
commit 131aa1ecd9
6 changed files with 789 additions and 3546 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,423 +0,0 @@
@import "tailwindcss";
@font-face {
font-family: 'Minecraft';
src: url('../font/MinecraftRegular-Bmg3.otf') format('opentype');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@layer base {
html {
@apply h-full;
margin: 0;
padding: 0;
box-sizing: border-box;
overflow-x: hidden;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
@apply min-h-full flex flex-col bg-gray-900 text-white;
font-family: 'Roboto', 'Verdana', sans-serif;
overflow-x: hidden;
}
h1, h2, h3, h4, h5, h6 {
@apply font-[Minecraft] text-white;
letter-spacing: 0.5px;
}
#app {
@apply flex-grow;
}
main {
@apply flex-grow container mx-auto px-4 sm:px-6 lg:px-8 py-6;
}
footer {
@apply bg-gray-800 py-4 text-center;
}
canvas {
@apply w-full max-w-[150px] h-auto;
aspect-ratio: 1/1;
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
@apply bg-gray-800;
}
::-webkit-scrollbar-thumb {
@apply bg-blue-600 rounded;
}
::-webkit-scrollbar-thumb:hover {
@apply bg-blue-700;
}
}
@layer components {
.section-bg {
@apply bg-gray-800 p-6 rounded-lg shadow-lg mb-6 w-full max-w-full;
overflow-x: hidden;
}
.modal {
@apply fixed inset-0 bg-black/75 flex items-center justify-center z-[1000];
}
.modal-content {
@apply bg-gray-800 p-6 rounded-lg w-full max-w-xl relative max-h-[80vh] overflow-y-auto;
scrollbar-width: thin;
scrollbar-color: #4B5563 #1F2937;
}
@media (max-width: 640px) {
.holesail-output-mobile-hidden {
display: none;
}
}
.modal-content::-webkit-scrollbar {
@apply w-2;
}
.modal-content::-webkit-scrollbar-track {
@apply bg-gray-800;
}
.modal-content::-webkit-scrollbar-thumb {
@apply bg-gray-600 rounded;
}
.modal-content::-webkit-scrollbar-thumb:hover {
@apply bg-gray-500;
}
.modal-close {
@apply absolute top-2 right-2 bg-transparent border-none text-white text-xl cursor-pointer;
}
.control-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-medium px-4 py-2 rounded transition duration-200;
}
.spinner {
@apply border-4 border-gray-700 border-t-blue-600 rounded-full w-6 h-6 animate-spin inline-block;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
#notificationContainer {
@apply fixed bottom-4 right-4 z-[1000] flex flex-col-reverse gap-2;
}
.notification {
@apply bg-gray-800 p-3 rounded-lg text-white flex items-center gap-2 shadow-lg;
max-width: 90%;
font-size: 0.875rem;
}
.notification.success {
@apply bg-green-600;
}
.notification.error {
@apply bg-red-600;
}
#dockerLogsTerminal {
@apply bg-gray-900 p-4 rounded-lg w-full max-w-full box-border;
height: 250px; /* Increase height to make the section taller */
overflow-y: hidden; /* Remove vertical scrollbar */
overflow-x: hidden; /* Maintain no horizontal scrollbar */
}
.xterm .xterm-viewport {
@apply overflow-y-auto;
height: 250px; /* Increase height to make the section taller */
scrollbar-width: thin;
scrollbar-color: #3b82f6 #1f2937;
}
.xterm .xterm-viewport::-webkit-scrollbar {
width: 8px;
}
.xterm .xterm-viewport::-webkit-scrollbar-track {
@apply bg-gray-800;
}
.xterm .xterm-viewport::-webkit-scrollbar-thumb {
@apply bg-blue-600 rounded;
}
.xterm .xterm-viewport::-webkit-scrollbar-thumb:hover {
@apply bg-blue-700;
}
.xterm .xterm-screen {
@apply w-full;
}
.item-entry {
@apply flex items-center gap-2 mb-2 w-full flex-wrap;
}
.item-entry input {
@apply bg-gray-700 p-2 rounded text-white w-full sm:w-auto;
}
.item-entry .item-amount {
@apply w-16 sm:w-12;
}
[role="switch"] {
@apply inline-block relative w-10 h-6 cursor-pointer;
}
[role="switch"] > div:first-child {
@apply block w-full h-full rounded-full bg-gray-700 transition-colors duration-200;
}
[role="switch"] > div:last-child {
@apply absolute w-4 h-4 rounded-full bg-white top-1 transition-all duration-200;
}
[role="switch"][aria-checked="true"] > div:first-child {
@apply bg-blue-600;
}
[role="switch"][aria-checked="true"] > div:last-child {
@apply left-5;
}
[role="switch"][aria-checked="false"] > div:last-child {
@apply left-1;
}
#sftpIframe {
@apply w-full rounded;
height: 50vh;
min-height: 300px;
}
#propertiesSearch {
@apply bg-gray-700 p-2 rounded text-white w-full;
}
#propertiesList {
@apply space-y-2;
}
}
.nav-btn {
@apply bg-blue-600 hover:bg-blue-700 text-white font-medium px-4 py-2 rounded transition duration-200;
}
.hamburger {
@apply md:hidden flex flex-col justify-center items-center w-10 h-10 fixed top-4 right-4 z-[99999];
}
.hamburger .bar {
@apply w-6 h-0.5 bg-blue-400 mb-1.5 transition-all duration-300;
}
.hamburger.active .bar:nth-child(1) {
@apply translate-y-2 rotate-45;
}
.hamburger.active .bar:nth-child(2) {
@apply opacity-0;
}
.hamburger.active .bar:nth-child(3) {
@apply -translate-y-2 -rotate-45;
}
.mobile-nav-container {
@apply hidden fixed inset-0 flex-col items-center justify-center bg-gray-900 z-[99998] p-4;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.mobile-nav-container.active {
@apply flex opacity-100 visible;
}
.mobile-nav-container ul li a,
.mobile-nav-container ul li button {
@apply block px-4 py-2 rounded text-lg text-white bg-blue-600 hover:bg-blue-700 mb-4;
}
@media (max-width: 768px) {
.section-bg {
@apply p-4;
}
.modal-content {
@apply p-4 max-w-[95%];
}
.section-bg .grid {
@apply grid-cols-1;
}
.section-bg .flex {
@apply flex-col gap-2;
}
canvas {
@apply max-w-[120px];
}
.section-bg input,
.section-bg textarea,
.section-bg select {
@apply p-2 text-sm;
}
.section-bg pre {
@apply text-sm;
}
#sftpIframe {
@apply h-[40vh] min-h-[300px];
}
#consoleOutput {
@apply h-32 text-sm;
}
.notification {
@apply text-sm p-2 max-w-[80%];
}
h1 { @apply text-3xl; }
h2 { @apply text-xl; }
h3 { @apply text-base; }
p, span, a { @apply text-sm; }
.nav-btn {
@apply hidden;
}
.hamburger {
@apply flex;
}
.control-btn {
@apply px-3 py-1 text-sm;
}
.item-entry {
@apply flex-col gap-1;
}
.item-entry .item-amount {
@apply w-full;
}
}
@media (max-width: 640px) {
.section-bg {
@apply p-3;
}
.modal-content {
@apply p-3 max-w-[95%];
}
canvas {
@apply max-w-[100px];
}
.section-bg input,
.section-bg textarea,
.section-bg select {
@apply p-1 text-xs;
}
.section-bg pre {
@apply text-xs;
}
#sftpIframe {
@apply h-[35vh] min-h-[250px];
}
#consoleOutput {
@apply h-28 text-xs;
}
.notification {
@apply text-xs p-1 max-w-[90%];
}
h1 { @apply text-2xl; }
h2 { @apply text-lg; }
h3 { @apply text-sm; }
p, span, a { @apply text-xs; }
.control-btn {
@apply px-2 py-1 text-xs;
}
}
@media (max-width: 480px) {
.section-bg {
@apply p-2;
}
.modal-content {
@apply p-2 max-w-[98%];
}
canvas {
@apply max-w-[80px];
}
.section-bg input,
.section-bg textarea,
.section-bg select {
@apply p-1 text-xs;
}
.section-bg pre {
@apply text-xs;
}
#sftpIframe {
@apply h-[30vh] min-h-[200px];
}
#consoleOutput {
@apply h-24 text-xs;
}
.notification {
@apply text-xs p-1 max-w-[95%];
}
h1 { @apply text-xl; }
h2 { @apply text-base; }
h3 { @apply text-xs; }
p, span, a { @apply text-xs; }
.control-btn {
@apply px-2 py-1 text-xs;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,100 +6,29 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Permissions-Policy" content="clipboard-write=(self https://sftp.my-mc.link)"> <meta http-equiv="Permissions-Policy" content="clipboard-write=(self https://sftp.my-mc.link)">
<title>My-MC Panel</title> <title>My-MC Panel</title>
<link rel="stylesheet" href="css/styles.min.css"> <link rel="stylesheet" href="/css/styles.min.css?p=1">
<link rel="stylesheet" href="css/main-site.css"> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700;900&display=swap" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" rel="stylesheet" /> <link href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" rel="stylesheet" />
<link rel="icon" href="https://minecraft.wiki/images/Favicon.png" type="image/png">
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
<link rel="manifest" href="/favicon/site.webmanifest"> <link rel="manifest" href="/favicon/site.webmanifest">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js"></script>
</head> </head>
<body class="min-h-full flex flex-col"> <body class="bg-gray-900 text-white overflow-x-hidden min-h-full flex flex-col">
<!-- Hamburger Menu Icon (visible on mobile) -->
<button class="hamburger md:hidden flex flex-col justify-center items-center w-10 h-10 focus:outline-none"
style="z-index: 99999; position: fixed; top: 1rem; right: 1rem; pointer-events: auto;">
<span class="bar w-6 h-0.5 bg-teal-400 mb-1.5 transition-all duration-300"></span>
<span class="bar w-6 h-0.5 bg-teal-400 mb-1.5 transition-all duration-300"></span>
<span class="bar w-6 h-0.5 bg-teal-400 transition-all duration-300"></span>
</button>
<!-- Mobile Navigation Menu -->
<nav class="mobile-nav mobile-nav-container hidden fixed inset-0 flex-col items-center justify-center md:hidden"
data-mobile-nav style="z-index: 99998; position: fixed; inset: 0; pointer-events: auto;">
<ul class="text-center">
<li class="mb-6">
<a href="https://my-mc.link"
class="text-lg minecraft-font text-white bg-gradient-to-r from-teal-400 to-blue-500 px-4 py-2 rounded-md hover:bg-gradient-to-r hover:from-blue-500 hover:to-teal-400">Home</a>
</li>
<li class="mb-6">
<a href="https://stats.my-mc.link"
class="text-lg minecraft-font text-white bg-gradient-to-r from-teal-400 to-blue-500 px-4 py-2 rounded-md hover:bg-gradient-to-r hover:from-blue-500 hover:to-teal-400">System
Stats</a>
</li>
<li class="mb-6">
<button id="mobileRefresh"
class="text-lg minecraft-font text-white bg-gradient-to-r from-teal-400 to-blue-500 px-4 py-2 rounded-md hover:bg-gradient-to-r hover:from-blue-500 hover:to-teal-400">Refresh</button>
</li>
<li class="mb-6">
<button id="mobileBackupBtn"
class="text-lg minecraft-font text-white bg-gradient-to-r from-teal-400 to-blue-500 px-4 py-2 rounded-md hover:bg-gradient-to-r hover:from-blue-500 hover:to-teal-400">Backup</button>
</li>
<li class="mb-6">
<a href="https://info.my-mc.link"
class="text-lg minecraft-font text-white bg-gradient-to-r from-teal-400 to-blue-500 px-4 py-2 rounded-md hover:bg-gradient-to-r hover:from-blue-500 hover:to-teal-400"
target="_blank">Wiki</a>
</li>
<li class="mb-6">
<button id="mobileLogoutBtn"
class="text-lg minecraft-font text-white bg-gradient-to-r from-teal-400 to-blue-500 px-4 py-2 rounded-md hover:bg-gradient-to-r hover:from-blue-500 hover:to-teal-400">Logout</button>
</li>
</ul>
</nav>
<!-- Particle Effects -->
<div class="particle"></div>
<div class="particle large"></div>
<div class="particle"></div>
<div class="particle large"></div>
<div class="particle"></div>
<header class="header-bg py-16 text-center relative z-2">
<div class="header-content flex items-center justify-between max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div>
<h1
class="text-5xl minecraft-font bg-clip-text text-transparent bg-gradient-to-r from-teal-400 to-blue-500">
My-MC Panel</h1>
<p class="text-lg mt-4 opacity-90 tracking-wide font-medium">Manage Your Minecraft Server</p>
</div>
<!-- Navigation Buttons (hidden on mobile) -->
<nav class="flex items-center gap-2 hidden md:flex">
<a href="https://my-mc.link" class="nav-btn">Home</a>
<a href="https://stats.my-mc.link" class="nav-btn" target="_blank">System Stats</a>
<button id="refresh" class="nav-btn">Refresh</button>
<button id="backupBtn" class="nav-btn">Backup</button>
<a href="https://info.my-mc.link" class="nav-btn" target="_blank">Wiki</a>
<button id="logoutBtn" class="nav-btn">Logout</button>
</nav>
</div>
</header>
<div id="app" class="flex-grow"> <div id="app" class="flex-grow">
<!-- Login Page and Modals --> <!-- Login Page and Modals (unchanged) -->
<div id="loginPage" class="modal hidden"> <div id="loginPage" class="hidden fixed inset-0 bg-gray-900 flex items-center justify-center">
<div class="modal-content"> <div class="bg-gray-800 p-8 rounded-lg shadow-lg w-full max-w-md">
<button class="modal-close">×</button> <h2 class="text-2xl font-bold mb-6 text-center">My-MC Panel</h2>
<h2 class="text-2xl minecraft-font mb-6 text-center">My-MC Panel Login</h2>
<div class="mb-4"> <div class="mb-4">
<input id="loginApiKey" type="text" placeholder="Enter API Key" <input id="loginApiKey" type="text" placeholder="Enter API Key"
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white w-full border border-[rgba(255,255,255,0.15)]"> class="bg-gray-700 px-4 py-2 rounded text-white w-full">
</div> </div>
<button id="loginBtn" class="btn-minecraft w-full">Login</button> <button id="loginBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Login</button>
<p id="loginError" class="text-red-500 text-sm mt-2 hidden"></p> <p id="loginError" class="text-red-500 text-sm mt-2 hidden"></p>
</div> </div>
</div> </div>
@@ -109,11 +38,11 @@
<div id="tellModal" class="modal hidden"> <div id="tellModal" class="modal hidden">
<div class="modal-content"> <div class="modal-content">
<button class="modal-close">×</button> <button class="modal-close">×</button>
<h2 class="text-xl minecraft-font mb-4">Send Message to <span id="tellPlayerName"></span></h2> <h2 class="text-xl font-semibold mb-4">Send Message to <span id="tellPlayerName"></span></h2>
<form id="tellForm"> <form id="tellForm">
<textarea id="tellMessage" placeholder="Enter your message" <textarea id="tellMessage" placeholder="Enter your message"
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white w-full h-24 mb-4 border border-[rgba(255,255,255,0.15)]"></textarea> class="bg-gray-700 px-4 py-2 rounded text-white w-full h-24 mb-4"></textarea>
<button type="submit" class="btn-minecraft w-full">Send</button> <button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Send</button>
</form> </form>
</div> </div>
</div> </div>
@@ -121,12 +50,11 @@
<div id="giveModal" class="modal hidden"> <div id="giveModal" class="modal hidden">
<div class="modal-content"> <div class="modal-content">
<button class="modal-close">×</button> <button class="modal-close">×</button>
<h2 class="text-xl minecraft-font mb-4">Give Items to <span id="givePlayerName"></span></h2> <h2 class="text-xl font-semibold mb-4">Give Items to <span id="givePlayerName"></span></h2>
<form id="giveForm"> <form id="giveForm">
<div class="mb-4"> <div class="mb-4">
<label for="loadoutSelect" class="block text-sm font-medium mb-1">Select Loadout</label> <label for="loadoutSelect" class="block text-sm font-medium mb-1">Select Loadout</label>
<select id="loadoutSelect" <select id="loadoutSelect" class="bg-gray-700 px-4 py-2 rounded text-white w-full">
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white w-full border border-[rgba(255,255,255,0.15)]">
<option value="custom">Custom</option> <option value="custom">Custom</option>
<option value="starter">Starter Kit (Torches, Food)</option> <option value="starter">Starter Kit (Torches, Food)</option>
<option value="builder">Builder Kit (Stone, Wood)</option> <option value="builder">Builder Kit (Stone, Wood)</option>
@@ -142,9 +70,10 @@
</div> </div>
<div id="customGiveFields" class="hidden mb-4"> <div id="customGiveFields" class="hidden mb-4">
<div id="itemList" class="space-y-2"></div> <div id="itemList" class="space-y-2"></div>
<button type="button" id="addItemBtn" class="btn-minecraft mt-2">Add Item</button> <button type="button" id="addItemBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded mt-2">Add
Item</button>
</div> </div>
<button type="submit" class="btn-minecraft w-full">Give</button> <button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Give</button>
</form> </form>
</div> </div>
</div> </div>
@@ -152,17 +81,15 @@
<div id="teleportModal" class="modal hidden"> <div id="teleportModal" class="modal hidden">
<div class="modal-content"> <div class="modal-content">
<button class="modal-close">×</button> <button class="modal-close">×</button>
<h2 class="text-xl minecraft-font mb-4">Teleport <span id="teleportPlayerName"></span></h2> <h2 class="text-xl font-semibold mb-4">Teleport <span id="teleportPlayerName"></span></h2>
<form id="teleportForm"> <form id="teleportForm">
<div class="mb-4"> <div class="mb-4">
<label for="teleportDestination" class="block text-sm font-medium mb-1">Select Destination <label for="teleportDestination" class="block text-sm font-medium mb-1">Select Destination Player</label>
Player</label> <select id="teleportDestination" class="bg-gray-700 px-4 py-2 rounded text-white w-full">
<select id="teleportDestination"
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white w-full border border-[rgba(255,255,255,0.15)]">
<!-- Options populated dynamically --> <!-- Options populated dynamically -->
</select> </select>
</div> </div>
<button type="submit" class="btn-minecraft w-full">Teleport</button> <button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Teleport</button>
</form> </form>
</div> </div>
</div> </div>
@@ -170,12 +97,11 @@
<div id="effectModal" class="modal hidden"> <div id="effectModal" class="modal hidden">
<div class="modal-content"> <div class="modal-content">
<button class="modal-close">×</button> <button class="modal-close">×</button>
<h2 class="text-xl minecraft-font mb-4">Apply Effect to <span id="effectPlayerName"></span></h2> <h2 class="text-xl font-semibold mb-4">Apply Effect to <span id="effectPlayerName"></span></h2>
<form id="effectForm"> <form id="effectForm">
<div class="mb-4"> <div class="mb-4">
<label for="effectSelect" class="block text-sm font-medium mb-1">Select Effect</label> <label for="effectSelect" class="block text-sm font-medium mb-1">Select Effect</label>
<select id="effectSelect" <select id="effectSelect" class="bg-gray-700 px-4 py-2 rounded text-white w-full">
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white w-full border border-[rgba(255,255,255,0.15)]">
<option value="speed:30:1">Speed (30s, Level 1)</option> <option value="speed:30:1">Speed (30s, Level 1)</option>
<option value="strength:30:1">Strength (30s, Level 1)</option> <option value="strength:30:1">Strength (30s, Level 1)</option>
<option value="regeneration:30:1">Regeneration (30s, Level 1)</option> <option value="regeneration:30:1">Regeneration (30s, Level 1)</option>
@@ -186,7 +112,7 @@
<option value="water_breathing:60:1">Water Breathing (60s, Level 1)</option> <option value="water_breathing:60:1">Water Breathing (60s, Level 1)</option>
</select> </select>
</div> </div>
<button type="submit" class="btn-minecraft w-full">Apply Effect</button> <button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Apply Effect</button>
</form> </form>
</div> </div>
</div> </div>
@@ -194,204 +120,220 @@
<div id="editPropertiesModal" class="modal hidden"> <div id="editPropertiesModal" class="modal hidden">
<div class="modal-content"> <div class="modal-content">
<button class="modal-close">×</button> <button class="modal-close">×</button>
<h2 class="text-xl minecraft-font mb-4">Edit server.properties</h2> <h2 class="text-xl font-semibold mb-4">Edit server.properties</h2>
<form id="editPropertiesForm" class="space-y-4"> <form id="editPropertiesForm" class="space-y-4">
<div id="propertiesFields" class="space-y-2"></div> <div id="propertiesFields" class="space-y-2"></div>
<button type="submit" class="btn-minecraft w-full">Save</button> <button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Save</button>
</form> </form>
</div> </div>
</div> </div>
<div id="updateModsModal" class="modal hidden"> <div id="updateModsModal"
<div class="modal-content flex flex-col"> class="modal hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-2 sm:p-4">
<div class="flex justify-between items-center p-4 border-b border-[rgba(255,255,255,0.12)]"> <div
<h2 class="text-xl minecraft-font">Mod Update Output</h2> class="modal-content bg-gray-900 rounded-lg max-w-[95%] w-full sm:w-[90%] md:w-[85%] lg:w-[80%] mx-auto flex flex-col max-h-[95vh]">
<button class="modal-close text-2xl">×</button> <div class="flex justify-between items-center p-4 border-b">
<h2 class="text-xl font-semibold text-white">Mod Update Output</h2>
<button class="modal-close text-2xl font-bold text-white">×</button>
</div> </div>
<pre id="updateModsOutput" <pre id="updateModsOutput"
class="flex-1 p-4 text-[#e0e7ff] text-sm max-h-[calc(95vh-10rem)] overflow-y-auto overflow-x-auto whitespace-pre-wrap break-words leading-relaxed"></pre> class="flex-1 p-4 text-white text-sm max-h-[calc(95vh-10rem)] overflow-y-auto overflow-x-auto whitespace-pre-wrap break-words leading-relaxed"></pre>
<div class="p-4 border-t border-[rgba(255,255,255,0.12)]"> <div class="p-4 border-t">
<button id="closeUpdateModsBtn" class="btn-minecraft w-full">Close</button> <button id="closeUpdateModsBtn"
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded w-full">Close</button>
</div> </div>
</div> </div>
</div> </div>
<!-- Main Content --> <!-- Navigation (unchanged) -->
<main id="mainContent" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-16 relative z-2"> <nav class="bg-gray-800 p-4 shadow-lg">
<div class="section-bg p-6 sm:p-8 mb-8" data-section="server-status"> <div class="container mx-auto flex justify-between items-center">
<div class="flex flex-col space-y-2 mb-4"> <h1 class="text-2xl font-bold">My-MC Panel</h1>
<div class="flex justify-between items-center"> <div class="flex space-x-4">
<h2 class="text-3xl minecraft-font">Server Status</h2> <button id="refresh" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded">Refresh</button>
<div class="flex space-x-2"> <button id="backupBtn" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded">Backup</button>
<button id="startBtn" class="control-btn">Start</button> <div id="authControls">
<button id="stopBtn" class="control-btn">Stop</button> <input id="apiKey" type="text" placeholder="Enter API Key" class="bg-gray-700 px-4 py-2 rounded text-white">
<button id="restartBtn" class="control-btn">Restart</button>
</div> </div>
</div> </div>
<div class="flex justify-end space-x-2">
<button id="editPropertiesBtn" class="control-btn">Edit Server Properties</button>
<button id="updateModsBtn" class="control-btn">Update Mods</button>
</div> </div>
</div> </nav>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="flex flex-col space-y-1"> <!-- Main Content (unchanged except for Holesail Keys section) -->
<main id="mainContent" class="container mx-auto p-6">
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6" data-section="server-status">
<h2 class="text-xl font-semibold mb-4">Server Status</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<p><strong>User:</strong> <span id="user">Loading...</span></p> <p><strong>User:</strong> <span id="user">Loading...</span></p>
<p><strong>Key Expiry:</strong> <span id="keyExpiry">Loading...</span></p> <p><strong>Key Expiry:</strong> <span id="keyExpiry">Loading...</span></p>
<p><strong>Status:</strong> <span id="serverStatus">Loading...</span></p> <p><strong>Status:</strong> <span id="serverStatus">Loading...</span></p>
</div> </div>
<div class="flex space-x-4 justify-center items-start"> <div class="flex space-x-4 justify-center">
<div class="text-center"> <div class="text-center">
<canvas id="memoryMeter" width="120" height="120"></canvas> <canvas id="memoryMeter" width="150" height="150"></canvas>
<p class="text-sm mt-1"><b>Memory Usage</b></p> <p class="text-sm mt-2"><b>Memory Usage</b></p>
<p id="memoryPercent" class="text-lg font-bold">0%</p> <p id="memoryPercent" class="text-lg font-bold">0%</p>
</div> </div>
<div class="text-center"> <div class="text-center">
<canvas id="cpuMeter" width="120" height="120"></canvas> <canvas id="cpuMeter" width="150" height="150"></canvas>
<p class="text-sm mt-1"><b>CPU Usage</b></p> <p class="text-sm mt-2"><b>CPU Usage</b></p>
<p id="cpuPercent" class="text-lg font-bold">0%</p> <p id="cpuPercent" class="text-lg font-bold">0%</p>
</div> </div>
</div> </div>
<div class="flex flex-wrap space-x-2 justify-end items-center">
<div class="flex space-x-2">
<button id="startBtn"
class="bg-green-600 hover:bg-green-700 rounded font-medium control-btn">Start</button>
<button id="stopBtn" class="bg-red-600 hover:bg-red-700 rounded font-medium control-btn">Stop</button>
<button id="restartBtn"
class="bg-yellow-600 hover:bg-yellow-700 rounded font-medium control-btn">Restart</button>
</div>
<button id="editPropertiesBtn"
class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded control-btn w-full mt-2">Edit Server
Properties</button>
<button id="updateModsBtn"
class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded control-btn w-full mt-2">Update Mods</button>
</div>
</div> </div>
</div> </div>
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
<div class="section-bg mb-12"> <h2 class="text-xl font-semibold mb-4">Player Management</h2>
<h2 class="text-3xl minecraft-font mb-8">Player Management</h2> <div class="mb-4"></div>
<p><strong>Connected Players:</strong><br> <span id="playerList">Loading...</span></p> <p><strong>Connected Players:</strong><br> <span id="playerList">Loading...</span></p>
</div> </div>
<div class="section-bg mb-12"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
<h2 class="text-3xl minecraft-font mb-8">Server Logs</h2> <h2 class="text-xl font-semibold mb-4">Server Logs</h2>
<div id="dockerLogsTerminal" class="mt-4"></div> <div id="dockerLogsTerminal" class="mt-4"></div>
</div> </div>
<div class="section-bg mb-12"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
<h2 class="text-3xl minecraft-font mb-8">Server Console</h2> <h2 class="text-xl font-semibold mb-4">Server Console</h2>
<form id="consoleForm" onsubmit="event.preventDefault(); sendConsoleCommand();"> <form id="consoleForm" onsubmit="event.preventDefault(); sendConsoleCommand();">
<input id="consoleInput" type="text" placeholder="Enter RCON Command (Hit Enter To Submit)" <input id="consoleInput" type="text" placeholder="Enter RCON Command (Hit Enter To Submit)"
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white w-full mb-2 border border-[rgba(255,255,255,0.15)]"> class="bg-gray-700 px-4 py-2 rounded text-white w-full mb-2">
<button id="sendConsole" type="submit" class="btn-minecraft" style="display: none;">Send</button> <button id="sendConsole" type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded"
style="display: none;">Send</button>
</form> </form>
<pre id="consoleOutput" <pre id="consoleOutput" class="bg-gray-900 p-4 rounded mt-4 h-48 overflow-y-auto"></pre>
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-4 rounded mt-4 h-48 overflow-y-auto border border-[rgba(255,255,255,0.15)]"></pre>
</div> </div>
<div class="section-bg mb-12" id="sftpBrowserSection" style="display: none;"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6" id="sftpBrowserSection" style="display: none;">
<div class="flex justify-between items-baseline mb-4"> <div class="flex justify-between items-baseline mb-4">
<h2 class="text-3xl minecraft-font">SFTP Browser</h2> <h2 class="text-xl font-semibold">SFTP Browser</h2>
<button id="sftpBtn" class="control-btn text-sm flex items-center space-x-1"> <button id="sftpBtn" class="px-3 py-1 rounded text-sm flex items-center space-x-1"
<i class="fas fa-sync-alt"></i> style="background-color: #121724; color: #ffffff;">
<i class="fas fa-sync-alt" style="color: #121724;"></i>
<span>Refresh SFTP</span> <span>Refresh SFTP</span>
</button> </button>
</div> </div>
<iframe id="sftpIframe" class="w-full rounded" allow="clipboard-read; clipboard-write"></iframe> <iframe id="sftpIframe" class="w-full rounded" style="height: 650px; min-height: 650px;"
allow="clipboard-read; clipboard-write"></iframe>
</div> </div>
<div class="section-bg mb-12"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
<h2 class="text-3xl minecraft-font mb-8">Mod Management</h2> <h2 class="text-xl font-semibold mb-4">Mod Management</h2>
<form id="modSearchForm" onsubmit="event.preventDefault(); searchMods(1);"> <form id="modSearchForm" onsubmit="event.preventDefault(); searchMods(1);">
<div class="mb-4 flex space-x-2"> <div class="mb-4 flex space-x-2">
<input id="modSearch" type="text" placeholder="Search Mods (Hit Enter To Submit)" <input id="modSearch" type="text" placeholder="Search Mods (Hit Enter To Submit)"
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white flex-grow border border-[rgba(255,255,255,0.15)]"> class="bg-gray-700 px-4 py-2 rounded text-white flex-grow">
<button id="searchBtn" type="submit" class="btn-minecraft" <button id="searchBtn" type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded"
style="display: none;">Search</button> style="display: none;">Search</button>
<button id="closeSearchBtn" type="button" class="btn-minecraft hidden">Close</button> <button id="closeSearchBtn" type="button"
class="bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded hidden">Close</button>
</div> </div>
</form> </form>
<div id="modResults" class="grid grid-cols-1 md:grid-cols-2 gap-6"></div> <div id="modResults" class="grid grid-cols-1 md:grid-cols-2 gap-4"></div>
<div id="pagination" class="mt-4 flex justify-center space-x-2"></div> <div id="pagination" class="mt-4 flex justify-center space-x-2"></div>
<h3 class="text-xl minecraft-font mt-4">Installed Mods</h3> <h3 class="text-lg font-semibold mt-4">Installed Mods</h3>
<div class="mb-4 flex space-x-2"> <div class="mb-4 flex space-x-2">
<input id="modListSearch" type="text" placeholder="Search Installed Mods" <input id="modListSearch" type="text" placeholder="Search Installed Mods"
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-4 py-2 rounded text-white flex-grow border border-[rgba(255,255,255,0.15)]"> class="bg-gray-700 px-4 py-2 rounded text-white flex-grow">
<button id="clearModListSearch" type="button" class="btn-minecraft hidden">Clear</button> <button id="clearModListSearch" type="button"
class="bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded hidden">Clear</button>
</div> </div>
<div id="modList" class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-6"></div> <div id="modList" class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-4"></div>
<div id="modListPagination" class="mt-4 flex justify-center space-x-2"></div> <div id="modListPagination" class="mt-4 flex justify-center space-x-2"></div>
</div> </div>
<div class="section-bg mb-12 p-8 rounded-lg"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
<h2 class="text-3xl minecraft-font mb-10 font-bold text-white">Server Links</h2> <h2 class="text-xl font-semibold mb-4">Server Links</h2>
<div class="flex flex-wrap gap-6 mb-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Connection Link Card --> <p><strong>Advanced Log URL:</strong> <a id="logUrl" href="#" class="text-blue-400"
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow flex-1 min-w-[250px]"> target="_blank">Loading...</a></p>
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">Connection Link</h3> <p><strong>Website URL:</strong> <a id="websiteUrl" href="#" class="text-blue-400"
<p class="text-gray-300 mb-4 break-all"> target="_blank">Loading...</a></p>
<span id="myLink" class="text-blue-400">Link Not Created</span> <p><strong>BlueMap URL:</strong> <a id="mapUrl" href="#" class="text-blue-400" target="_blank">Loading...</a>
<span id="connectionStatus" class="text-sm"></span>
</p> </p>
<button id="generateMyLinkBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md transition-colors"> <div>
Generate Connection Link <p><strong>Connection Link:</strong> <span id="myLink">Link Not Created</span> <span
</button> id="connectionStatus"></span></p>
<button id="generateMyLinkBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-1 rounded mt-2">Generate
Connection Link</button>
</div> </div>
<div>
<!-- Geyser Link Card --> <p><strong>Geyser Link:</strong> <span id="geyserLink">Link Not Created</span> <span
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow flex-1 min-w-[250px]"> id="geyserStatus"></span></p>
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">Geyser Link</h3> <button id="generateGeyserLinkBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-1 rounded mt-2">Generate
<p class="text-gray-300 mb-4 break-all"> Geyser Link</button>
<span id="geyserLink" class="text-blue-400">Link Not Created</span>
<span id="geyserStatus" class="text-sm"></span>
</p>
<button id="generateGeyserLinkBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md transition-colors">
Generate Geyser Link
</button>
</div> </div>
<div>
<!-- SFTP Link Card --> <p><strong>SFTP Link:</strong> <span id="sftpLink">Link Not Created</span> <span id="sftpStatus"></span></p>
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow flex-1 min-w-[250px]"> <button id="generateSftpLinkBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-1 rounded mt-2">Generate SFTP
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">SFTP Link</h3> Link</button>
<p class="text-gray-300 mb-4 break-all">
<span id="sftpLink" class="text-blue-400">Link Not Created</span>
<span id="sftpStatus" class="text-sm"></span>
</p>
<button id="generateSftpLinkBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md transition-colors">
Generate SFTP Link
</button>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Advanced Log URL Card -->
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow">
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">Advanced Log</h3>
<p class="text-gray-300 mb-4 break-all">
<a id="logUrl" href="#" class="text-blue-400 hover:underline" target="_blank">Loading...</a>
</p>
</div>
<!-- Website URL Card -->
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow">
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">Website</h3>
<p class="text-gray-300 mb-4 break-all">
<a id="websiteUrl" href="#" class="text-blue-400 hover:underline" target="_blank">Loading...</a>
</p>
</div>
<!-- BlueMap URL Card -->
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow">
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">BlueMap</h3>
<p class="text-gray-300 mb-4 break-all">
<a id="mapUrl" href="#" class="text-blue-400 hover:underline" target="_blank">Loading...</a>
</p>
</div> </div>
</div> </div>
</div> </div>
<!-- Holesail Keys Section --> <!-- Updated Holesail Keys Section -->
<div class="section-bg mb-12"> <div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
<div class="flex items-center justify-between mb-4 flex-wrap"> <div class="flex items-center justify-between mb-4">
<h2 class="text-3xl minecraft-font">Holesail Keys</h2> <h2 class="text-xl font-semibold text-white">Holesail Keys</h2>
<button id="toggleTutorial" <button id="toggleTutorial"
class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-md transition duration-200 md:mt-0 mt-2">Tutorial</button> class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-md transition duration-200">Tutorial</button>
</div> </div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6"> <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div class="flex items-center p-4"> <div class="flex items-center bg-gray-700 p-3 rounded-md">
<div class="flex-grow"> <div class="flex-grow">
<p><strong>Minecraft Key:</strong></p> <p class="text-gray-300"><strong>Minecraft Key:</strong></p>
<p class="break-all" id="holesailHash">Not Loaded</p> <p class="text-gray-100 break-all" id="holesailHash">Not Loaded</p>
<p class="text-sm">Port: 127.0.0.1:25565</p> <p class="text-sm text-gray-400">Port: 127.0.0.1:25565</p>
</div> </div>
<button class="copy-key-btn ml-2" data-key-id="holesailHash" data-key-type="Minecraft" <button class="copy-key-btn ml-2 text-gray-300 hover:text-white" data-key-id="holesailHash"
data-key-type="Minecraft" title="Copy">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">
</path>
</svg>
</button>
</div>
<div class="flex items-center bg-gray-700 p-3 rounded-md">
<div class="flex-grow">
<p class="text-gray-300"><strong>Geyser Key:</strong></p>
<p class="text-gray-100 break-all" id="geyserHash">Not Loaded</p>
<p class="text-sm text-gray-400">Port: 127.0.0.1:19132</p>
</div>
<button class="copy-key-btn ml-2 text-gray-300 hover:text-white" data-key-id="geyserHash"
data-key-type="Geyser" title="Copy">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">
</path>
</svg>
</button>
</div>
<div class="flex items-center bg-gray-700 p-3 rounded-md">
<div class="flex-grow">
<p class="text-gray-300"><strong>SFTP Key:</strong></p>
<p class="text-gray-100 break-all" id="sftpHash">Not Loaded</p>
<p class="text-sm text-gray-400">Port: 127.0.0.1:22</p>
</div>
<button class="copy-key-btn ml-2 text-gray-300 hover:text-white" data-key-id="sftpHash" data-key-type="SFTP"
title="Copy"> title="Copy">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
@@ -401,108 +343,73 @@
</svg> </svg>
</button> </button>
</div> </div>
<div class=" flex items-center p-4">
<div class="flex-grow">
<p><strong>Geyser Key:</strong></p>
<p class="break-all" id="geyserHash">Not Loaded</p>
<p class="text-sm">Port: 127.0.0.1:19132</p>
</div>
<button class="copy-key-btn ml-2" data-key-id="geyserHash" data-key-type="Geyser" title="Copy">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">
</path>
</svg>
</button>
</div>
<div class="flex items-center p-4">
<div class="flex-grow">
<p><strong>SFTP Key:</strong></p>
<p class="break-all" id="sftpHash">Not Loaded</p>
<p class="text-sm">Port: 127.0.0.1:22</p>
</div>
<button class="copy-key-btn ml-2" data-key-id="sftpHash" data-key-type="SFTP" title="Copy">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">
</path>
</svg>
</button>
</div>
</div> </div>
<div id="tutorialSection" class="hidden"> <div id="tutorialSection" class="hidden">
<div class="feature-card tilt-card p-6 mb-6"> <div class="bg-gray-700 p-6 rounded-xl mb-6 border border-gray-600">
<h3 class="text-xl minecraft-font mb-4">What is Holesail.io?</h3> <h3 class="text-xl font-bold mb-4 text-white border-b border-gray-500 pb-2">What is Holesail.io?</h3>
<p class="text-base leading-relaxed mb-4"> <p class="text-gray-200 text-base leading-relaxed mb-4">
<a href="https://holesail.io" target="_blank" <a href="https://holesail.io" target="_blank"
class="text-teal-400 hover:text-blue-400">Holesail.io</a> is an open-source, class="text-blue-400 hover:underline font-medium">Holesail.io</a> is an open-source, peer-to-peer
peer-to-peer networking tool that creates secure, encrypted tunnels that bypass network networking tool that creates secure, encrypted tunnels that bypass network restrictions, firewalls, and
restrictions, firewalls, and NAT. It exposes your local network to the internet without NAT.<BR>It exposes your local network to the internet without needing port forwarding, static IPs, or
needing port forwarding, static IPs, or Dynamic DNS, acting as a versatile tunneling and Dynamic DNS, acting as a versatile tunneling and reverse proxy solution.
reverse proxy solution.
</p> </p>
<div class="mb-4"> <div class="mb-4">
<p class="font-semibold mb-2">With Holesail, you can:</p> <p class="text-gray-200 font-semibold mb-2">With Holesail, you can:</p>
<ul class="list-disc pl-6 space-y-1 text-base"> <ul class="list-disc pl-6 space-y-1 text-gray-200 text-base">
<li>Access machines over the internet securely.</li> <li>Access machines over the internet securely.</li>
<li>Share locally running servers, websites, or AI models with other ports/services. <li>Share locally running servers, websites, or AI models with other ports/services.</li>
</li>
<li>Transfer files and folders remotely without bandwidth or size limits.</li> <li>Transfer files and folders remotely without bandwidth or size limits.</li>
<li>Play LAN games like Minecraft with friends remotely.</li> <li>Play LAN games like Minecraft with friends remotely.</li>
<li>Secure SSH servers by blocking IP access and using Holesail for connections.</li> <li>Secure SSH servers by blocking IP access and using Holesail for connections.</li>
<li>Built for ANY application, Holesail supports both the TCP and UDP Protocols <li>Built for ANY application, Holesail supports both the TCP and UDP Protocols nativly.</li>
natively.</li> <li>Expose single ports to the peer-to-peer network, unlike VPNs you never expose your entire local
<li>Expose single ports to the peer-to-peer network, unlike VPNs you never expose your network.</li>
entire local network.</li> <BR>And so much more! With Holesail, the possiblities are endless!
</ul> </ul>
</div> </div>
<p class="text-base leading-relaxed"> <p class="text-gray-200 text-base leading-relaxed">
Built with security in mind, Holesail ensures all data is encrypted and never touches Built with security in mind, Holesail ensures all data is encrypted and never touches third-party
third-party servers. Connections are truly peer-to-peer, accessible only to those with whom servers.<BR>Connections are truly peer-to-peer, accessible only to those with whom you share your private
you share your private key, providing both ease of use and robust security. Other peers key, providing both ease of use and robust security.<BR>Other peers cannot detect your activity or
cannot detect your activity or services. As an open-source tool, Holesail enables services.<BR>As an open-source tool, Holesail enables third-party services to integrate it, enhancing
third-party services to integrate it, enhancing their security and connectivity. their security and connectivity.
</p> </p>
<p class="text-base leading-relaxed mt-4"> <p class="text-gray-200 text-base leading-relaxed">
Your Public My-MC Ports are Holesail connections hosted on a separate server, not our <BR>Your Public My-MC Ports are Holesail connections hosted on a separate server, not our Minecraft
Minecraft host. They use the same keys from the tutorial below. We hook 'em up at our jump host.<BR>They use the same keys from the tutorial below. We hook 'em up at our jump host to go public.
host to go public. Pretty dope, right?
</p> </p>
</div> </div>
<div class="feature-card tilt-card p-6 mb-6"> <div class="bg-gray-700 p-4 rounded-md mb-6">
<h3 class="text-xl minecraft-font mb-4">How to Use Holesail Keys</h3> <h3 class="text-lg font-semibold mb-3 text-white">How to Use Holesail Keys</h3>
<ol class="list-decimal list-inside space-y-2"> <ol class="list-decimal list-inside space-y-2 text-gray-300">
<li>Ensure <a href="https://nodejs.org/" target="_blank" <li>Ensure <a href="https://nodejs.org/" target="_blank" class="text-blue-400 hover:underline">Node.js</a>
class="text-teal-400 hover:text-blue-400">Node.js</a> is installed on your system. is installed on your system.</li>
</li>
<li>Install Holesail by running: <li>Install Holesail by running:
<pre <pre class="bg-gray-800 p-2 rounded mt-1 text-sm">npm i holesail@2.1.0</pre>
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-2 rounded mt-1 text-sm border border-[rgba(255,255,255,0.15)]">npm i holesail@2.1.0</pre>
</li> </li>
<li>Connect to a key using the appropriate command: <li>Connect to a key using the appropriate command:
<ul class="list-disc list-inside ml-4 mt-1"> <ul class="list-disc list-inside ml-4 mt-1">
<li>For Minecraft Key (e.g., Minecraft server): <li>For Minecraft Key (e.g., Minecraft server):
<pre <pre
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-2 rounded mt-1 text-sm border border-[rgba(255,255,255,0.15)]">holesail <span id="tutorialHolesailHash">Not Loaded</span></pre> class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialHolesailHash">Not Loaded</span></pre>
</li> </li>
<li>For Geyser key (e.g., cross-platform Minecraft): <li>For Geyser key (e.g., cross-platform Minecraft):
<pre <pre
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-2 rounded mt-1 text-sm border border-[rgba(255,255,255,0.15)]">holesail <span id="tutorialGeyserHash">Not Loaded</span></pre> class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialGeyserHash">Not Loaded</span></pre>
</li> </li>
<li>For SFTP key (e.g., file transfer): <li>For SFTP key (e.g., file transfer):
<pre <pre
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-2 rounded mt-1 text-sm border border-[rgba(255,255,255,0.15)]">holesail <span id="tutorialSftpHash">Not Loaded</span></pre> class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialSftpHash">Not Loaded</span></pre>
</li> </li>
</ul> </ul>
</li> </li>
<li class="holesail-output-mobile-hidden">Holesail will confirm the connection. Example <li class="holesail-output-mobile-hidden">Holesail will confirm the connection. Example output for your
output for your Minecraft server: Minecraft server:
<pre <pre class="bg-gray-800 p-2 rounded mt-1 text-sm">
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-2 rounded mt-1 text-sm border border-[rgba(255,255,255,0.15)]">
~ holesail <span id="tutorialHolesailHashOutput">Not Loaded</span> ~ holesail <span id="tutorialHolesailHashOutput">Not Loaded</span>
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
| | | |
@@ -518,48 +425,49 @@
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
</pre> </pre>
</li> </li>
<li>Now you can connect to your own localhost within Minecraft!<br>Connect to: <BR>Now you can connect to your own localhost within Minecraft!<BR><BR>Connect to:
<code <code class="bg-gray-800 px-1 rounded">127.0.0.1:25565</code><BR><BR>
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-1 rounded border border-[rgba(255,255,255,0.15)]">127.0.0.1:25565</code><br><br>
</li>
<li>To share the port over your internet IP as an open port, add the <code <li>To share the port over your internet IP as an open port, add the <code
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] px-1 rounded border border-[rgba(255,255,255,0.15)]">--host 0.0.0.0</code> class="bg-gray-800 px-1 rounded">--host 0.0.0.0</code> switch:
switch:
<pre <pre
class="bg-[rgba(10,17,40,0.3)] backdrop-blur-[12px] p-2 rounded mt-1 text-sm border border-[rgba(255,255,255,0.15)]">holesail <span id="tutorialHolesailHashHost">Not Loaded</span> --host 0.0.0.0</pre> class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialHolesailHashHost">Not Loaded</span> --host 0.0.0.0</pre><BR>
<br>Note: Using the --host 0.0.0.0 method will require you open your port within your Note: Using the --host 0.0.0.0 method will require you open your port within your router in order to serve the port from your IP Address remotely.
router in order to serve the port from your IP Address remotely.
</li> </li>
</ol> </ol>
</div> </div>
<div class="feature-card tilt-card p-6"> <div class="bg-gray-700 p-4 rounded-md">
<h3 class="text-xl minecraft-font mb-4">Share with Friends</h3> <h3 class="text-lg font-semibold mb-3 text-white">Share with Friends</h3>
<p class="mb-3"> <p class="text-gray-300 mb-3">
Share this tutorial with your friends so they can connect to your Minecraft server or other Share this tutorial with your friends so they can connect to your Minecraft server or other services on
services on their own localhosts! With Holesail, no public IPs are needed! Everything stays their own localhosts!<BR>With Holesail, no public IPs are needed! Everything stays secure and
secure and peer-to-peer! peer-to-peer!
</p> </p>
<button id="copyTutorial" class="btn-minecraft">Copy Tutorial</button> <button id="copyTutorial"
class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-md transition duration-200">Copy
Tutorial</button>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
<footer class="bg-[rgba(10,17,40,0.75)] backdrop-filter backdrop-blur-xl py-8 text-center relative z-2"> <footer class="bg-gray-800 py-4">
<p class="text-sm opacity-90">© 2025 My-MC.Link. All rights reserved.</p> <div class="container mx-auto px-6 text-center">
<p class="text-sm opacity-90 mt-3"> <p class="text-gray-400 text-sm">
Powered by <a href="https://holesail.io" class="underline text-teal-400 hover:text-blue-400" © 2025 My-MC.Link. All rights reserved.<br>
target="_blank">Holesail</a> with services <a href="https://raven-scott.fyi" target="_blank" class="text-blue-400 hover:text-blue-500">Made with ❤️ by
donated by <a href="https://raven-scott.fyi" SNXRaven</a> | <a href="https://git.ssh.surf/hypermc/panel" target="_blank"
class="underline text-teal-400 hover:text-blue-400">SNXRaven</a> | class="text-blue-400 hover:text-blue-500">Source Code</a>
<a href="https://git.ssh.surf/hypermc/panel" class="underline text-teal-400 hover:text-blue-400"
target="_blank">Source Code</a>
</p> </p>
</div>
</footer> </footer>
</div>
<script src="js/app_test.js"></script> <script src="js/app.js"></script>
<script src="js/tutorial.js"></script> <script src="js/tutorial.js"></script>
</body> </body>
</html> </html>

View File

@@ -28,137 +28,6 @@ document.addEventListener('DOMContentLoaded', () => {
'enable-status' 'enable-status'
]; ];
const sections = document.querySelectorAll('.section-bg');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
entry.target.style.transform = 'translateY(0)';
entry.target.style.opacity = '1';
entry.target.style.transitionDelay = `${index * 0.1}s`;
}
});
}, { threshold: 0.1 });
// sections.forEach(section => {
// section.style.transform = 'translateY(30px)';
// section.style.opacity = '0';
// section.style.transition = 'transform 0.7s ease-out, opacity 0.7s ease-out';
// observer.observe(section);
// });
// const PARTICLE_POOL_SIZE = 50;
// const particlePool = [];
// const activeParticles = new Set();
// function createParticleElement() {
// const particle = document.createElement('div');
// particle.classList.add('particle');
// if (Math.random() > 0.6) particle.classList.add('large');
// return particle;
// }
// function initializeParticlePool() {
// for (let i = 0; i < PARTICLE_POOL_SIZE; i++) {
// particlePool.push(createParticleElement());
// }
// }
// function resetParticle(particle) {
// particle.style.left = `${Math.random() * 100}%`;
// particle.style.top = `${Math.random() * 100}%`;
// particle.style.animationDelay = `${Math.random() * 8}s`;
// particle.style.animationDuration = `${8 + Math.random() * 6}s`;
// particle.classList.remove('fade-out');
// return particle;
// }
// function spawnParticle() {
// if (particlePool.length === 0 || activeParticles.size >= PARTICLE_POOL_SIZE) return;
// const particle = resetParticle(particlePool.pop());
// if (!particle.parentNode) document.body.appendChild(particle);
// activeParticles.add(particle);
// setTimeout(() => {
// particle.classList.add('fade-out');
// setTimeout(() => {
// activeParticles.delete(particle);
// particlePool.push(particle);
// }, 500);
// }, 14000);
// }
// function animate() {
// if (Math.random() < 0.1) spawnParticle(); // Reduced spawn frequency
// requestAnimationFrame(animate);
// }
// // Initialize and start
// setTimeout(() => {
// initializeParticlePool();
// animate();
// }, 500);
function throttle(fn, wait) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= wait) {
fn.apply(this, args);
lastTime = now;
}
};
}
// const buttons = document.querySelectorAll('.btn-minecraft');
// buttons.forEach(button => {
// button.addEventListener('mousemove', (e) => {
// const rect = button.getBoundingClientRect();
// const x = e.clientX - rect.left;
// const y = e.clientY - rect.top;
// button.style.setProperty('--x', `${x}px`);
// button.style.setProperty('--y', `${y}px`);
// });
// });
// Hamburger Menu Toggle
const hamburger = document.querySelector('.hamburger');
const mobileNav = document.querySelector('[data-mobile-nav]');
const navLinks = mobileNav.querySelectorAll('a');
// Debounce function to prevent rapid clicks
function debounce(fn, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => fn.apply(this, args), wait);
};
}
hamburger.addEventListener('click', debounce(() => {
console.log('Hamburger clicked, toggling menu');
mobileNav.classList.toggle('active');
hamburger.classList.toggle('active');
}, 100));
navLinks.forEach(link => {
link.addEventListener('click', () => {
console.log('Nav link clicked, closing menu');
mobileNav.classList.remove('active');
hamburger.classList.remove('active');
});
});
document.addEventListener('click', (e) => {
if (!mobileNav.contains(e.target) && !hamburger.contains(e.target) && mobileNav.classList.contains('active')) {
console.log('Clicked outside, closing menu');
mobileNav.classList.remove('active');
hamburger.classList.remove('active');
}
});
const elements = { const elements = {
loginPage: document.getElementById('loginPage'), loginPage: document.getElementById('loginPage'),
loginApiKey: document.getElementById('loginApiKey'), loginApiKey: document.getElementById('loginApiKey'),
@@ -452,7 +321,7 @@ document.addEventListener('DOMContentLoaded', () => {
terminal.clear(); terminal.clear();
} else { } else {
terminal = new Terminal({ terminal = new Terminal({
rows: 22, rows: 8,
fontSize: 14, fontSize: 14,
fontFamily: 'monospace', fontFamily: 'monospace',
theme: { theme: {
@@ -1169,7 +1038,9 @@ document.addEventListener('DOMContentLoaded', () => {
} }
elements.loginPage.classList.remove('hidden'); elements.loginPage.classList.remove('hidden');
elements.mainContent.classList.add('hidden'); elements.mainContent.classList.add('hidden');
elements.authControls.innerHTML = '<input id="apiKey" type="text" placeholder="Enter API Key" class="bg-gray-700 px-4 py-2 rounded text-white">';
elements.apiKeyInput = document.getElementById('apiKey'); elements.apiKeyInput = document.getElementById('apiKey');
elements.apiKeyInput.addEventListener('change', handleApiKeyChange);
if (ws) { if (ws) {
ws.close(); ws.close();
ws = null; ws = null;
@@ -1198,35 +1069,13 @@ document.addEventListener('DOMContentLoaded', () => {
} }
elements.loginPage.classList.add('hidden'); elements.loginPage.classList.add('hidden');
elements.mainContent.classList.remove('hidden'); elements.mainContent.classList.remove('hidden');
// Verify buttons exist elements.authControls.innerHTML = '<button id="logoutBtn" class="bg-red-600 hover:bg-red-700 px-4 py-2 rounded">Logout</button>';
const logoutBtn = document.getElementById('logoutBtn'); const logoutBtn = document.getElementById('logoutBtn');
const mobileLogoutBtn = document.getElementById('mobileLogoutBtn');
if (logoutBtn) { if (logoutBtn) {
console.log('Desktop logout button found'); logoutBtn.addEventListener('click', handleLogout);
} else { } else {
console.error('Desktop logout button (#logoutBtn) not found'); console.error('Logout button not found after insertion');
} }
if (mobileLogoutBtn) {
console.log('Mobile logout button found');
} else {
console.error('Mobile logout button (#mobileLogoutBtn) not found');
}
// Remove any existing logout listeners to prevent duplicates
document.removeEventListener('click', handleLogoutClick);
// Event delegation for logout buttons
function handleLogoutClick(event) {
if (event.target.id === 'logoutBtn' || event.target.id === 'mobileLogoutBtn') {
console.log(`Logout button clicked: ${event.target.id}`);
handleLogout();
}
}
document.addEventListener('click', handleLogoutClick);
initializeCharts(); initializeCharts();
initializeTerminal(); initializeTerminal();
} }
@@ -1246,18 +1095,6 @@ document.addEventListener('DOMContentLoaded', () => {
showLoginPage(); showLoginPage();
} }
async function handleRefresh() {
if (ws && ws.readyState === WebSocket.OPEN) {
const key = `action-refresh`;
const notification = showNotification('Refreshing server data...', 'loading', key);
ws.send(JSON.stringify({ type: 'refresh' }));
initializeTerminal();
setTimeout(() => updateNotification(notification, 'Server data refreshed successfully', 'success', key), 1000);
} else {
showNotification('Not connected to server. Please log in.', 'error', 'ws-disconnected');
}
}
function updatePagination() { function updatePagination() {
const totalPages = Math.max(1, Math.ceil(totalResults / resultsPerPage)); const totalPages = Math.max(1, Math.ceil(totalResults / resultsPerPage));
elements.pagination.innerHTML = ''; elements.pagination.innerHTML = '';
@@ -1850,6 +1687,7 @@ document.addEventListener('DOMContentLoaded', () => {
switchContainer.className = 'relative inline-block'; switchContainer.className = 'relative inline-block';
switchContainer.setAttribute('role', 'switch'); switchContainer.setAttribute('role', 'switch');
switchContainer.setAttribute('aria-checked', value.toLowerCase()); switchContainer.setAttribute('aria-checked', value.toLowerCase());
switchContainer.setAttribute('tabindex', '0');
switchContainer.dataset.name = key; switchContainer.dataset.name = key;
switchContainer.style.width = '40px'; switchContainer.style.width = '40px';
switchContainer.style.height = '24px'; switchContainer.style.height = '24px';
@@ -2080,7 +1918,7 @@ document.addEventListener('DOMContentLoaded', () => {
} }
}); });
// elements.apiKeyInput.addEventListener('change', handleApiKeyChange); elements.apiKeyInput.addEventListener('change', handleApiKeyChange);
elements.generateMyLinkBtn.addEventListener('click', async () => { elements.generateMyLinkBtn.addEventListener('click', async () => {
try { try {
@@ -2227,8 +2065,6 @@ document.addEventListener('DOMContentLoaded', () => {
} }
}); });
elements.updateModsBtn.addEventListener('click', updateMods); elements.updateModsBtn.addEventListener('click', updateMods);
elements.closeUpdateModsBtn.addEventListener('click', () => { elements.closeUpdateModsBtn.addEventListener('click', () => {
@@ -2341,42 +2177,4 @@ document.addEventListener('DOMContentLoaded', () => {
showLoginPage(); showLoginPage();
} }
window.showNotification = showNotification; window.showNotification = showNotification;
// Add this at the end of the document.addEventListener('DOMContentLoaded', ...) block
function applyResponsiveStyles() {
const sections = document.querySelectorAll('.section-bg');
sections.forEach(section => {
section.style.padding = window.innerWidth <= 640 ? '1rem' : window.innerWidth <= 768 ? '1.5rem' : '2rem';
section.style.maxWidth = '100%';
section.style.overflowX = 'hidden';
});
const iframes = document.querySelectorAll('#sftpIframe');
iframes.forEach(iframe => {
iframe.style.height = window.innerWidth <= 640 ? '300px' : window.innerWidth <= 768 ? '400px' : '650px';
iframe.style.minHeight = iframe.style.height;
iframe.style.width = '100%';
iframe.style.maxWidth = '100%';
});
const canvases = document.querySelectorAll('#memoryMeter, #cpuMeter');
canvases.forEach(canvas => {
canvas.style.width = window.innerWidth <= 640 ? '80px' : window.innerWidth <= 768 ? '100px' : '150px';
canvas.style.height = canvas.style.width;
});
const terminals = document.querySelectorAll('#dockerLogsTerminal');
terminals.forEach(terminal => {
terminal.style.maxHeight = window.innerWidth <= 640 ? '7rem' : window.innerWidth <= 768 ? '8rem' : '12rem';
});
const consoles = document.querySelectorAll('#consoleOutput');
consoles.forEach(console => {
console.style.height = window.innerWidth <= 640 ? '7rem' : window.innerWidth <= 768 ? '8rem' : '12rem';
});
}
window.addEventListener('resize', applyResponsiveStyles);
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 980 KiB

After

Width:  |  Height:  |  Size: 642 KiB