Update UptimeStatusIsland and UpdateTimer components for improved refresh intervals and styling

- Increased the refresh interval in UpdateTimer from 300 seconds to 1800 seconds for less frequent updates.
- Refactored UptimeStatusIsland to utilize a 30-minute window for data caching and fetching, enhancing performance.
- Updated styles in UptimeStatusIsland for better visual consistency, including backdrop blur effects and improved layout for mobile responsiveness.
This commit is contained in:
becarta
2025-06-11 23:37:13 +02:00
parent a67e19a2f8
commit afe9d45b5e
4 changed files with 37 additions and 34 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
const REFRESH_INTERVAL = 300; // seconds const REFRESH_INTERVAL = 1800; // seconds
export default function UpdateTimer({ onRefresh }) { export default function UpdateTimer({ onRefresh }) {
const [secondsLeft, setSecondsLeft] = useState(REFRESH_INTERVAL); const [secondsLeft, setSecondsLeft] = useState(REFRESH_INTERVAL);

View File

@@ -105,36 +105,37 @@ export default function UptimeStatusIsland() {
setUserLocale(navigator.language || 'en-US'); setUserLocale(navigator.language || 'en-US');
}, []); }, []);
const getSecondsToNext5Min = () => { // Helper: get the current 30-min window key (e.g., '2024-06-07T12:00')
const getCurrent30MinKey = () => {
const now = new Date();
now.setSeconds(0, 0);
const min = now.getMinutes();
now.setMinutes(Math.floor(min / 30) * 30);
return now.toISOString().slice(0, 16); // 'YYYY-MM-DDTHH:mm'
};
// Helper: get seconds to next 30-min mark
const getSecondsToNext30Min = () => {
const now = new Date(); const now = new Date();
const minutes = now.getMinutes(); const minutes = now.getMinutes();
const seconds = now.getSeconds(); const seconds = now.getSeconds();
const ms = now.getMilliseconds(); const ms = now.getMilliseconds();
const next5 = Math.ceil((minutes + 0.01) / 5) * 5; const next30 = Math.ceil((minutes + 0.01) / 30) * 30;
let next = new Date(now); let next = new Date(now);
next.setMinutes(next5, 0, 0); next.setMinutes(next30, 0, 0);
if (next <= now) { if (next <= now) {
next.setMinutes(next.getMinutes() + 5); next.setMinutes(next.getMinutes() + 30);
} }
return Math.floor((next - now) / 1000); return Math.floor((next - now) / 1000);
}; };
useEffect(() => { useEffect(() => {
const update = () => setSecondsToNextUpdate(getSecondsToNext5Min()); const update = () => setSecondsToNextUpdate(getSecondsToNext30Min());
update(); update();
const interval = setInterval(update, 1000); const interval = setInterval(update, 1000);
return () => clearInterval(interval); return () => clearInterval(interval);
}, []); }, []);
// Helper: get the current 5-min window key (e.g., '2024-06-07T12:00')
const getCurrent5MinKey = () => {
const now = new Date();
now.setSeconds(0, 0);
const min = now.getMinutes();
now.setMinutes(Math.floor(min / 5) * 5);
return now.toISOString().slice(0, 16); // 'YYYY-MM-DDTHH:mm'
};
// On mount, check sessionStorage for valid cached data // On mount, check sessionStorage for valid cached data
useEffect(() => { useEffect(() => {
const cacheKey = 'uptimeStatusCache'; const cacheKey = 'uptimeStatusCache';
@@ -142,7 +143,7 @@ export default function UptimeStatusIsland() {
if (cache) { if (cache) {
try { try {
const { key, data: cachedData } = JSON.parse(cache); const { key, data: cachedData } = JSON.parse(cache);
if (key === getCurrent5MinKey() && cachedData) { if (key === getCurrent30MinKey() && cachedData) {
setData(cachedData); setData(cachedData);
setLoading(false); setLoading(false);
return; return;
@@ -162,9 +163,9 @@ export default function UptimeStatusIsland() {
if (!response.ok) throw new Error('Failed to fetch uptime data'); if (!response.ok) throw new Error('Failed to fetch uptime data');
const json = await response.json(); const json = await response.json();
setData(json); setData(json);
// Cache with current 5-min key // Cache with current 30-min key
const cacheKey = 'uptimeStatusCache'; const cacheKey = 'uptimeStatusCache';
sessionStorage.setItem(cacheKey, JSON.stringify({ key: getCurrent5MinKey(), data: json })); sessionStorage.setItem(cacheKey, JSON.stringify({ key: getCurrent30MinKey(), data: json }));
} catch (err) { } catch (err) {
setError(err.message || 'Unknown error'); setError(err.message || 'Unknown error');
} finally { } finally {
@@ -172,7 +173,7 @@ export default function UptimeStatusIsland() {
} }
}, []); }, []);
// Scheduled fetch logic (every 5 min, update cache) // Scheduled fetch logic (every 30 min, update cache)
const fetchData = useCallback(async () => { const fetchData = useCallback(async () => {
setLoading(true); setLoading(true);
setError(null); setError(null);
@@ -181,9 +182,9 @@ export default function UptimeStatusIsland() {
if (!response.ok) throw new Error('Failed to fetch uptime data'); if (!response.ok) throw new Error('Failed to fetch uptime data');
const json = await response.json(); const json = await response.json();
setData(json); setData(json);
// Cache with current 5-min key // Cache with current 30-min key
const cacheKey = 'uptimeStatusCache'; const cacheKey = 'uptimeStatusCache';
sessionStorage.setItem(cacheKey, JSON.stringify({ key: getCurrent5MinKey(), data: json })); sessionStorage.setItem(cacheKey, JSON.stringify({ key: getCurrent30MinKey(), data: json }));
} catch (err) { } catch (err) {
setError(err.message || 'Unknown error'); setError(err.message || 'Unknown error');
} finally { } finally {
@@ -196,16 +197,16 @@ export default function UptimeStatusIsland() {
const minutes = now.getMinutes(); const minutes = now.getMinutes();
const seconds = now.getSeconds(); const seconds = now.getSeconds();
const ms = now.getMilliseconds(); const ms = now.getMilliseconds();
const next5 = Math.ceil((minutes + 0.01) / 5) * 5; const next30 = Math.ceil((minutes + 0.01) / 30) * 30;
let next = new Date(now); let next = new Date(now);
next.setMinutes(next5, 0, 0); next.setMinutes(next30, 0, 0);
if (next <= now) { if (next <= now) {
next.setMinutes(next.getMinutes() + 5); next.setMinutes(next.getMinutes() + 30);
} }
const msToNext = next - now; const msToNext = next - now;
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
fetchData(); fetchData();
const interval = setInterval(fetchData, 5 * 60 * 1000); const interval = setInterval(fetchData, 30 * 60 * 1000);
fetchData.interval = interval; fetchData.interval = interval;
}, msToNext); }, msToNext);
return () => { return () => {
@@ -246,7 +247,7 @@ export default function UptimeStatusIsland() {
return badgeRefs.current[monitorId][badge]; return badgeRefs.current[monitorId][badge];
}; };
const totalBarSeconds = 5 * 60; const totalBarSeconds = 30 * 60;
const barValue = secondsToNextUpdate !== null ? (totalBarSeconds - secondsToNextUpdate) : 0; const barValue = secondsToNextUpdate !== null ? (totalBarSeconds - secondsToNextUpdate) : 0;
const barPercent = (barValue / totalBarSeconds) * 100; const barPercent = (barValue / totalBarSeconds) * 100;
const barGradient = 'linear-gradient(90deg, #0161ef 0%, #0154cf 100%)'; const barGradient = 'linear-gradient(90deg, #0161ef 0%, #0154cf 100%)';
@@ -316,11 +317,11 @@ export default function UptimeStatusIsland() {
<div className="text-center text-red-500 dark:text-red-400">{error}</div> <div className="text-center text-red-500 dark:text-red-400">{error}</div>
) : data && data.publicGroupList && data.publicGroupList.length > 0 ? ( ) : data && data.publicGroupList && data.publicGroupList.length > 0 ? (
data.publicGroupList.map((group) => ( data.publicGroupList.map((group) => (
<section key={group.id} className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg p-8 flex flex-col"> <section key={group.id} className="bg-white/40 dark:bg-slate-800/40 backdrop-blur-md border border-gray-200 dark:border-slate-800 rounded-2xl shadow-lg p-8 flex flex-col">
<h2 className="text-2xl font-bold mb-6 text-gray-900 dark:text-white">{group.name}</h2> <h2 className="text-2xl font-bold mb-6 text-gray-900 dark:text-white">{group.name}</h2>
<ul className="space-y-6"> <ul className="space-y-6">
{group.monitorList.map((monitor) => ( {group.monitorList.map((monitor) => (
<li key={monitor.id} className="flex flex-col gap-2 bg-gray-50 dark:bg-slate-900 rounded-xl px-5 py-4 shadow border border-gray-200 dark:border-gray-700"> <li key={monitor.id} className="flex flex-col gap-2 rounded-xl px-5 py-4 shadow border border-gray-200 dark:border-gray-700">
{isMobile ? ( {isMobile ? (
<> <>
<div className="flex items-center min-w-0 mb-2"> <div className="flex items-center min-w-0 mb-2">

View File

@@ -126,7 +126,7 @@ const formatDate = (dateString) => {
{Array.isArray(userCommits) && userCommits.length > 0 ? ( {Array.isArray(userCommits) && userCommits.length > 0 ? (
<div class="space-y-4"> <div class="space-y-4">
{userCommits.map((commit) => ( {userCommits.map((commit) => (
<div class="bg-white/90 dark:bg-slate-900/90 p-6 rounded-2xl shadow-lg hover:shadow-xl transition-shadow duration-200 border border-gray-100 dark:border-slate-800 flex flex-col gap-4 md:flex-row md:items-stretch md:gap-8 mb-6"> <div class="bg-white/40 dark:bg-slate-800/40 backdrop-blur-md p-6 rounded-2xl shadow-lg hover:shadow-xl transition-shadow duration-200 border border-gray-200 dark:border-slate-800 flex flex-col gap-4 md:flex-row md:items-stretch md:gap-8 mb-6">
<div class="flex-1"> <div class="flex-1">
<h3 class="font-semibold text-lg md:text-xl text-gray-900 dark:text-white mb-1">{commit.message.split('\n')[0] || 'No message'}</h3> <h3 class="font-semibold text-lg md:text-xl text-gray-900 dark:text-white mb-1">{commit.message.split('\n')[0] || 'No message'}</h3>
{/* Format commit description with bullet points on new lines */} {/* Format commit description with bullet points on new lines */}

View File

@@ -43,11 +43,13 @@ const t = getTranslation(currentLang);
--- ---
<Layout> <Layout>
<main class="max-w-7xl mx-auto px-4 sm:px-6 py-12"> <main class="relative max-w-7xl mx-auto px-4 sm:px-6 py-12">
<div class="relative">
<div class="text-center mb-5"> <div class="text-center mb-5">
<h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">{t.uptime.title}</h1> <h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">{t.uptime.title}</h1>
<p class="text-lg text-gray-600 dark:text-gray-300">{t.uptime.subtitle}</p> <p class="text-lg text-gray-600 dark:text-gray-300">{t.uptime.subtitle}</p>
</div> </div>
<UptimeStatus /> <UptimeStatus />
</div>
</main> </main>
</Layout> </Layout>