update to add widget section
This commit is contained in:
@ -59,7 +59,32 @@
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add fade-out animation for the banner alert */
|
||||
@keyframes fadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#copyAlert {
|
||||
transition: opacity 0.3s ease-out;
|
||||
}
|
||||
|
||||
#copyAlert.hidden {
|
||||
opacity: 0;
|
||||
}
|
137
public/css/style.min.css
vendored
137
public/css/style.min.css
vendored
@ -8,49 +8,25 @@
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||
"Courier New", monospace;
|
||||
--color-red-400: oklch(70.4% 0.191 22.216);
|
||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||
--color-red-600: oklch(57.7% 0.245 27.325);
|
||||
--color-red-700: oklch(50.5% 0.213 27.518);
|
||||
--color-yellow-600: oklch(68.1% 0.162 75.834);
|
||||
--color-yellow-700: oklch(55.4% 0.135 66.442);
|
||||
--color-yellow-400: oklch(85.2% 0.199 91.936);
|
||||
--color-green-400: oklch(79.2% 0.209 151.711);
|
||||
--color-green-600: oklch(62.7% 0.194 149.214);
|
||||
--color-green-700: oklch(52.7% 0.154 150.069);
|
||||
--color-teal-600: oklch(60% 0.118 184.704);
|
||||
--color-teal-700: oklch(51.1% 0.096 186.391);
|
||||
--color-cyan-600: oklch(60.9% 0.126 221.723);
|
||||
--color-cyan-700: oklch(52% 0.105 223.128);
|
||||
--color-blue-400: oklch(70.7% 0.165 254.624);
|
||||
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||
--color-blue-600: oklch(54.6% 0.245 262.881);
|
||||
--color-blue-700: oklch(48.8% 0.243 264.376);
|
||||
--color-purple-600: oklch(55.8% 0.288 302.321);
|
||||
--color-purple-700: oklch(49.6% 0.265 301.924);
|
||||
--color-gray-100: oklch(96.7% 0.003 264.542);
|
||||
--color-gray-200: oklch(92.8% 0.006 264.531);
|
||||
--color-gray-300: oklch(87.2% 0.01 258.338);
|
||||
--color-gray-400: oklch(70.7% 0.022 261.325);
|
||||
--color-gray-500: oklch(55.1% 0.027 264.364);
|
||||
--color-gray-600: oklch(44.6% 0.03 256.802);
|
||||
--color-gray-700: oklch(37.3% 0.034 259.733);
|
||||
--color-gray-800: oklch(27.8% 0.033 256.848);
|
||||
--color-gray-900: oklch(21% 0.034 264.665);
|
||||
--color-black: #000;
|
||||
--color-white: #fff;
|
||||
--spacing: 0.25rem;
|
||||
--container-md: 28rem;
|
||||
--container-lg: 32rem;
|
||||
--container-7xl: 80rem;
|
||||
--text-xs: 0.75rem;
|
||||
--text-xs--line-height: calc(1 / 0.75);
|
||||
--text-sm: 0.875rem;
|
||||
--text-sm--line-height: calc(1.25 / 0.875);
|
||||
--text-base: 1rem;
|
||||
--text-base--line-height: calc(1.5 / 1);
|
||||
--text-lg: 1.125rem;
|
||||
--text-lg--line-height: calc(1.75 / 1.125);
|
||||
--text-xl: 1.25rem;
|
||||
--text-xl--line-height: calc(1.75 / 1.25);
|
||||
--text-2xl: 1.5rem;
|
||||
--text-2xl--line-height: calc(2 / 1.5);
|
||||
--text-4xl: 2.25rem;
|
||||
@ -59,12 +35,9 @@
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
--tracking-tight: -0.025em;
|
||||
--leading-relaxed: 1.625;
|
||||
--radius-md: 0.375rem;
|
||||
--radius-lg: 0.5rem;
|
||||
--radius-xl: 0.75rem;
|
||||
--radius-2xl: 1rem;
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
--blur-md: 12px;
|
||||
--default-transition-duration: 150ms;
|
||||
@ -219,21 +192,36 @@
|
||||
}
|
||||
}
|
||||
@layer utilities {
|
||||
.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
.absolute {
|
||||
position: absolute;
|
||||
}
|
||||
.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
.inset-0 {
|
||||
inset: calc(var(--spacing) * 0);
|
||||
}
|
||||
.top-4 {
|
||||
top: calc(var(--spacing) * 4);
|
||||
}
|
||||
.left-1\/2 {
|
||||
left: calc(1/2 * 100%);
|
||||
}
|
||||
.z-0 {
|
||||
z-index: 0;
|
||||
}
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
.z-50 {
|
||||
z-index: 50;
|
||||
}
|
||||
.mx-auto {
|
||||
margin-inline: auto;
|
||||
}
|
||||
@ -246,6 +234,9 @@
|
||||
.mt-8 {
|
||||
margin-top: calc(var(--spacing) * 8);
|
||||
}
|
||||
.mb-4 {
|
||||
margin-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
@ -270,6 +261,13 @@
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.-translate-x-1\/2 {
|
||||
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.transform {
|
||||
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
||||
}
|
||||
.animate-pulse {
|
||||
animation: var(--animate-pulse);
|
||||
}
|
||||
@ -286,12 +284,18 @@
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.rounded-2xl {
|
||||
border-radius: var(--radius-2xl);
|
||||
}
|
||||
.rounded-lg {
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
.rounded-md {
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
.border {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
@ -308,6 +312,9 @@
|
||||
background-color: color-mix(in oklab, var(--color-gray-700) 50%, transparent);
|
||||
}
|
||||
}
|
||||
.bg-gray-800 {
|
||||
background-color: var(--color-gray-800);
|
||||
}
|
||||
.bg-gray-800\/50 {
|
||||
background-color: color-mix(in srgb, oklch(27.8% 0.033 256.848) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
@ -323,6 +330,9 @@
|
||||
.bg-gray-900 {
|
||||
background-color: var(--color-gray-900);
|
||||
}
|
||||
.p-4 {
|
||||
padding: calc(var(--spacing) * 4);
|
||||
}
|
||||
.p-6 {
|
||||
padding: calc(var(--spacing) * 6);
|
||||
}
|
||||
@ -335,6 +345,9 @@
|
||||
.px-4 {
|
||||
padding-inline: calc(var(--spacing) * 4);
|
||||
}
|
||||
.px-6 {
|
||||
padding-inline: calc(var(--spacing) * 6);
|
||||
}
|
||||
.py-2 {
|
||||
padding-block: calc(var(--spacing) * 2);
|
||||
}
|
||||
@ -402,6 +415,13 @@
|
||||
.text-white {
|
||||
color: var(--color-white);
|
||||
}
|
||||
.text-yellow-400 {
|
||||
color: var(--color-yellow-400);
|
||||
}
|
||||
.shadow-lg {
|
||||
--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
}
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
@ -435,6 +455,10 @@
|
||||
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
}
|
||||
.backdrop-filter {
|
||||
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
||||
}
|
||||
.transition-all {
|
||||
transition-property: all;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
@ -545,6 +569,55 @@
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
#copyAlert {
|
||||
transition: opacity 0.3s ease-out;
|
||||
}
|
||||
#copyAlert.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
@property --tw-translate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-translate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-translate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-rotate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-rotate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-skew-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-skew-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-space-y-reverse {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@ -681,6 +754,14 @@
|
||||
@layer properties {
|
||||
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
||||
*, ::before, ::after, ::backdrop {
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-translate-z: 0;
|
||||
--tw-rotate-x: initial;
|
||||
--tw-rotate-y: initial;
|
||||
--tw-rotate-z: initial;
|
||||
--tw-skew-x: initial;
|
||||
--tw-skew-y: initial;
|
||||
--tw-space-y-reverse: 0;
|
||||
--tw-border-style: solid;
|
||||
--tw-font-weight: initial;
|
||||
|
@ -51,6 +51,21 @@
|
||||
<h2 class="text-2xl font-semibold text-blue-400 animate-slide-in">Server Status</h2>
|
||||
<div id="statusContent" class="mt-4 p-6 bg-gray-700/50 rounded-lg text-gray-200 ring-1 ring-gray-600/50"></div>
|
||||
</div>
|
||||
<div id="widgetSection" class="mt-8 hidden">
|
||||
<h2 class="text-2xl font-semibold text-blue-400 animate-slide-in">Embed Server Status Widget</h2>
|
||||
<div class="mt-4 p-6 bg-gray-700/50 rounded-lg text-gray-200 ring-1 ring-gray-600/50">
|
||||
<p class="mb-4">Add a widget to your website to display your server's status:</p>
|
||||
<pre id="widgetCode" class="bg-gray-800 p-4 rounded-md text-sm text-gray-300 overflow-x-auto" style="display: none;"></pre>
|
||||
|
||||
<button id="copyWidgetCode" class="mt-4 bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition-all duration-300 shadow-md hover:shadow-lg">
|
||||
Copy Widget Code
|
||||
</button>
|
||||
<div id="copyAlert" class="hidden fixed bottom-4 right-4 bg-blue-600 text-white text-sm px-6 py-3 rounded-lg shadow-lg animate-slide-in z-50">
|
||||
Widget code copied to clipboard!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<footer class="relative z-10 bg-gray-800/80 backdrop-blur-md py-4 shadow-md">
|
||||
@ -58,6 +73,9 @@
|
||||
<p class="text-gray-400 text-sm">© 2025 My-MC.Link Server Status Checker</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
|
||||
</script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
|
||||
|
@ -34,6 +34,8 @@ document.getElementById('serverForm').addEventListener('submit', async (e) => {
|
||||
const loadingSpinner = document.getElementById('loadingSpinner');
|
||||
const statusResult = document.getElementById('statusResult');
|
||||
const statusContent = document.getElementById('statusContent');
|
||||
const widgetSection = document.getElementById('widgetSection');
|
||||
const widgetCode = document.getElementById('widgetCode');
|
||||
const submitButton = e.target.querySelector('button[type="submit"]');
|
||||
|
||||
if (!host || !port) {
|
||||
@ -45,6 +47,7 @@ document.getElementById('serverForm').addEventListener('submit', async (e) => {
|
||||
loadingSpinner.style.display = 'block';
|
||||
submitButton.disabled = true;
|
||||
statusResult.classList.add('hidden');
|
||||
widgetSection.classList.add('hidden');
|
||||
statusContent.innerHTML = '<p class="animate-pulse">Checking...</p>';
|
||||
|
||||
try {
|
||||
@ -88,6 +91,11 @@ document.getElementById('serverForm').addEventListener('submit', async (e) => {
|
||||
<p><strong class="text-blue-400">${key}:</strong> ${value}</p>
|
||||
`).join('')}
|
||||
`;
|
||||
|
||||
// Show widget section and set widget code
|
||||
widgetSection.classList.remove('hidden');
|
||||
const widgetIframe = `<iframe src="https://status.my-mc.link/widget/${edition}/${host}/${port}" width="280" height="145" frameborder="0" scrolling="no"></iframe>`;
|
||||
widgetCode.textContent = widgetIframe;
|
||||
} else {
|
||||
statusContent.innerHTML = `
|
||||
<p><strong class="text-blue-400">Status:</strong> <span class="text-red-400">Offline</span></p>
|
||||
@ -114,6 +122,19 @@ document.getElementById('serverForm').addEventListener('submit', async (e) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Assuming the copy functionality is in js/app.js, add this to handle the banner alert
|
||||
document.getElementById('copyWidgetCode').addEventListener('click', function () {
|
||||
const widgetCode = document.getElementById('widgetCode').textContent;
|
||||
navigator.clipboard.writeText(widgetCode).then(() => {
|
||||
const alert = document.getElementById('copyAlert');
|
||||
alert.classList.remove('hidden');
|
||||
setTimeout(() => {
|
||||
alert.classList.add('hidden');
|
||||
}, 3000);
|
||||
}).catch(err => {
|
||||
console.error('Failed to copy: ', err);
|
||||
});
|
||||
});
|
||||
// Handle URL-based checks
|
||||
const path = window.location.pathname.split('/');
|
||||
if (path[1] && path[2] && path[3]) {
|
||||
|
@ -406,10 +406,11 @@ app.get('/widget/:edition/:host/:port', (req, res) => {
|
||||
try {
|
||||
validateEdition(edition);
|
||||
validateHostname(host);
|
||||
if (host !== 'my-mc.link') {
|
||||
logger.error('Unauthorized hostname', { host });
|
||||
throw new Error('Hostname must be my-mc.link');
|
||||
}
|
||||
// Uncomment this to only allow our system servers to have widgets.
|
||||
// if (host !== 'my-mc.link') {
|
||||
// logger.error('Unauthorized hostname', { host });
|
||||
// throw new Error('Hostname must be my-mc.link');
|
||||
// }
|
||||
validatePort(port);
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.send(widgetTemplate(edition, host, port));
|
||||
|
Reference in New Issue
Block a user