From c464f3b3b54f05dac1a24693e5748c76dab97f01 Mon Sep 17 00:00:00 2001 From: MCHost Date: Thu, 3 Jul 2025 02:51:10 -0400 Subject: [PATCH] update to add widget section --- public/css/style.css | 29 ++++++++- public/css/style.min.css | 137 +++++++++++++++++++++++++++++++-------- public/index.html | 18 +++++ public/js/app.js | 21 ++++++ status-site.js | 9 +-- 5 files changed, 180 insertions(+), 34 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index b8cad4b..cbbc61f 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -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; } \ No newline at end of file diff --git a/public/css/style.min.css b/public/css/style.min.css index 0887750..dabac42 100644 --- a/public/css/style.min.css +++ b/public/css/style.min.css @@ -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; diff --git a/public/index.html b/public/index.html index 364150e..deba6c5 100644 --- a/public/index.html +++ b/public/index.html @@ -51,6 +51,21 @@

Server Status

+ + + diff --git a/public/js/app.js b/public/js/app.js index 28d5bf7..2ed4b04 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -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 = '

Checking...

'; try { @@ -88,6 +91,11 @@ document.getElementById('serverForm').addEventListener('submit', async (e) => {

${key}: ${value}

`).join('')} `; + + // Show widget section and set widget code + widgetSection.classList.remove('hidden'); + const widgetIframe = ``; + widgetCode.textContent = widgetIframe; } else { statusContent.innerHTML = `

Status: Offline

@@ -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]) { diff --git a/status-site.js b/status-site.js index 99ca7fa..951a849 100644 --- a/status-site.js +++ b/status-site.js @@ -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));