Move panel to website theme
This commit is contained in:
1492
public/css/main-site.css
Normal file
1492
public/css/main-site.css
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Minecraft';
|
||||
src: url('../font/MinecraftRegular-Bmg3.otf') format('opentype');
|
||||
@ -5,148 +7,69 @@
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.holesail-output-mobile-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@import "tailwindcss";
|
||||
|
||||
@layer base {
|
||||
/* Sticky footer base styles */
|
||||
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;
|
||||
@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 {
|
||||
font-family: 'Minecraft', sans-serif;
|
||||
@apply font-[Minecraft] text-white;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
#app {
|
||||
@apply flex-1 flex flex-col;
|
||||
}
|
||||
|
||||
main {
|
||||
@apply flex-grow;
|
||||
}
|
||||
|
||||
main {
|
||||
@apply flex-grow container mx-auto px-4 sm:px-6 lg:px-8 py-6;
|
||||
}
|
||||
|
||||
footer {
|
||||
@apply flex-shrink-0;
|
||||
@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 {
|
||||
.spinner {
|
||||
@apply border-4 border-gray-700 border-t-white rounded-full w-6 h-6 animate-spin inline-block;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
#notificationContainer {
|
||||
@apply fixed bottom-5 right-5 z-[1000] flex flex-col-reverse gap-2;
|
||||
}
|
||||
|
||||
.notification {
|
||||
@apply bg-gray-800 text-white p-4 rounded-lg flex items-center gap-3 shadow-lg transition-opacity duration-300;
|
||||
}
|
||||
|
||||
.notification.success {
|
||||
@apply bg-green-700;
|
||||
}
|
||||
|
||||
.notification.error {
|
||||
@apply bg-red-700;
|
||||
}
|
||||
|
||||
#dockerLogsTerminal {
|
||||
@apply bg-gray-800 p-4 rounded-lg max-h-48 w-full;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport {
|
||||
@apply overflow-y-auto;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #4B5563 #1F2937;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport::-webkit-scrollbar {
|
||||
@apply w-2;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport::-webkit-scrollbar-track {
|
||||
@apply bg-gray-800;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport::-webkit-scrollbar-thumb {
|
||||
@apply bg-gray-600 rounded;
|
||||
}
|
||||
|
||||
.xterm .xterm-viewport::-webkit-scrollbar-thumb:hover {
|
||||
@apply bg-gray-500;
|
||||
}
|
||||
|
||||
.xterm .xterm-screen {
|
||||
@apply w-full;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
@apply px-4 py-2 text-sm font-medium transition-all duration-200 min-w-[80px] text-center shadow-sm;
|
||||
}
|
||||
|
||||
.control-btn:hover:not(.disabled-btn) {
|
||||
@apply -translate-y-px;
|
||||
}
|
||||
|
||||
.control-btn:active:not(.disabled-btn) {
|
||||
@apply translate-y-0;
|
||||
}
|
||||
|
||||
/* Player button styles */
|
||||
.tell-player {
|
||||
@apply bg-blue-600 hover:bg-blue-700 px-2 py-1 rounded text-sm font-[Minecraft] transition-all duration-200;
|
||||
}
|
||||
|
||||
.give-player {
|
||||
@apply bg-green-600 hover:bg-green-700 px-2 py-1 rounded text-sm font-[Minecraft] transition-all duration-200;
|
||||
}
|
||||
|
||||
.op-player, .deop-player {
|
||||
@apply bg-purple-600 hover:bg-purple-700 px-2 py-1 rounded text-sm font-[Minecraft] transition-all duration-200;
|
||||
}
|
||||
|
||||
.kick-player, .ban-player {
|
||||
@apply bg-red-600 hover:bg-red-700 px-2 py-1 rounded text-sm font-[Minecraft] transition-all duration-200;
|
||||
}
|
||||
|
||||
.teleport-player {
|
||||
@apply bg-cyan-600 hover:bg-cyan-700 px-2 py-1 rounded text-sm font-[Minecraft] transition-all duration-200;
|
||||
}
|
||||
|
||||
.teleport-player:hover:not(.disabled-btn) {
|
||||
@apply -translate-y-px;
|
||||
}
|
||||
|
||||
.teleport-player:active:not(.disabled-btn) {
|
||||
@apply translate-y-0;
|
||||
}
|
||||
|
||||
.effect-player {
|
||||
@apply bg-teal-600 hover:bg-teal-700 px-2 py-1 rounded text-sm font-[Minecraft] transition-all duration-200;
|
||||
}
|
||||
|
||||
.effect-player:hover:not(.disabled-btn) {
|
||||
@apply -translate-y-px;
|
||||
}
|
||||
|
||||
.effect-player:active:not(.disabled-btn) {
|
||||
@apply translate-y-0;
|
||||
.section-bg {
|
||||
@apply bg-gray-800 p-6 rounded-lg shadow-lg mb-6 w-full max-w-full;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.modal {
|
||||
@ -159,6 +82,13 @@
|
||||
scrollbar-color: #4B5563 #1F2937;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.holesail-output-mobile-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.modal-content::-webkit-scrollbar {
|
||||
@apply w-2;
|
||||
}
|
||||
@ -179,97 +109,315 @@
|
||||
@apply absolute top-2 right-2 bg-transparent border-none text-white text-xl cursor-pointer;
|
||||
}
|
||||
|
||||
.disabled-btn {
|
||||
@apply opacity-50 cursor-not-allowed pointer-events-none;
|
||||
.control-btn {
|
||||
@apply bg-blue-600 hover:bg-blue-700 text-white font-medium px-4 py-2 rounded transition duration-200;
|
||||
}
|
||||
|
||||
.disabled-btn:hover {
|
||||
@apply cursor-not-allowed;
|
||||
.spinner {
|
||||
@apply border-4 border-gray-700 border-t-blue-600 rounded-full w-6 h-6 animate-spin inline-block;
|
||||
}
|
||||
|
||||
/* Search box and properties fields */
|
||||
#searchContainer {
|
||||
@apply mb-4 block;
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
#propertiesSearch {
|
||||
@apply bg-gray-700 px-4 py-2 rounded text-white w-full block;
|
||||
#notificationContainer {
|
||||
@apply fixed bottom-4 right-4 z-[1000] flex flex-col-reverse gap-2;
|
||||
}
|
||||
|
||||
#propertiesList {
|
||||
@apply space-y-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;
|
||||
}
|
||||
|
||||
/* Toggle switch styles */
|
||||
[role="switch"] {
|
||||
@apply inline-block relative w-10 h-6 cursor-pointer z-10;
|
||||
}
|
||||
|
||||
[role="switch"] > div:first-child {
|
||||
@apply w-full h-full rounded-full transition-colors duration-200 ease-in-out;
|
||||
}
|
||||
|
||||
[role="switch"] > div:last-child {
|
||||
@apply absolute w-4 h-4 rounded-full bg-white top-1 transition-all duration-200 ease-in-out z-[11];
|
||||
}
|
||||
|
||||
[role="switch"][aria-checked="true"] > div:first-child {
|
||||
.notification.success {
|
||||
@apply bg-green-600;
|
||||
}
|
||||
|
||||
[role="switch"][aria-checked="false"] > div:first-child {
|
||||
@apply bg-gray-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-6;
|
||||
@apply left-5;
|
||||
}
|
||||
|
||||
[role="switch"][aria-checked="false"] > div:last-child {
|
||||
@apply left-1;
|
||||
}
|
||||
|
||||
#sftpIframe {
|
||||
@apply w-full rounded;
|
||||
height: 50vh;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
/* Custom utilities */
|
||||
#propertiesSearch {
|
||||
@apply bg-gray-700 p-2 rounded text-white w-full;
|
||||
}
|
||||
|
||||
/* Media queries */
|
||||
@media (max-width: 640px) {
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg .grid {
|
||||
#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;
|
||||
}
|
||||
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg p {
|
||||
@apply flex flex-col gap-2 break-all;
|
||||
.section-bg .flex {
|
||||
@apply flex-col gap-2;
|
||||
}
|
||||
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg a,
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg span {
|
||||
@apply break-words whitespace-normal;
|
||||
canvas {
|
||||
@apply max-w-[120px];
|
||||
}
|
||||
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg button {
|
||||
@apply w-full mt-2;
|
||||
.section-bg input,
|
||||
.section-bg textarea,
|
||||
.section-bg select {
|
||||
@apply p-2 text-sm;
|
||||
}
|
||||
|
||||
.tell-player,
|
||||
.give-player,
|
||||
.teleport-player,
|
||||
.effect-player,
|
||||
.op-player,
|
||||
.deop-player,
|
||||
.kick-player,
|
||||
.ban-player {
|
||||
@apply w-full text-center mt-1;
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional styles */
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg .grid {
|
||||
@apply overflow-x-hidden;
|
||||
@media (max-width: 640px) {
|
||||
.section-bg {
|
||||
@apply p-3;
|
||||
}
|
||||
|
||||
.bg-gray-800.p-6.rounded-lg.shadow-lg p {
|
||||
@apply max-w-full;
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
|
1122
public/css/styles.min.css
vendored
1122
public/css/styles.min.css
vendored
File diff suppressed because it is too large
Load Diff
@ -6,29 +6,100 @@
|
||||
<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)">
|
||||
<title>My-MC Panel</title>
|
||||
<link rel="stylesheet" href="/css/styles.min.css?p=1">
|
||||
<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>
|
||||
<link rel="stylesheet" href="css/styles.min.css">
|
||||
<link rel="stylesheet" href="css/main-site.css">
|
||||
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700;900&display=swap" rel="stylesheet">
|
||||
<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 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="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="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>
|
||||
|
||||
<body class="bg-gray-900 text-white overflow-x-hidden min-h-full flex flex-col">
|
||||
<body class="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">
|
||||
<!-- Login Page and Modals (unchanged) -->
|
||||
<div id="loginPage" class="hidden fixed inset-0 bg-gray-900 flex items-center justify-center">
|
||||
<div class="bg-gray-800 p-8 rounded-lg shadow-lg w-full max-w-md">
|
||||
<h2 class="text-2xl font-bold mb-6 text-center">My-MC Panel</h2>
|
||||
<!-- Login Page and Modals -->
|
||||
<div id="loginPage" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2 class="text-2xl minecraft-font mb-6 text-center">My-MC Panel Login</h2>
|
||||
<div class="mb-4">
|
||||
<input id="loginApiKey" type="text" placeholder="Enter API Key"
|
||||
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)]">
|
||||
</div>
|
||||
<button id="loginBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Login</button>
|
||||
<button id="loginBtn" class="btn-minecraft w-full">Login</button>
|
||||
<p id="loginError" class="text-red-500 text-sm mt-2 hidden"></p>
|
||||
</div>
|
||||
</div>
|
||||
@ -38,11 +109,11 @@
|
||||
<div id="tellModal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2 class="text-xl font-semibold mb-4">Send Message to <span id="tellPlayerName"></span></h2>
|
||||
<h2 class="text-xl minecraft-font mb-4">Send Message to <span id="tellPlayerName"></span></h2>
|
||||
<form id="tellForm">
|
||||
<textarea id="tellMessage" placeholder="Enter your message"
|
||||
class="bg-gray-700 px-4 py-2 rounded text-white w-full h-24 mb-4"></textarea>
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Send</button>
|
||||
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>
|
||||
<button type="submit" class="btn-minecraft w-full">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -50,11 +121,12 @@
|
||||
<div id="giveModal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2 class="text-xl font-semibold mb-4">Give Items to <span id="givePlayerName"></span></h2>
|
||||
<h2 class="text-xl minecraft-font mb-4">Give Items to <span id="givePlayerName"></span></h2>
|
||||
<form id="giveForm">
|
||||
<div class="mb-4">
|
||||
<label for="loadoutSelect" class="block text-sm font-medium mb-1">Select Loadout</label>
|
||||
<select id="loadoutSelect" class="bg-gray-700 px-4 py-2 rounded text-white w-full">
|
||||
<select id="loadoutSelect"
|
||||
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="starter">Starter Kit (Torches, Food)</option>
|
||||
<option value="builder">Builder Kit (Stone, Wood)</option>
|
||||
@ -70,10 +142,9 @@
|
||||
</div>
|
||||
<div id="customGiveFields" class="hidden mb-4">
|
||||
<div id="itemList" class="space-y-2"></div>
|
||||
<button type="button" id="addItemBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded mt-2">Add
|
||||
Item</button>
|
||||
<button type="button" id="addItemBtn" class="btn-minecraft mt-2">Add Item</button>
|
||||
</div>
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Give</button>
|
||||
<button type="submit" class="btn-minecraft w-full">Give</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -81,15 +152,17 @@
|
||||
<div id="teleportModal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2 class="text-xl font-semibold mb-4">Teleport <span id="teleportPlayerName"></span></h2>
|
||||
<h2 class="text-xl minecraft-font mb-4">Teleport <span id="teleportPlayerName"></span></h2>
|
||||
<form id="teleportForm">
|
||||
<div class="mb-4">
|
||||
<label for="teleportDestination" class="block text-sm font-medium mb-1">Select Destination Player</label>
|
||||
<select id="teleportDestination" class="bg-gray-700 px-4 py-2 rounded text-white w-full">
|
||||
<label for="teleportDestination" class="block text-sm font-medium mb-1">Select Destination
|
||||
Player</label>
|
||||
<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 -->
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Teleport</button>
|
||||
<button type="submit" class="btn-minecraft w-full">Teleport</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -97,11 +170,12 @@
|
||||
<div id="effectModal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2 class="text-xl font-semibold mb-4">Apply Effect to <span id="effectPlayerName"></span></h2>
|
||||
<h2 class="text-xl minecraft-font mb-4">Apply Effect to <span id="effectPlayerName"></span></h2>
|
||||
<form id="effectForm">
|
||||
<div class="mb-4">
|
||||
<label for="effectSelect" class="block text-sm font-medium mb-1">Select Effect</label>
|
||||
<select id="effectSelect" class="bg-gray-700 px-4 py-2 rounded text-white w-full">
|
||||
<select id="effectSelect"
|
||||
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="strength:30:1">Strength (30s, Level 1)</option>
|
||||
<option value="regeneration:30:1">Regeneration (30s, Level 1)</option>
|
||||
@ -112,7 +186,7 @@
|
||||
<option value="water_breathing:60:1">Water Breathing (60s, Level 1)</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Apply Effect</button>
|
||||
<button type="submit" class="btn-minecraft w-full">Apply Effect</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -120,220 +194,204 @@
|
||||
<div id="editPropertiesModal" class="modal hidden">
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2 class="text-xl font-semibold mb-4">Edit server.properties</h2>
|
||||
<h2 class="text-xl minecraft-font mb-4">Edit server.properties</h2>
|
||||
<form id="editPropertiesForm" class="space-y-4">
|
||||
<div id="propertiesFields" class="space-y-2"></div>
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Save</button>
|
||||
<button type="submit" class="btn-minecraft w-full">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="updateModsModal"
|
||||
class="modal hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-2 sm:p-4">
|
||||
<div
|
||||
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]">
|
||||
<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 id="updateModsModal" class="modal hidden">
|
||||
<div class="modal-content flex flex-col">
|
||||
<div class="flex justify-between items-center p-4 border-b border-[rgba(255,255,255,0.12)]">
|
||||
<h2 class="text-xl minecraft-font">Mod Update Output</h2>
|
||||
<button class="modal-close text-2xl">×</button>
|
||||
</div>
|
||||
<pre id="updateModsOutput"
|
||||
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">
|
||||
<button id="closeUpdateModsBtn"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded w-full">Close</button>
|
||||
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>
|
||||
<div class="p-4 border-t border-[rgba(255,255,255,0.12)]">
|
||||
<button id="closeUpdateModsBtn" class="btn-minecraft w-full">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation (unchanged) -->
|
||||
<nav class="bg-gray-800 p-4 shadow-lg">
|
||||
<div class="container mx-auto flex justify-between items-center">
|
||||
<h1 class="text-2xl font-bold">My-MC Panel</h1>
|
||||
<div class="flex space-x-4">
|
||||
<button id="refresh" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded">Refresh</button>
|
||||
<button id="backupBtn" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded">Backup</button>
|
||||
<div id="authControls">
|
||||
<input id="apiKey" type="text" placeholder="Enter API Key" class="bg-gray-700 px-4 py-2 rounded text-white">
|
||||
<!-- Main Content -->
|
||||
<main id="mainContent" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-16 relative z-2">
|
||||
<div class="section-bg p-6 sm:p-8 mb-8" data-section="server-status">
|
||||
<div class="flex flex-col space-y-2 mb-4">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="text-3xl minecraft-font">Server Status</h2>
|
||||
<div class="flex space-x-2">
|
||||
<button id="startBtn" class="control-btn">Start</button>
|
||||
<button id="stopBtn" class="control-btn">Stop</button>
|
||||
<button id="restartBtn" class="control-btn">Restart</button>
|
||||
</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>
|
||||
</nav>
|
||||
|
||||
<!-- 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>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex flex-col space-y-1">
|
||||
<p><strong>User:</strong> <span id="user">Loading...</span></p>
|
||||
<p><strong>Key Expiry:</strong> <span id="keyExpiry">Loading...</span></p>
|
||||
<p><strong>Status:</strong> <span id="serverStatus">Loading...</span></p>
|
||||
</div>
|
||||
<div class="flex space-x-4 justify-center">
|
||||
<div class="flex space-x-4 justify-center items-start">
|
||||
<div class="text-center">
|
||||
<canvas id="memoryMeter" width="150" height="150"></canvas>
|
||||
<p class="text-sm mt-2"><b>Memory Usage</b></p>
|
||||
<canvas id="memoryMeter" width="120" height="120"></canvas>
|
||||
<p class="text-sm mt-1"><b>Memory Usage</b></p>
|
||||
<p id="memoryPercent" class="text-lg font-bold">0%</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<canvas id="cpuMeter" width="150" height="150"></canvas>
|
||||
<p class="text-sm mt-2"><b>CPU Usage</b></p>
|
||||
<canvas id="cpuMeter" width="120" height="120"></canvas>
|
||||
<p class="text-sm mt-1"><b>CPU Usage</b></p>
|
||||
<p id="cpuPercent" class="text-lg font-bold">0%</p>
|
||||
</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 class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Player Management</h2>
|
||||
<div class="mb-4"></div>
|
||||
|
||||
<div class="section-bg mb-12">
|
||||
<h2 class="text-3xl minecraft-font mb-8">Player Management</h2>
|
||||
<p><strong>Connected Players:</strong><br> <span id="playerList">Loading...</span></p>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Server Logs</h2>
|
||||
<div class="section-bg mb-12">
|
||||
<h2 class="text-3xl minecraft-font mb-8">Server Logs</h2>
|
||||
<div id="dockerLogsTerminal" class="mt-4"></div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Server Console</h2>
|
||||
<div class="section-bg mb-12">
|
||||
<h2 class="text-3xl minecraft-font mb-8">Server Console</h2>
|
||||
<form id="consoleForm" onsubmit="event.preventDefault(); sendConsoleCommand();">
|
||||
<input id="consoleInput" type="text" placeholder="Enter RCON Command (Hit Enter To Submit)"
|
||||
class="bg-gray-700 px-4 py-2 rounded text-white w-full mb-2">
|
||||
<button id="sendConsole" type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded"
|
||||
style="display: none;">Send</button>
|
||||
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)]">
|
||||
<button id="sendConsole" type="submit" class="btn-minecraft" style="display: none;">Send</button>
|
||||
</form>
|
||||
<pre id="consoleOutput" class="bg-gray-900 p-4 rounded mt-4 h-48 overflow-y-auto"></pre>
|
||||
<pre id="consoleOutput"
|
||||
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 class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6" id="sftpBrowserSection" style="display: none;">
|
||||
<div class="section-bg mb-12" id="sftpBrowserSection" style="display: none;">
|
||||
<div class="flex justify-between items-baseline mb-4">
|
||||
<h2 class="text-xl font-semibold">SFTP Browser</h2>
|
||||
<button id="sftpBtn" class="px-3 py-1 rounded text-sm flex items-center space-x-1"
|
||||
style="background-color: #121724; color: #ffffff;">
|
||||
<i class="fas fa-sync-alt" style="color: #121724;"></i>
|
||||
<h2 class="text-3xl minecraft-font">SFTP Browser</h2>
|
||||
<button id="sftpBtn" class="control-btn text-sm flex items-center space-x-1">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
<span>Refresh SFTP</span>
|
||||
</button>
|
||||
</div>
|
||||
<iframe id="sftpIframe" class="w-full rounded" style="height: 650px; min-height: 650px;"
|
||||
allow="clipboard-read; clipboard-write"></iframe>
|
||||
<iframe id="sftpIframe" class="w-full rounded" allow="clipboard-read; clipboard-write"></iframe>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Mod Management</h2>
|
||||
<div class="section-bg mb-12">
|
||||
<h2 class="text-3xl minecraft-font mb-8">Mod Management</h2>
|
||||
<form id="modSearchForm" onsubmit="event.preventDefault(); searchMods(1);">
|
||||
<div class="mb-4 flex space-x-2">
|
||||
<input id="modSearch" type="text" placeholder="Search Mods (Hit Enter To Submit)"
|
||||
class="bg-gray-700 px-4 py-2 rounded text-white flex-grow">
|
||||
<button id="searchBtn" type="submit" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded"
|
||||
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)]">
|
||||
<button id="searchBtn" type="submit" class="btn-minecraft"
|
||||
style="display: none;">Search</button>
|
||||
<button id="closeSearchBtn" type="button"
|
||||
class="bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded hidden">Close</button>
|
||||
<button id="closeSearchBtn" type="button" class="btn-minecraft hidden">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
<div id="modResults" class="grid grid-cols-1 md:grid-cols-2 gap-4"></div>
|
||||
<div id="modResults" class="grid grid-cols-1 md:grid-cols-2 gap-6"></div>
|
||||
<div id="pagination" class="mt-4 flex justify-center space-x-2"></div>
|
||||
<h3 class="text-lg font-semibold mt-4">Installed Mods</h3>
|
||||
<h3 class="text-xl minecraft-font mt-4">Installed Mods</h3>
|
||||
<div class="mb-4 flex space-x-2">
|
||||
<input id="modListSearch" type="text" placeholder="Search Installed Mods"
|
||||
class="bg-gray-700 px-4 py-2 rounded text-white flex-grow">
|
||||
<button id="clearModListSearch" type="button"
|
||||
class="bg-gray-600 hover:bg-gray-700 px-4 py-2 rounded hidden">Clear</button>
|
||||
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)]">
|
||||
<button id="clearModListSearch" type="button" class="btn-minecraft hidden">Clear</button>
|
||||
</div>
|
||||
<div id="modList" class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-4"></div>
|
||||
<div id="modList" class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-6"></div>
|
||||
<div id="modListPagination" class="mt-4 flex justify-center space-x-2"></div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||
<h2 class="text-xl font-semibold mb-4">Server Links</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<p><strong>Advanced Log URL:</strong> <a id="logUrl" href="#" class="text-blue-400"
|
||||
target="_blank">Loading...</a></p>
|
||||
<p><strong>Website URL:</strong> <a id="websiteUrl" href="#" class="text-blue-400"
|
||||
target="_blank">Loading...</a></p>
|
||||
<p><strong>BlueMap URL:</strong> <a id="mapUrl" href="#" class="text-blue-400" target="_blank">Loading...</a>
|
||||
<div class="section-bg mb-12 p-8 rounded-lg">
|
||||
<h2 class="text-3xl minecraft-font mb-10 font-bold text-white">Server Links</h2>
|
||||
<div class="flex flex-wrap gap-6 mb-6">
|
||||
<!-- Connection Link Card -->
|
||||
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow flex-1 min-w-[250px]">
|
||||
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">Connection Link</h3>
|
||||
<p class="text-gray-300 mb-4 break-all">
|
||||
<span id="myLink" class="text-blue-400">Link Not Created</span>
|
||||
<span id="connectionStatus" class="text-sm"></span>
|
||||
</p>
|
||||
<div>
|
||||
<p><strong>Connection Link:</strong> <span id="myLink">Link Not Created</span> <span
|
||||
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>
|
||||
<button id="generateMyLinkBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md transition-colors">
|
||||
Generate Connection Link
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>Geyser Link:</strong> <span id="geyserLink">Link Not Created</span> <span
|
||||
id="geyserStatus"></span></p>
|
||||
<button id="generateGeyserLinkBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-1 rounded mt-2">Generate
|
||||
Geyser Link</button>
|
||||
|
||||
<!-- Geyser Link Card -->
|
||||
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow flex-1 min-w-[250px]">
|
||||
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">Geyser Link</h3>
|
||||
<p class="text-gray-300 mb-4 break-all">
|
||||
<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>
|
||||
<p><strong>SFTP Link:</strong> <span id="sftpLink">Link Not Created</span> <span id="sftpStatus"></span></p>
|
||||
<button id="generateSftpLinkBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-1 rounded mt-2">Generate SFTP
|
||||
Link</button>
|
||||
|
||||
<!-- SFTP Link Card -->
|
||||
<div class="bg-gray-800/40 p-6 rounded-xl shadow-md hover:shadow-lg transition-shadow flex-1 min-w-[250px]">
|
||||
<h3 class="text-xl minecraft-font font-semibold text-white mb-3">SFTP Link</h3>
|
||||
<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>
|
||||
|
||||
<!-- Updated Holesail Keys Section -->
|
||||
<div class="bg-gray-800 p-6 rounded-lg shadow-lg mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold text-white">Holesail Keys</h2>
|
||||
<!-- Holesail Keys Section -->
|
||||
<div class="section-bg mb-12">
|
||||
<div class="flex items-center justify-between mb-4 flex-wrap">
|
||||
<h2 class="text-3xl minecraft-font">Holesail Keys</h2>
|
||||
<button id="toggleTutorial"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-md transition duration-200">Tutorial</button>
|
||||
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>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
||||
<div class="flex items-center bg-gray-700 p-3 rounded-md">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
|
||||
<div class="flex items-center p-4">
|
||||
<div class="flex-grow">
|
||||
<p class="text-gray-300"><strong>Minecraft Key:</strong></p>
|
||||
<p class="text-gray-100 break-all" id="holesailHash">Not Loaded</p>
|
||||
<p class="text-sm text-gray-400">Port: 127.0.0.1:25565</p>
|
||||
<p><strong>Minecraft Key:</strong></p>
|
||||
<p class="break-all" id="holesailHash">Not Loaded</p>
|
||||
<p class="text-sm">Port: 127.0.0.1:25565</p>
|
||||
</div>
|
||||
<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"
|
||||
<button class="copy-key-btn ml-2" 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">
|
||||
@ -343,73 +401,108 @@
|
||||
</svg>
|
||||
</button>
|
||||
</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 id="tutorialSection" class="hidden">
|
||||
<div class="bg-gray-700 p-6 rounded-xl mb-6 border border-gray-600">
|
||||
<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-gray-200 text-base leading-relaxed mb-4">
|
||||
<div class="feature-card tilt-card p-6 mb-6">
|
||||
<h3 class="text-xl minecraft-font mb-4">What is Holesail.io?</h3>
|
||||
<p class="text-base leading-relaxed mb-4">
|
||||
<a href="https://holesail.io" target="_blank"
|
||||
class="text-blue-400 hover:underline font-medium">Holesail.io</a> is an open-source, peer-to-peer
|
||||
networking tool that creates secure, encrypted tunnels that bypass network restrictions, firewalls, and
|
||||
NAT.<BR>It exposes your local network to the internet without needing port forwarding, static IPs, or
|
||||
Dynamic DNS, acting as a versatile tunneling and reverse proxy solution.
|
||||
class="text-teal-400 hover:text-blue-400">Holesail.io</a> is an open-source,
|
||||
peer-to-peer networking tool that creates secure, encrypted tunnels that bypass network
|
||||
restrictions, firewalls, and NAT. It exposes your local network to the internet without
|
||||
needing port forwarding, static IPs, or Dynamic DNS, acting as a versatile tunneling and
|
||||
reverse proxy solution.
|
||||
</p>
|
||||
<div class="mb-4">
|
||||
<p class="text-gray-200 font-semibold mb-2">With Holesail, you can:</p>
|
||||
<ul class="list-disc pl-6 space-y-1 text-gray-200 text-base">
|
||||
<p class="font-semibold mb-2">With Holesail, you can:</p>
|
||||
<ul class="list-disc pl-6 space-y-1 text-base">
|
||||
<li>Access machines over the internet securely.</li>
|
||||
<li>Share locally running servers, websites, or AI models with other ports/services.</li>
|
||||
<li>Share locally running servers, websites, or AI models with other ports/services.
|
||||
</li>
|
||||
<li>Transfer files and folders remotely without bandwidth or size limits.</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>Built for ANY application, Holesail supports both the TCP and UDP Protocols nativly.</li>
|
||||
<li>Expose single ports to the peer-to-peer network, unlike VPNs you never expose your entire local
|
||||
network.</li>
|
||||
<BR>And so much more! With Holesail, the possiblities are endless!
|
||||
<li>Built for ANY application, Holesail supports both the TCP and UDP Protocols
|
||||
natively.</li>
|
||||
<li>Expose single ports to the peer-to-peer network, unlike VPNs you never expose your
|
||||
entire local network.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="text-gray-200 text-base leading-relaxed">
|
||||
Built with security in mind, Holesail ensures all data is encrypted and never touches third-party
|
||||
servers.<BR>Connections are truly peer-to-peer, accessible only to those with whom you share your private
|
||||
key, providing both ease of use and robust security.<BR>Other peers cannot detect your activity or
|
||||
services.<BR>As an open-source tool, Holesail enables third-party services to integrate it, enhancing
|
||||
their security and connectivity.
|
||||
<p class="text-base leading-relaxed">
|
||||
Built with security in mind, Holesail ensures all data is encrypted and never touches
|
||||
third-party servers. Connections are truly peer-to-peer, accessible only to those with whom
|
||||
you share your private key, providing both ease of use and robust security. Other peers
|
||||
cannot detect your activity or services. As an open-source tool, Holesail enables
|
||||
third-party services to integrate it, enhancing their security and connectivity.
|
||||
</p>
|
||||
<p class="text-gray-200 text-base leading-relaxed">
|
||||
<BR>Your Public My-MC Ports are Holesail connections hosted on a separate server, not our Minecraft
|
||||
host.<BR>They use the same keys from the tutorial below. We hook 'em up at our jump host to go public.
|
||||
Pretty dope, right?
|
||||
<p class="text-base leading-relaxed mt-4">
|
||||
Your Public My-MC Ports are Holesail connections hosted on a separate server, not our
|
||||
Minecraft host. They use the same keys from the tutorial below. We hook 'em up at our jump
|
||||
host to go public.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-700 p-4 rounded-md mb-6">
|
||||
<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 text-gray-300">
|
||||
<li>Ensure <a href="https://nodejs.org/" target="_blank" class="text-blue-400 hover:underline">Node.js</a>
|
||||
is installed on your system.</li>
|
||||
<div class="feature-card tilt-card p-6 mb-6">
|
||||
<h3 class="text-xl minecraft-font mb-4">How to Use Holesail Keys</h3>
|
||||
<ol class="list-decimal list-inside space-y-2">
|
||||
<li>Ensure <a href="https://nodejs.org/" target="_blank"
|
||||
class="text-teal-400 hover:text-blue-400">Node.js</a> is installed on your system.
|
||||
</li>
|
||||
<li>Install Holesail by running:
|
||||
<pre class="bg-gray-800 p-2 rounded mt-1 text-sm">npm i holesail@2.1.0</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)]">npm i holesail@2.1.0</pre>
|
||||
</li>
|
||||
<li>Connect to a key using the appropriate command:
|
||||
<ul class="list-disc list-inside ml-4 mt-1">
|
||||
<li>For Minecraft Key (e.g., Minecraft server):
|
||||
<pre
|
||||
class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialHolesailHash">Not Loaded</span></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>
|
||||
</li>
|
||||
<li>For Geyser key (e.g., cross-platform Minecraft):
|
||||
<pre
|
||||
class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialGeyserHash">Not Loaded</span></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>
|
||||
</li>
|
||||
<li>For SFTP key (e.g., file transfer):
|
||||
<pre
|
||||
class="bg-gray-800 p-2 rounded mt-1 text-sm">holesail <span id="tutorialSftpHash">Not Loaded</span></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>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="holesail-output-mobile-hidden">Holesail will confirm the connection. Example output for your
|
||||
Minecraft server:
|
||||
<pre class="bg-gray-800 p-2 rounded mt-1 text-sm">
|
||||
<li class="holesail-output-mobile-hidden">Holesail will confirm the connection. Example
|
||||
output for your Minecraft server:
|
||||
<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="tutorialHolesailHashOutput">Not Loaded</span>
|
||||
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
| |
|
||||
@ -425,49 +518,48 @@
|
||||
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
</pre>
|
||||
</li>
|
||||
<BR>Now you can connect to your own localhost within Minecraft!<BR><BR>Connect to:
|
||||
<code class="bg-gray-800 px-1 rounded">127.0.0.1:25565</code><BR><BR>
|
||||
<li>Now you can connect to your own localhost within Minecraft!<br>Connect to:
|
||||
<code
|
||||
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
|
||||
class="bg-gray-800 px-1 rounded">--host 0.0.0.0</code> switch:
|
||||
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>
|
||||
switch:
|
||||
<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>
|
||||
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.
|
||||
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>
|
||||
<br>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.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-700 p-4 rounded-md">
|
||||
<h3 class="text-lg font-semibold mb-3 text-white">Share with Friends</h3>
|
||||
<p class="text-gray-300 mb-3">
|
||||
Share this tutorial with your friends so they can connect to your Minecraft server or other services on
|
||||
their own localhosts!<BR>With Holesail, no public IPs are needed! Everything stays secure and
|
||||
peer-to-peer!
|
||||
<div class="feature-card tilt-card p-6">
|
||||
<h3 class="text-xl minecraft-font mb-4">Share with Friends</h3>
|
||||
<p class="mb-3">
|
||||
Share this tutorial with your friends so they can connect to your Minecraft server or other
|
||||
services on their own localhosts! With Holesail, no public IPs are needed! Everything stays
|
||||
secure and peer-to-peer!
|
||||
</p>
|
||||
<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>
|
||||
<button id="copyTutorial" class="btn-minecraft">Copy Tutorial</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="bg-gray-800 py-4">
|
||||
<div class="container mx-auto px-6 text-center">
|
||||
<p class="text-gray-400 text-sm">
|
||||
© 2025 My-MC.Link. All rights reserved.<br>
|
||||
<a href="https://raven-scott.fyi" target="_blank" class="text-blue-400 hover:text-blue-500">Made with ❤️ by
|
||||
SNXRaven</a> | <a href="https://git.ssh.surf/hypermc/panel" target="_blank"
|
||||
class="text-blue-400 hover:text-blue-500">Source Code</a>
|
||||
<footer class="bg-[rgba(10,17,40,0.75)] backdrop-filter backdrop-blur-xl py-8 text-center relative z-2">
|
||||
<p class="text-sm opacity-90">© 2025 My-MC.Link. All rights reserved.</p>
|
||||
<p class="text-sm opacity-90 mt-3">
|
||||
Powered by <a href="https://holesail.io" class="underline text-teal-400 hover:text-blue-400"
|
||||
target="_blank">Holesail</a> with services
|
||||
donated by <a href="https://raven-scott.fyi"
|
||||
class="underline text-teal-400 hover:text-blue-400">SNXRaven</a> |
|
||||
<a href="https://git.ssh.surf/hypermc/panel" class="underline text-teal-400 hover:text-blue-400"
|
||||
target="_blank">Source Code</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/app_test.js"></script>
|
||||
<script src="js/tutorial.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
218
public/js/app.js
218
public/js/app.js
@ -28,6 +28,137 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
'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 = {
|
||||
loginPage: document.getElementById('loginPage'),
|
||||
loginApiKey: document.getElementById('loginApiKey'),
|
||||
@ -321,7 +452,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
terminal.clear();
|
||||
} else {
|
||||
terminal = new Terminal({
|
||||
rows: 8,
|
||||
rows: 22,
|
||||
fontSize: 14,
|
||||
fontFamily: 'monospace',
|
||||
theme: {
|
||||
@ -1038,9 +1169,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
elements.loginPage.classList.remove('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.addEventListener('change', handleApiKeyChange);
|
||||
if (ws) {
|
||||
ws.close();
|
||||
ws = null;
|
||||
@ -1069,13 +1198,35 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
elements.loginPage.classList.add('hidden');
|
||||
elements.mainContent.classList.remove('hidden');
|
||||
elements.authControls.innerHTML = '<button id="logoutBtn" class="bg-red-600 hover:bg-red-700 px-4 py-2 rounded">Logout</button>';
|
||||
// Verify buttons exist
|
||||
const logoutBtn = document.getElementById('logoutBtn');
|
||||
const mobileLogoutBtn = document.getElementById('mobileLogoutBtn');
|
||||
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', handleLogout);
|
||||
console.log('Desktop logout button found');
|
||||
} else {
|
||||
console.error('Logout button not found after insertion');
|
||||
console.error('Desktop logout button (#logoutBtn) not found');
|
||||
}
|
||||
|
||||
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();
|
||||
initializeTerminal();
|
||||
}
|
||||
@ -1095,6 +1246,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
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() {
|
||||
const totalPages = Math.max(1, Math.ceil(totalResults / resultsPerPage));
|
||||
elements.pagination.innerHTML = '';
|
||||
@ -1687,7 +1850,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
switchContainer.className = 'relative inline-block';
|
||||
switchContainer.setAttribute('role', 'switch');
|
||||
switchContainer.setAttribute('aria-checked', value.toLowerCase());
|
||||
switchContainer.setAttribute('tabindex', '0');
|
||||
switchContainer.dataset.name = key;
|
||||
switchContainer.style.width = '40px';
|
||||
switchContainer.style.height = '24px';
|
||||
@ -1918,7 +2080,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
|
||||
elements.apiKeyInput.addEventListener('change', handleApiKeyChange);
|
||||
// elements.apiKeyInput.addEventListener('change', handleApiKeyChange);
|
||||
|
||||
elements.generateMyLinkBtn.addEventListener('click', async () => {
|
||||
try {
|
||||
@ -2065,6 +2227,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
elements.updateModsBtn.addEventListener('click', updateMods);
|
||||
|
||||
elements.closeUpdateModsBtn.addEventListener('click', () => {
|
||||
@ -2177,4 +2341,42 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
showLoginPage();
|
||||
}
|
||||
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);
|
||||
|
||||
|
||||
});
|
@ -4,6 +4,7 @@ module.exports = {
|
||||
'./public/**/*.html',
|
||||
'./public/**/*.js',
|
||||
'./public/*.html',
|
||||
'./public/css/*.css',
|
||||
'./public/*.js'
|
||||
],
|
||||
theme: {
|
||||
|
Reference in New Issue
Block a user