This commit is contained in:
AntoninoP 2024-09-01 19:51:13 +02:00
parent c66fdf4842
commit d5eb9345ae
5 changed files with 262 additions and 5 deletions

View File

@ -0,0 +1,202 @@
import styles from './PlayersStatus.module.scss';
import serviiApi from "../../service/api.tsx";
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
const PlayerStatus = () => {
const { serverName } = useParams();
const [whiteListUsername, setWhiteListUsername] = useState('');
const [adminUsername, setAdminUsername] = useState('');
const [banUsername, setBanUsername] = useState('');
const [banipUsername, setBanipUsername] = useState('');
const [whitelist, setWhitelist] = useState([]);
const [operators, setOperators] = useState([]);
const [bannedPlayers, setBannedPlayers] = useState([]);
const [bannedIps, setBannedIps] = useState([]);
const loadPlayersStatus = async () => {
try {
const ApiResponse = await serviiApi.fetchPlayersStatus(serverName);
console.log("API Response:", ApiResponse);
const cleanAndParse = (data) => {
if (data) {
const cleanedData = data.replace(/\\n/g, '').replace(/\\r/g, '');
return tryParseJSON(cleanedData);
}
return [];
}
const parsedWhitelist = cleanAndParse(ApiResponse.message.Whitelist);
const parsedOperators = cleanAndParse(ApiResponse.message.Operators);
const parsedBannedPlayers = cleanAndParse(ApiResponse.message.BannedPlayers);
const parsedBannedIps = cleanAndParse(ApiResponse.message.BannedIps);
setWhitelist(parsedWhitelist || []);
setOperators(parsedOperators || []);
setBannedPlayers(parsedBannedPlayers || []);
setBannedIps(parsedBannedIps || []);
} catch (error) {
console.error('Error fetching data:', error);
}
}
const tryParseJSON = (jsonString) => {
try {
return JSON.parse(jsonString);
} catch (e) {
console.warn("Could not parse JSON: ", jsonString);
return [];
}
};
const handlePlayerStatus = async (username, commandType, clearInput) => {
try {
await AddPlayerStatus(username, commandType);
clearInput();
loadPlayersStatus();
} catch (error) {
console.error('Error adding a player status:', error);
}
}
const AddPlayerStatus = async (username, commandType) => {
let serverCommande = '';
try {
switch (commandType) {
case 'whiteList':
serverCommande = `whitelist add ${username}`;
break;
case 'admin':
serverCommande = `op ${username}`;
break;
case 'ban':
serverCommande = `ban ${username}`;
break;
case 'banip':
serverCommande = `banip ${username}`;
break;
default:
break;
}
await serviiApi.command(serverCommande, serverName);
} catch (error) {
console.error('Error adding a player status:', error);
}
}
useEffect(() => {
loadPlayersStatus();
}, []); // Dependency array added
return (
<div className={styles.container}>
<div>
<div className={styles.titlesection}>Liste Blanche</div>
<div className={styles.inputSection}>
<input
type="text"
placeholder="Nom d'utilisateur"
value={whiteListUsername}
onChange={(e) => setWhiteListUsername(e.target.value)}
/>
<button
className={styles.sendButton}
onClick={() => handlePlayerStatus(whiteListUsername, 'whiteList', () => setWhiteListUsername(''))}
>
Envoyer
</button>
</div>
<div className={styles.playerList}>
{whitelist.length > 0 ? (
whitelist.map(player => <div key={player.uuid}>{player.name}</div>)
) : (
<div>Aucun joueur dans la liste blanche</div>
)}
</div>
</div>
<div>
<div className={styles.titlesection}>Admins</div>
<div className={styles.inputSection}>
<input
type="text"
placeholder="Nom d'utilisateur"
value={adminUsername}
onChange={(e) => setAdminUsername(e.target.value)}
/>
<button
className={styles.sendButton}
onClick={() => handlePlayerStatus(adminUsername, 'admin', () => setAdminUsername(''))}
>
Envoyer
</button>
</div>
<div className={styles.playerList}>
{operators.length > 0 ? (
operators.map(player => <div key={player.uuid}>{player.name}</div>)
) : (
<div>Aucun administrateur</div>
)}
</div>
</div>
<div>
<div className={styles.titlesection}>Joueurs bannis</div>
<div className={styles.inputSection}>
<input
type="text"
placeholder="Nom d'utilisateur"
value={banUsername}
onChange={(e) => setBanUsername(e.target.value)}
/>
<button
className={styles.sendButton}
onClick={() => handlePlayerStatus(banUsername, 'ban', () => setBanUsername(''))}
>
Envoyer
</button>
</div>
<div className={styles.playerList}>
{bannedPlayers.length > 0 ? (
bannedPlayers.map(player => <div key={player.uuid}>{player.name}</div>)
) : (
<div>Aucun joueur banni</div>
)}
</div>
</div>
<div>
<div className={styles.titlesection}>IP bannies</div>
<div className={styles.inputSection}>
<input
type="text"
placeholder="Nom d'utilisateur"
value={banipUsername}
onChange={(e) => setBanipUsername(e.target.value)}
/>
<button
className={styles.sendButton}
onClick={() => handlePlayerStatus(banipUsername, 'banip', () => setBanipUsername(''))}
>
Envoyer
</button>
</div>
<div className={styles.playerList}>
{bannedIps.length > 0 ? (
bannedIps.map(ip => <div key={ip}>{ip}</div>)
) : (
<div>Aucune IP bannie</div>
)}
</div>
</div>
</div>
);
}
export default PlayerStatus;

View File

@ -0,0 +1,37 @@
.container {
margin-top: calc(var(--navbar-height) - .5rem);
width: 45rem;
display: flex;
justify-content: start;
flex-direction: column;
}
.inputSection {
display: flex;
align-items: center;
margin-top: .5rem;
}
input {
border: 1px solid var(--primary-color);
font-size: 1.5rem;
padding: .5rem;
flex: 1;
}
.sendButton {
margin-left: .5rem;
padding: .5rem 1rem;
font-size: 1.5rem;
background-color: blue;
color: white;
border: none;
cursor: pointer;
}
.titlesection {
font-size: 2rem;
font-weight: 400;
margin-top: 3rem;
}

View File

@ -0,0 +1,10 @@
const FeatureSoon = () => {
return (
<div>
<h1>Cette fonctionnalitée sera prochainement disponible</h1>
</div>
);
}
export default FeatureSoon;

View File

@ -4,10 +4,11 @@ import Navbar from '../../components/navbar/Navbar';
import ServerProperties from '../ServerProperties/ServerProperties'; import ServerProperties from '../ServerProperties/ServerProperties';
import ServerConsole from '../ServerConsole/ServerConsole'; import ServerConsole from '../ServerConsole/ServerConsole';
import ServerHistory from '../ServerHistory/ServerHistory'; import ServerHistory from '../ServerHistory/ServerHistory';
// import ServerPlayers from '../ServerPlayers/ServerPlayers'; import PlayerStatus from '../PlayersStatus/PlayersStatus';
// import ServerWorlds from '../ServerWorlds/ServerWorlds'; // import ServerWorlds from '../ServerWorlds/ServerWorlds';
// import ServerBackups from '../ServerBackups/ServerBackups'; // import ServerBackups from '../ServerBackups/ServerBackups';
// import ServerAccess from '../ServerAccess/ServerAccess'; // import ServerAccess from '../ServerAccess/ServerAccess';
import FeatureSoon from './FeatureSoon';
import styles from './ServerDetails.module.scss'; import styles from './ServerDetails.module.scss';
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { FaCogs, FaUserFriends, FaGlobe, FaHistory, FaClipboardList, FaSave, FaLock } from 'react-icons/fa'; import { FaCogs, FaUserFriends, FaGlobe, FaHistory, FaClipboardList, FaSave, FaLock } from 'react-icons/fa';
@ -97,10 +98,10 @@ const ServerDetails = ({ user }) => {
<Route path="options" element={<ServerProperties user={user} status={status} />} /> <Route path="options" element={<ServerProperties user={user} status={status} />} />
<Route path="console" element={<ServerConsole user={user} status={status} />} /> <Route path="console" element={<ServerConsole user={user} status={status} />} />
<Route path="history" element={<ServerHistory user={user} status={status} />} /> <Route path="history" element={<ServerHistory user={user} status={status} />} />
<Route path="players" element={<h2 >Cette fonctionnalité sera prochainement disponible.</h2>} /> <Route path="players" element={<PlayerStatus user={user} status={status} />} />
<Route path="worlds" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} /> <Route path="worlds" element={<FeatureSoon user={user} status={status}/>} />
<Route path="backups" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} /> <Route path="backups" element={<FeatureSoon user={user} status={status}/>} />
<Route path="access" element={<h2>Cette fonctionnalité sera prochainement disponible.</h2>} /> <Route path="access" element={<FeatureSoon user={user} status={status}/>}/>
<Route path="*" element={<NotFoundPage />} /> <Route path="*" element={<NotFoundPage />} />
</Routes> </Routes>
</div> </div>

View File

@ -49,12 +49,14 @@ enum serviiRequest {
command = 'Command', command = 'Command',
fetchLogs = 'FetchLogs', fetchLogs = 'FetchLogs',
fetchHistory = 'FetchHistory', fetchHistory = 'FetchHistory',
fetchPlayersStatus = 'FetchPlayersStatus',
} }
const nonToastableCalls: string[] = [ const nonToastableCalls: string[] = [
serviiRequest.fetchServers, serviiRequest.fetchServers,
serviiRequest.fetchLogs, serviiRequest.fetchLogs,
serviiRequest.fetchHistory, serviiRequest.fetchHistory,
serviiRequest.fetchPlayersStatus,
]; ];
class serviiApi { class serviiApi {
@ -134,6 +136,11 @@ class serviiApi {
return this.call(serviiRequest.fetchHistory, payload); return this.call(serviiRequest.fetchHistory, payload);
} }
public static async fetchPlayersStatus(name: string): Promise<ApiResponse> {
const payload: ServerRequest = { token: this.token(), name: name,};
return this.call(serviiRequest.fetchPlayersStatus, payload);
}
public static async accountCreate(): Promise<ApiResponse> { public static async accountCreate(): Promise<ApiResponse> {
const payload: BaseRequest = { token: this.token() }; const payload: BaseRequest = { token: this.token() };
return this.call(serviiRequest.accountCreate, payload); return this.call(serviiRequest.accountCreate, payload);