Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 101 additions & 1 deletion frontend/src/components/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useNavigate } from "react-router-dom";
import { copyToClipboard } from "../utils/clipboardUtils";
import UserTable from "./UserTable";
import Button from "./Button";
import { apiJwt, setAuthToken } from "../api";
import { apiJwt, setAuthToken, api, apiStatus } from "../api";
import "../styles/Minecraft.css";
import TitleImage from "./TitleImage";

Expand Down Expand Up @@ -36,9 +36,78 @@ function Dashboard() {
const [invitationCode, setInvitationCode] = useState<string | null>(null);
const [isCopied, setIsCopied] = useState(false);
const [error, setError] = useState<string | null>(null);
const [serverStatus, setServerStatus] = useState<string>("");

const invitationCodeRef = useRef<HTMLInputElement>(null);

// Function to fetch server status
const fetchServerStatus = () => {
// Try backend API status endpoint first, fallback to direct status service
api.get('/api/status')
.then(response => setServerStatus(response.data.status))
.catch(() => {
// Fallback to direct status service if backend proxy is unavailable
if (process.env.REACT_APP_STATUS_API_URL) {
apiStatus.get('/status')
.then(response => setServerStatus(response.data.status))
.catch(() => {
setServerStatus("Error fetching status");
});
} else {
setServerStatus("Error fetching status");
}
});
};

const startClick = () => {
console.log('WakeUp');
// Try backend API wakeup endpoint first, fallback to direct status service
api.post('/api/status/wakeup', {})
.then((response) => {
console.log('WakeUp Success', response);
// Update status immediately after wake-up attempt
fetchServerStatus();
})
.catch(() => {
// Fallback to direct status service if backend proxy is unavailable
if (process.env.REACT_APP_STATUS_API_URL) {
apiStatus.post('/wakeup', {})
.then((response) => {
console.log('WakeUp Success (direct)', response);
// Update status immediately after wake-up attempt
fetchServerStatus();
})
.catch((error) => {
console.log('WakeUp Error', error);
});
} else {
console.log('WakeUp Error: No status service URL configured');
}
});
};

const getTexts = (status: string) => {
let emoji = '❌'
let buttonText = status;
switch (status) {
case 'Running':
emoji = '🟩'
buttonText = 'Server is running'
break;
case 'Sleeping':
emoji = '🟥'
buttonText = "Wake Up Server"
break;
case 'Starting':
emoji = '🟧'
buttonText = '...Waiting...'
break;
}
return { emoji, buttonText };
};

const serverStatusLink = process.env.REACT_APP_SERVER_STATUS_URL;

const generateCode = async () => {
try {
const response = await apiJwt.post("/api/invitation/generate-invitation-code");
Expand Down Expand Up @@ -72,6 +141,19 @@ function Dashboard() {
useEffect(() => {
const url = window.location.host;
document.title = `Admin Dashboard - ${url}`;

// Fetch status immediately
fetchServerStatus();

// Set up polling to fetch status every 5 seconds
const statusInterval = setInterval(() => {
fetchServerStatus();
}, 5000); // Poll every 5 seconds

// Cleanup interval on unmount
return () => {
clearInterval(statusInterval);
};
}, []);

return (
Expand All @@ -94,6 +176,17 @@ function Dashboard() {
/>
</div>
)}
<button className="item full server-status-btn" onClick={serverStatus === "Error fetching status" ? undefined : startClick}>
<div className="title">
{serverStatus === "Error fetching status" ? (
"Error fetching status"
) : (
<div className="standard-text">
{getTexts(serverStatus).buttonText}
</div>
)}
</div>
</button>
<div className="double">
<Button className="item" onClick={generateCode} type="button">
<div className="title">
Expand All @@ -106,6 +199,13 @@ function Dashboard() {
</div>
</Button>
</div>
{serverStatusLink && (
<div className="item full lang">
<a className="standard-text title" href={serverStatusLink} target="_blank" rel="noopener noreferrer">
{getTexts(serverStatus).emoji}
</a>
</div>
)}
</div>
</div>
);
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/styles/Minecraft.css
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,16 @@ grid-gap: 8px;
grid-template-areas:
'. first .'
'. second .'
'. . .'
'lang fourth .'
;
grid-gap: 8px;
}
.menu-dashboard :nth-child(1) {grid-area: first;}
.menu-dashboard .server-status-btn {grid-area: first;}
.menu-dashboard .double {grid-area: second;}
.menu-dashboard .double :nth-child(1) {grid-area: left;}
.menu-dashboard .double :nth-child(2) {grid-area: right;}
.menu-dashboard .lang {grid-area: lang;}

.title {
align-items: center;
Expand Down