mirror of
https://github.com/hubHarmony/servii-frontend.git
synced 2024-11-18 05:40:31 +00:00
Merge pull request #22 from hubHarmony/newdetails
New Server details form
This commit is contained in:
commit
d6709163ee
9
package-lock.json
generated
9
package-lock.json
generated
@ -19,6 +19,7 @@
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.3.0",
|
||||
"react-router-dom": "^6.24.0",
|
||||
"react-toastify": "^10.0.5",
|
||||
"sass": "^1.77.6",
|
||||
@ -9754,6 +9755,14 @@
|
||||
"react": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz",
|
||||
"integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
@ -22,6 +22,7 @@
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.3.0",
|
||||
"react-router-dom": "^6.24.0",
|
||||
"react-toastify": "^10.0.5",
|
||||
"sass": "^1.77.6",
|
||||
|
@ -33,7 +33,8 @@ const App = () => {
|
||||
<Routes>
|
||||
<Route path="/login" element={user ? <Navigate to="/dashboard" /> : <LoginPage />} />
|
||||
<Route path="/dashboard" element={user ? <DashboardPage user={user} /> : <Navigate to="/login" />} />
|
||||
<Route path="/server/:serverName" element={user ? <ServerDetails user={user} /> : <Navigate to="/login" />} />
|
||||
<Route path="/createServer" element={<Navigate />} />
|
||||
<Route path="/server/:serverName/*" element={user ? <ServerDetails user={user} /> : <Navigate to="/login" />} />
|
||||
<Route path="/" element={<Navigate to={user ? "/dashboard" : "/login"} />} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
|
@ -10,26 +10,10 @@ import spigot from '../../assets/frameworks/spigot.png';
|
||||
import paper from '../../assets/frameworks/paper.png';
|
||||
|
||||
const versions = {
|
||||
vanilla: ['1.21', '1.20', '1.19'],
|
||||
bukkit: [
|
||||
'1.15.0', '1.15.1', '1.15.2', '1.15.3', '1.15.4', '1.15.5',
|
||||
'1.16.0', '1.16.1', '1.16.2', '1.16.3', '1.16.4', '1.16.5',
|
||||
'1.17.0', '1.17.1', '1.17.2', '1.17.3', '1.17.4', '1.17.5',
|
||||
'1.18.1', '1.18.2',
|
||||
'1.19.1', '1.19.2', '1.19.3', '1.19.4',
|
||||
'1.20.1', '1.20.2', '1.20.4', '1.20.6'
|
||||
],
|
||||
spigot: ['1.21', '1.20'],
|
||||
paper: [
|
||||
'1.13.1', '1.13.2',
|
||||
'1.14.1', '1.14.2', '1.14.3', '1.14.4',
|
||||
'1.15.1', '1.15.2',
|
||||
'1.16.1', '1.16.2', '1.16.3', '1.16.4', '1.16.5',
|
||||
'1.17.1',
|
||||
'1.18.1', '1.18.2',
|
||||
'1.19.1', '1.19.2', '1.19.3', '1.19.4',
|
||||
'1.20.1', '1.20.2', '1.20.4', '1.20.5', '1.20.6'
|
||||
],
|
||||
vanilla:[ "1.21.1", "1.21", "1.20.6", "1.20.5", "1.20.4", "1.20.2", "1.20.1", "1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.18.2", "1.18.1", "1.17.1", "1.16.5", "1.16.4", "1.16.3", "1.16.2", "1.16.1", "1.15.2", "1.15.1", "1.14.4", "1.14.3", "1.14.2", "1.14.1", "1.13.2", "1.13.1", "1.12.2", "1.12.1", "1.11.2", "1.10.2", "1.9.4"],
|
||||
bukkit: [ "1.20.6", "1.20.4", "1.20.2", "1.20.1", "1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.18.2", "1.17.5", "1.17.4", "1.17.3", "1.17.2", "1.17.0", "1.16.5", "1.16.4", "1.16.3", "1.16.2", "1.16.1", "1.16.0", "1.15.5", "1.15.4", "1.15.3", "1.15.2", "1.15.1", "1.15.0", "1.14.5", "1.14.4", "1.14.3", "1.14.2", "1.14.1", "1.14.0", "1.13.5", "1.13.4", "1.13.3", "1.13.2", "1.13.1", "1.13.0", "1.12.5", "1.12.4", "1.12.3", "1.12.2", "1.12.1", "1.12.0", "1.11.5", "1.11.4", "1.11.3", "1.11.2", "1.11.1", "1.11.0", "1.10.5", "1.10.4", "1.10.3", "1.10.2", "1.10.1", "1.10.0", "1.9.5", "1.9.4", "1.9.3", "1.9.2", "1.9.1", "1.9.0", "1.8.5", "1.8.4", "1.8.3", "1.8.2", "1.8.1", "1.8.0", "1.7.5", "1.7.4", "1.7.3", "1.7.2", "1.7.1", "1.7.0", "1.6.5", "1.6.4", "1.6.3", "1.6.2", "1.6.1", "1.6.0", "1.5.5", "1.5.4", "1.5.3", "1.5.2", "1.5.1", "1.5.0", "1.4.5", "1.4.4", "1.4.3", "1.4.2", "1.4.1", "1.4.0", "1.3.5", "1.3.4", "1.3.3", "1.3.2", "1.3.1", "1.3.0", "1.2.5", "1.2.4", "1.2.3", "1.2.2", "1.2.1", "1.2.0", "1.1.5", "1.1.4", "1.1.3", "1.1.2", "1.1.1", "1.1.0", "1.0.5", "1.0.4", "1.0.3", "1.0.2", "1.0.1", "1.0.0"],
|
||||
spigot: [ "1.21", "1.20.6", "1.20.4", "1.20.2", "1.20.1", "1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.18.2", "1.18.1", "1.17.1", "1.16.5", "1.16.4", "1.16.3", "1.16.2", "1.16.1", "1.15.2", "1.15.1", "1.14.4", "1.14.3", "1.14.2", "1.14.1", "1.13.2", "1.13.1", "1.12.2", "1.12.1", "1.11.2", "1.11.1", "1.10.2", "1.9.4", "1.9.2", "1.8.8", "1.8.7", "1.8.6", "1.8.5", "1.8.4", "1.8.3", "1.7.10", "1.7.9", "1.7.8", "1.7.5", "1.7.2", "1.6.4", "1.6.2", "1.5.2", "1.5.1", "1.4.7", "1.4.6"],
|
||||
paper: [ "1.21.1", "1.21", "1.20.6", "1.20.5", "1.20.4", "1.20.2", "1.20.1", "1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.18.2", "1.18.1", "1.17.1", "1.16.5", "1.16.4", "1.16.3", "1.16.2", "1.16.1", "1.15.2", "1.15.1", "1.14.4", "1.14.3", "1.14.2", "1.14.1", "1.13.2", "1.13.1", "1.12.2", "1.12.1", "1.11.2", "1.10.2", "1.9.4"]
|
||||
};
|
||||
|
||||
const CreateServer = ({ user, onCreateServer, onSubdomainUpdate, onCancel, noServers }) => {
|
||||
@ -37,7 +21,7 @@ const CreateServer = ({ user, onCreateServer, onSubdomainUpdate, onCancel, noSer
|
||||
const [subdomainInput, setSubdomainInput] = useState('');
|
||||
const [serverName, setServerName] = useState('');
|
||||
const [serverVersion, setServerVersion] = useState();
|
||||
const [selectedFramework, setSelectedFramework] = useState("vanilla");
|
||||
const [selectedFramework, setSelectedFramework] = useState("paper");
|
||||
|
||||
const loadSubdomain = async () => {
|
||||
try {
|
||||
@ -69,11 +53,13 @@ const CreateServer = ({ user, onCreateServer, onSubdomainUpdate, onCancel, noSer
|
||||
|
||||
const handleCreateServer = async () => {
|
||||
try {
|
||||
await onCreateServer(serverName, serverVersion, selectedFramework);
|
||||
const frameworkToSend = selectedFramework === 'vanilla' ? 'paper' : selectedFramework;
|
||||
await onCreateServer(serverName, serverVersion, frameworkToSend);
|
||||
} catch (error) {
|
||||
console.error('Error creating server:', error);
|
||||
console.error('Error creating server:', error);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const validateInput = (input) => {
|
||||
return input.replace(/[^a-zA-Z]/g, '');
|
||||
@ -124,45 +110,56 @@ const CreateServer = ({ user, onCreateServer, onSubdomainUpdate, onCancel, noSer
|
||||
|
||||
<div className={styles.subtitle}>Sélection du framework</div>
|
||||
<div className={styles.carreContainer}>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'vanilla' ? styles.selected : ''}`}
|
||||
src={vanilla}
|
||||
alt="Vanilla Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('vanilla');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'bukkit' ? styles.selected : ''}`}
|
||||
src={bukkit}
|
||||
alt="Bukkit Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('bukkit');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'spigot' ? styles.selected : ''}`}
|
||||
src={spigot}
|
||||
alt="Spigot Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('spigot');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'paper' ? styles.selected : ''}`}
|
||||
src={paper}
|
||||
alt="Paper Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('paper');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.carreWrapper}>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'vanilla' ? styles.selected : ''}`}
|
||||
src={vanilla}
|
||||
alt="Vanilla Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('vanilla');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.subtitle}>Sélection de la version</div>
|
||||
<div className={styles.carreWrapper}>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'bukkit' ? styles.selected : ''}`}
|
||||
src={bukkit}
|
||||
alt="Bukkit Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('bukkit');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.carreWrapper}>
|
||||
<img
|
||||
className={`${styles.carre} ${selectedFramework === 'spigot' ? styles.selected : ''}`}
|
||||
src={spigot}
|
||||
alt="Spigot Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('spigot');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.carreWrapper}>
|
||||
<img
|
||||
className={`${styles.carre} ${styles.adviced} ${selectedFramework === 'paper' ? styles.selected : ''}`}
|
||||
src={paper}
|
||||
alt="Paper Logo"
|
||||
onClick={() => {
|
||||
setSelectedFramework('paper');
|
||||
setServerVersion('');
|
||||
}}
|
||||
/>
|
||||
<label className={styles.recommendationLabel}>Recommandé</label> {}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.subtitle}>Sélection de la version</div>
|
||||
|
||||
<select
|
||||
className={styles.select}
|
||||
|
@ -139,7 +139,13 @@
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 5rem;
|
||||
height: 6rem;
|
||||
}
|
||||
|
||||
.carreWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.carre {
|
||||
@ -160,6 +166,17 @@
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.adviced {
|
||||
border: 2px solid violet;
|
||||
}
|
||||
|
||||
.recommendationLabel {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 1rem;
|
||||
color: violet;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -35,7 +35,6 @@ const Navbar = ({ user }) => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('User data:', user);
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
|
@ -9,6 +9,7 @@ import PropTypes from "prop-types";
|
||||
|
||||
const ServerCard = ({ status, version, name, framework, onRunClick, onStopClick, onDeleteClick , countPlayers , maxPlayers}) => {
|
||||
|
||||
|
||||
const getFrameworkSource = () => {
|
||||
switch (framework) {
|
||||
case "bukkit":
|
||||
@ -50,7 +51,10 @@ const ServerCard = ({ status, version, name, framework, onRunClick, onStopClick,
|
||||
};
|
||||
|
||||
return (
|
||||
<Link to={`/server/${name}`} className={styles.serverCard}>
|
||||
<Link
|
||||
to={`/server/${name}/options`}
|
||||
className={styles.serverCard}
|
||||
state={{ status }}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.serverInfo}>
|
||||
<img src={getFrameworkSource()} alt={`${name} Icon`} className={styles.frameworkIcon} />
|
||||
|
@ -88,9 +88,7 @@ const DashboardPage = ({ user }) => {
|
||||
const handleCopyAddress = () => {
|
||||
const address = `${subdomain}.servii.fr`;
|
||||
navigator.clipboard.writeText(address)
|
||||
.then(() => {
|
||||
console.log('Address copied to clipboard');
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
|
133
src/pages/ServerConsole/ServerConsole.jsx
Normal file
133
src/pages/ServerConsole/ServerConsole.jsx
Normal file
@ -0,0 +1,133 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { FaExclamationCircle } from 'react-icons/fa';
|
||||
import styles from './ServerConsole.module.scss';
|
||||
import serviiApi from "../../service/api.tsx";
|
||||
import Loading from '../Loading/loading.jsx';
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ServerConsole = ({ user }) => {
|
||||
const navigate = useNavigate();
|
||||
const { serverName } = useParams();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [logs, setLogs] = useState('');
|
||||
const [message, setMessage] = useState('');
|
||||
const location = useLocation();
|
||||
const status = location.state?.status;
|
||||
|
||||
const logsEndRef = useRef(null);
|
||||
|
||||
const scrollToBottom = () => {
|
||||
logsEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
};
|
||||
|
||||
const fetchServerLogs = async () => {
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await serviiApi.fetchLogs(serverName);
|
||||
if (response.return_code === 200) {
|
||||
let logString = response.message;
|
||||
logString = logString.slice(1, -1);
|
||||
logString = logString.replace(/\\n/g, '\n');
|
||||
logString = logString.replace(/\\\"/g, '"');
|
||||
logString = logString.replace(/, ?/g, '');
|
||||
logString = logString.replace(/"{2,}/g, '');
|
||||
logString = logString.replace(/'{2,}/g, '');
|
||||
logString = logString.trim();
|
||||
setLogs(logString);
|
||||
} else {
|
||||
setError(`Erreur lors de la récupération des logs: ${response.message}`);
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Erreur: ${err.message}`);
|
||||
} finally {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchServerLogs();
|
||||
}, [serverName]);
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [logs]);
|
||||
|
||||
const handleSendMessage = async () => {
|
||||
if (message.trim() === "") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await serviiApi.command(message, serverName);
|
||||
setMessage('');
|
||||
fetchServerLogs();
|
||||
} catch (err) {
|
||||
setError(`Erreur lors de l'envoi de la commande : ${err.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className={styles.serverDetailsContainer}>
|
||||
<div className={styles.error}>
|
||||
<h1>{error}</h1>
|
||||
<button onClick={() => navigate('/dashboard')}>Retour au Dashboard</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.containerConsole}>
|
||||
<div className={styles.header}>
|
||||
Console {status ? '(En marche)' : '(Arrêté)'}
|
||||
</div>
|
||||
<div className={styles.logContainer}>
|
||||
{status ? (
|
||||
<>
|
||||
<pre className={styles.logs}>
|
||||
{logs}
|
||||
</pre>
|
||||
<div ref={logsEndRef} />
|
||||
</>
|
||||
) : (
|
||||
<div className={styles.offline}>
|
||||
<FaExclamationCircle style={{ marginRight: '.6rem' }} />
|
||||
<span>Serveur hors ligne</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.chatInputContainer}>
|
||||
<input
|
||||
type="text"
|
||||
className={styles.chatInput}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="Écrire un message..."
|
||||
/>
|
||||
<button className={styles.sendButton} onClick={handleSendMessage}>
|
||||
Envoyer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
ServerConsole.propTypes = {
|
||||
user: PropTypes.oneOfType([
|
||||
PropTypes.shape({
|
||||
uid: PropTypes.string.isRequired,
|
||||
}),
|
||||
]),
|
||||
};
|
||||
|
||||
export default ServerConsole;
|
99
src/pages/ServerConsole/ServerConsole.module.scss
Normal file
99
src/pages/ServerConsole/ServerConsole.module.scss
Normal file
@ -0,0 +1,99 @@
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: var(--navbar-height);
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.containerConsole {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
background-color: #100D25;
|
||||
width: 100%;
|
||||
max-width: 50rem;
|
||||
height: 38rem;
|
||||
overflow: hidden;
|
||||
border: .1rem solid #343947;
|
||||
padding: 0;
|
||||
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background-color: #1D1836;
|
||||
width: 100%;
|
||||
height: 3rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
border-bottom: .1rem solid #343947;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.logContainer {
|
||||
width: 100%;
|
||||
height: calc(100% - 6rem);
|
||||
overflow-y: auto;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.logs {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 0.9rem;
|
||||
color: #ffffff;
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.chatInputContainer {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
background-color: #1D1836;
|
||||
border-top: .1rem solid #343947;
|
||||
border-left: .1rem solid #343947;
|
||||
border-right: .1rem solid #343947;
|
||||
}
|
||||
|
||||
.chatInput {
|
||||
flex: 1;
|
||||
padding: 0.5rem;
|
||||
border: .1rem solid #343947;
|
||||
background-color: #2C2A3E;
|
||||
color: #ffffff;
|
||||
font-size: 0.9rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sendButton {
|
||||
margin-left: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: #3E3B59;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.sendButton:hover {
|
||||
background-color: #5A567E;
|
||||
}
|
||||
|
||||
|
||||
.offline {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 1.5rem;
|
||||
}
|
@ -1,155 +1,101 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useParams, useNavigate, Route, Routes, Link } from 'react-router-dom';
|
||||
import Navbar from '../../components/navbar/Navbar';
|
||||
import ServerProperties from '../ServerProperties/ServerProperties';
|
||||
import ServerConsole from '../ServerConsole/ServerConsole';
|
||||
// import ServerHistory from '../ServerHistory/ServerHistory';
|
||||
// import ServerPlayers from '../ServerPlayers/ServerPlayers';
|
||||
// import ServerWorlds from '../ServerWorlds/ServerWorlds';
|
||||
// import ServerBackups from '../ServerBackups/ServerBackups';
|
||||
// import ServerAccess from '../ServerAccess/ServerAccess';
|
||||
import styles from './ServerDetails.module.scss';
|
||||
import serviiApi from "../../service/api.tsx";
|
||||
import Loading from '../Loading/loading';
|
||||
import PropTypes from "prop-types";
|
||||
import { FaServer, FaCogs, FaUserFriends, FaGlobe, FaHistory, FaClipboardList, FaSave, FaLock } from 'react-icons/fa';
|
||||
import NotFoundPage from '../NotFoundPage/NotFoundPage';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
|
||||
const ServerDetails = ({ user }) => {
|
||||
const ServerDetails = ({ user }) => {
|
||||
const { serverName } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [server, setServer] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchServer = async () => {
|
||||
try {
|
||||
const ApiResponse = await serviiApi.fetchServers();
|
||||
const data = ApiResponse.message;
|
||||
const foundServer = data.find(server => server.name === serverName);
|
||||
|
||||
if (foundServer) {
|
||||
setServer(foundServer);
|
||||
} else {
|
||||
setError('Server not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching server:', error);
|
||||
setError('Error fetching server');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchServer();
|
||||
}, [serverName]);
|
||||
|
||||
const validateInput = (input) => {
|
||||
return input.replace(/[^a-zA-Z]/g, '');
|
||||
};
|
||||
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
const validatedValue = name === 'motd' ? validateInput(value) : value;
|
||||
setServer({ ...server, [name]: validatedValue });
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const props = [
|
||||
['max-players', server.maxPlayers.toString()],
|
||||
['motd', server.motd],
|
||||
['difficulty', server.difficulty],
|
||||
['enable-command-block', server.enableCommandBlock.toString()],
|
||||
['gamemode', server.gamemode.toString()],
|
||||
['hardcore', server.hardcore.toString()],
|
||||
['online-mode', server.onlineMode.toString()],
|
||||
['pvp', server.pvp.toString()]
|
||||
];
|
||||
|
||||
await serviiApi.updateProperties(server.name, props);
|
||||
} catch (error) {
|
||||
console.error('Error updating server:', error);
|
||||
alert('Error updating server');
|
||||
}
|
||||
handleQuit();
|
||||
};
|
||||
const location = useLocation();
|
||||
const status = location.state?.status;
|
||||
|
||||
const handleQuit = () => {
|
||||
navigate('/dashboard');
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className={styles.serverDetailsContainer}>
|
||||
<Navbar user={user} />
|
||||
<div className={styles.error}>
|
||||
<h1>{error}</h1>
|
||||
<button onClick={() => navigate('/dashboard')}>Retour au Dashboard</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.serverDetailsContainer}>
|
||||
<>
|
||||
<Navbar user={user} />
|
||||
<div className={styles.details}>
|
||||
<h1>Détails du serveur {server.name}</h1>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="difficulty">Difficultée:</label>
|
||||
<select id="difficulty" name="difficulty" value={server.difficulty} onChange={handleChange}>
|
||||
<option value="easy">Facile</option>
|
||||
<option value="normal">Normal</option>
|
||||
<option value="hard">Difficile</option>
|
||||
</select>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.sidebar}>
|
||||
<div className={styles.userinfo}>
|
||||
<div className={styles.user}>
|
||||
<p>{user.displayName}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.menu}>
|
||||
<NavLink
|
||||
to={`/server/${serverName}/options`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaCogs /> Propriétés
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
state={{ status }}
|
||||
to={`/server/${serverName}/console`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaClipboardList /> Console
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to={`/server/${serverName}/history`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaHistory /> Historique
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to={`/server/${serverName}/players`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaUserFriends /> Joueurs
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to={`/server/${serverName}/worlds`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaGlobe /> Mondes
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to={`/server/${serverName}/backups`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaSave /> Sauvegardes
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to={`/server/${serverName}/access`}
|
||||
className={({ isActive }) => isActive ? `${styles.menuItem} ${styles.active}` : styles.menuItem}>
|
||||
<FaLock /> Accès
|
||||
</NavLink>
|
||||
</div>
|
||||
<button className={styles.BackButton} onClick={handleQuit}>Retour</button>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="enableCommandBlock">Activation des commandes block:</label>
|
||||
<select id="enableCommandBlock" name="enableCommandBlock" value={server.enableCommandBlock} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
<div className={styles.serverDetailsContainer}>
|
||||
<Routes>
|
||||
<Route path="options" element={<ServerProperties user={user} status={status} />} />
|
||||
<Route path="console" element={<ServerConsole user={user} status={status} />} />
|
||||
<Route path="history" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} />
|
||||
<Route path="players" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} />
|
||||
<Route path="worlds" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} />
|
||||
<Route path="backups" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} />
|
||||
<Route path="access" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="gamemode">Gamemode:</label>
|
||||
<select id="gamemode" name="gamemode" value={server.gamemode} onChange={handleChange}>
|
||||
<option value="survival">Survie</option>
|
||||
<option value="creative">Créatif</option>
|
||||
<option value="adventure">Aventure</option>
|
||||
<option value="spectator">Spectateur</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="hardcore">Hardcore:</label>
|
||||
<select id="hardcore" name="hardcore" value={server.hardcore} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="maxPlayers">Max de joueurs:</label>
|
||||
<input type="number" id="maxPlayers" name="maxPlayers" value={server.maxPlayers} onChange={handleChange} />
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="motd">Description du serveur:</label>
|
||||
<input type="text" id="motd" name="motd" value={server.motd} onChange={handleChange} />
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="onlineMode">Mode en ligne:</label>
|
||||
<select id="onlineMode" name="onlineMode" value={server.onlineMode} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="pvp">PVP:</label>
|
||||
<select id="pvp" name="pvp" value={server.pvp} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<button className={styles.saveButton} onClick={handleSave}>Sauvegarder et quitter</button>
|
||||
<button className={styles.quitButton} onClick={handleQuit}>Retour</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -162,4 +108,5 @@ ServerDetails.propTypes = {
|
||||
}),
|
||||
]),
|
||||
};
|
||||
|
||||
export default ServerDetails;
|
||||
|
@ -1,133 +1,114 @@
|
||||
.container {
|
||||
display: flex;
|
||||
min-height: calc(100vh - var(--navbar-height));
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 20rem;
|
||||
background-color: #100D25;
|
||||
padding: 2rem 1rem;
|
||||
padding-left: 0rem;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
height: calc(100vh - var(--navbar-height));
|
||||
top: var(--navbar-height);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menuItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.7rem 1rem ;
|
||||
margin: .5rem 0rem;
|
||||
padding-right: 0rem;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
color: #D1D5DB;
|
||||
text-decoration: none;
|
||||
width: 100%;
|
||||
&.active {
|
||||
background-color: #1D1836;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.menuItem:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.user {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.user p {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user small {
|
||||
font-size: 0.875rem;
|
||||
color: #9CA3AF;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.menuItem:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menuItem svg {
|
||||
margin-right: 1rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.BackButton {
|
||||
margin-top: 1rem;
|
||||
padding: 0.70rem 1.5rem;
|
||||
background-color: #1D1836;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
width: 20rem;
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
|
||||
}
|
||||
|
||||
.serverDetailsContainer {
|
||||
padding-top: var(--navbar-height);
|
||||
margin-top: var(--navbar-height);
|
||||
flex: 1;
|
||||
margin-left: 20rem;
|
||||
padding-top: 1rem;
|
||||
background-color: var(--main-bg-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: var(--text-color);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-top: 5rem;
|
||||
padding: 3rem;
|
||||
padding-top: 0;
|
||||
background-color: var(--card-bg-color);
|
||||
|
||||
.navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-width: 60rem;
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
height: var(--navbar-height);
|
||||
background-color: var(--navbar-bg-color);
|
||||
z-index: 1000;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
margin-bottom: 2.5rem;
|
||||
.userinfo {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.formGroup label {
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.4rem;
|
||||
color: var(--label-color);
|
||||
}
|
||||
|
||||
.formGroup input,
|
||||
.formGroup select {
|
||||
width: 100%;
|
||||
padding: 1.2rem;
|
||||
height: auto;
|
||||
background-color: var(--input-bg-color);
|
||||
border: 1px solid var(--input-border-color);
|
||||
border-radius: 0.75rem;
|
||||
color: var(--text-color);
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.5rem;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.formGroup input:focus,
|
||||
.formGroup select:focus {
|
||||
border-color: var(--focus-border-color);
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Chrome- styles */
|
||||
@supports (-webkit-appearance: none) {
|
||||
.formGroup select {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg fill="%23ddd" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/></svg>');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 1.2rem center;
|
||||
background-size: 1rem;
|
||||
padding-right: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.saveButton,
|
||||
.quitButton {
|
||||
padding: 1.2rem 2.5rem;
|
||||
color: var(--button-text-color);
|
||||
border: none;
|
||||
border-radius: 0.75rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, transform 0.3s ease;
|
||||
font-size: 1.2rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.saveButton {
|
||||
background-color: #05a771;
|
||||
}
|
||||
|
||||
.saveButton:hover {
|
||||
background-color: #05a77183;
|
||||
}
|
||||
|
||||
.quitButton {
|
||||
background-color: gray;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.details h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 3rem;
|
||||
color: var(--header-color);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.details {
|
||||
width: 90%;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.formGroup input,
|
||||
.formGroup select {
|
||||
height: auto;
|
||||
font-size: 1.1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.saveButton,
|
||||
.quitButton {
|
||||
padding: 1rem 2rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.details h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
156
src/pages/ServerProperties/ServerProperties.jsx
Normal file
156
src/pages/ServerProperties/ServerProperties.jsx
Normal file
@ -0,0 +1,156 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import styles from './ServerProperties.module.scss';
|
||||
import serviiApi from "../../service/api.tsx";
|
||||
import Loading from '../Loading/loading';
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ServerProprieties = ({ user }) => {
|
||||
const { serverName } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [server, setServer] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchServer = async () => {
|
||||
try {
|
||||
const ApiResponse = await serviiApi.fetchServers();
|
||||
const data = ApiResponse.message;
|
||||
const foundServer = data.find(server => server.name === serverName);
|
||||
|
||||
if (foundServer) {
|
||||
setServer(foundServer);
|
||||
} else {
|
||||
setError('Server not found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching server:', error);
|
||||
setError('Error fetching server');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchServer();
|
||||
}, [serverName]);
|
||||
|
||||
const validateInput = (input) => {
|
||||
return input.replace(/[^a-zA-Z]/g, '');
|
||||
};
|
||||
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
const validatedValue = name === 'motd' ? validateInput(value) : value;
|
||||
setServer({ ...server, [name]: validatedValue });
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const props = [
|
||||
['max-players', server.maxPlayers.toString()],
|
||||
['motd', server.motd],
|
||||
['difficulty', server.difficulty],
|
||||
['enable-command-block', server.enableCommandBlock.toString()],
|
||||
['gamemode', server.gamemode.toString()],
|
||||
['hardcore', server.hardcore.toString()],
|
||||
['online-mode', server.onlineMode.toString()],
|
||||
['pvp', server.pvp.toString()]
|
||||
];
|
||||
|
||||
await serviiApi.updateProperties(server.name, props);
|
||||
} catch (error) {
|
||||
console.error('Error updating server:', error);
|
||||
alert('Error updating server');
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className={styles.serverDetailsContainer}>
|
||||
<div className={styles.error}>
|
||||
<h1>{error}</h1>
|
||||
<button onClick={() => navigate('/dashboard')}>Retour au Dashboard</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.serverDetailsContainer}>
|
||||
<div className={styles.details}>
|
||||
<h1>Propriétés du serveur {server.name}</h1>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="difficulty">Difficultée:</label>
|
||||
<select id="difficulty" name="difficulty" value={server.difficulty} onChange={handleChange}>
|
||||
<option value="easy">Facile</option>
|
||||
<option value="normal">Normal</option>
|
||||
<option value="hard">Difficile</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="enableCommandBlock">Activation des commandes block:</label>
|
||||
<select id="enableCommandBlock" name="enableCommandBlock" value={server.enableCommandBlock} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="gamemode">Gamemode:</label>
|
||||
<select id="gamemode" name="gamemode" value={server.gamemode} onChange={handleChange}>
|
||||
<option value="survival">Survie</option>
|
||||
<option value="creative">Créatif</option>
|
||||
<option value="adventure">Aventure</option>
|
||||
<option value="spectator">Spectateur</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="hardcore">Hardcore:</label>
|
||||
<select id="hardcore" name="hardcore" value={server.hardcore} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="maxPlayers">Max de joueurs:</label>
|
||||
<input type="number" id="maxPlayers" name="maxPlayers" value={server.maxPlayers} onChange={handleChange} />
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="motd">Description du serveur:</label>
|
||||
<input type="text" id="motd" name="motd" value={server.motd} onChange={handleChange} />
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="onlineMode">Mode en ligne:</label>
|
||||
<select id="onlineMode" name="onlineMode" value={server.onlineMode} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="pvp">PVP:</label>
|
||||
<select id="pvp" name="pvp" value={server.pvp} onChange={handleChange}>
|
||||
<option value="true">Activé</option>
|
||||
<option value="false">Désactivé</option>
|
||||
</select>
|
||||
</div>
|
||||
<button className={styles.saveButton} onClick={handleSave}>Sauvegarder</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ServerProprieties.propTypes = {
|
||||
user: PropTypes.oneOfType([
|
||||
PropTypes.shape({
|
||||
uid: PropTypes.string.isRequired,
|
||||
displayName: PropTypes.string,
|
||||
email: PropTypes.string,
|
||||
}),
|
||||
]),
|
||||
};
|
||||
|
||||
export default ServerProprieties;
|
133
src/pages/ServerProperties/ServerProperties.module.scss
Normal file
133
src/pages/ServerProperties/ServerProperties.module.scss
Normal file
@ -0,0 +1,133 @@
|
||||
.serverDetailsContainer {
|
||||
padding-top: var(--navbar-height);
|
||||
background-color: var(--main-bg-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: var(--text-color);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.details {
|
||||
padding: 3rem;
|
||||
padding-top: 0;
|
||||
background-color: var(--card-bg-color);
|
||||
width: 100%;
|
||||
max-width: 60rem;
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
margin-bottom: 2.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.formGroup label {
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.4rem;
|
||||
color: var(--label-color);
|
||||
}
|
||||
|
||||
.formGroup input,
|
||||
.formGroup select {
|
||||
width: 100%;
|
||||
padding: 1.2rem;
|
||||
height: auto;
|
||||
background-color: var(--input-bg-color);
|
||||
border: 1px solid var(--input-border-color);
|
||||
border-radius: 0.75rem;
|
||||
color: var(--text-color);
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.5rem;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.formGroup input:focus,
|
||||
.formGroup select:focus {
|
||||
border-color: var(--focus-border-color);
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Chrome- styles */
|
||||
@supports (-webkit-appearance: none) {
|
||||
.formGroup select {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg fill="%23ddd" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/></svg>');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 1.2rem center;
|
||||
background-size: 1rem;
|
||||
padding-right: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.saveButton,
|
||||
.quitButton {
|
||||
padding: 1.2rem 2.5rem;
|
||||
color: var(--button-text-color);
|
||||
border: none;
|
||||
border-radius: 0.75rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, transform 0.3s ease;
|
||||
font-size: 1.2rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.saveButton {
|
||||
background-color: #05a771;
|
||||
}
|
||||
|
||||
.saveButton:hover {
|
||||
background-color: #05a77183;
|
||||
}
|
||||
|
||||
.quitButton {
|
||||
background-color: gray;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.details h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 3rem;
|
||||
color: var(--header-color);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.details {
|
||||
width: 90%;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.formGroup input,
|
||||
.formGroup select {
|
||||
height: auto;
|
||||
font-size: 1.1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.saveButton,
|
||||
.quitButton {
|
||||
padding: 1rem 2rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.details h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,15 @@ enum serviiRequest {
|
||||
serverStop = 'ServerStop',
|
||||
updateProperty = 'UpdateProperties',
|
||||
command = 'Command',
|
||||
fetchLogs = 'FetchLogs',
|
||||
}
|
||||
|
||||
|
||||
const nonToastableCalls: string[] = [
|
||||
serviiRequest.fetchServers,
|
||||
serviiRequest.fetchLogs,
|
||||
];
|
||||
|
||||
class serviiApi {
|
||||
constructor() {}
|
||||
|
||||
@ -65,33 +72,35 @@ class serviiApi {
|
||||
|
||||
if (json.message === undefined) {
|
||||
if (!(endpoint === serviiRequest.fetchServers)) {
|
||||
return { return_code: status, message: "Couldn't find an available API, we're sorry for the inconvenience." };
|
||||
return { return_code: status, message: "Couldn't find an available API" };
|
||||
}
|
||||
return { return_code: status, message: json };
|
||||
}
|
||||
|
||||
let toastType: 'success' | 'error' | 'info';
|
||||
let toastColor: string;
|
||||
if (!nonToastableCalls.includes(endpoint)) {
|
||||
|
||||
if (status >= 200 && status < 300) {
|
||||
toastType = 'success';
|
||||
} else if (status >= 400 && status < 600) {
|
||||
toastType = 'error';
|
||||
} else {
|
||||
toastType = 'info';
|
||||
}
|
||||
let toastType: 'success' | 'error' | 'info';
|
||||
|
||||
toast[toastType](json.message, {
|
||||
position: "top-right",
|
||||
autoClose: 3500,
|
||||
hideProgressBar: false,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
theme: "light",
|
||||
transition: Bounce,
|
||||
});
|
||||
if (status >= 200 && status < 300) {
|
||||
toastType = 'success';
|
||||
} else if (status >= 400 && status < 600) {
|
||||
toastType = 'error';
|
||||
} else {
|
||||
toastType = 'info';
|
||||
}
|
||||
|
||||
toast[toastType](json.message, {
|
||||
position: "top-right",
|
||||
autoClose: 3500,
|
||||
hideProgressBar: false,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
theme: "light",
|
||||
transition: Bounce,
|
||||
});
|
||||
}
|
||||
|
||||
return { return_code: status, message: json.message };
|
||||
}
|
||||
@ -114,6 +123,11 @@ class serviiApi {
|
||||
return this.call(serviiRequest.fetchServers, payload);
|
||||
}
|
||||
|
||||
public static async fetchLogs(name: string): Promise<ApiResponse> {
|
||||
const payload: ServerRequest = { token: this.token(), name: name };
|
||||
return this.call(serviiRequest.fetchLogs, payload);
|
||||
}
|
||||
|
||||
public static async accountCreate(): Promise<ApiResponse> {
|
||||
const payload: BaseRequest = { token: this.token() };
|
||||
return this.call(serviiRequest.accountCreate, payload);
|
||||
@ -150,7 +164,7 @@ class serviiApi {
|
||||
name: name,
|
||||
props: props,
|
||||
};
|
||||
return this.call(serviiRequest.updateProperty, payload); // Correct usage here
|
||||
return this.call(serviiRequest.updateProperty, payload);
|
||||
}
|
||||
|
||||
public static async command(command: string, name: string): Promise<ApiResponse> {
|
||||
|
Loading…
Reference in New Issue
Block a user