mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-02-09 17:01:58 +01:00
Implemented player list to server page
Holy moly was it a big fight to get DataTables to cooperate
This commit is contained in:
parent
71424fa2ec
commit
df0c0fa8a5
@ -4,6 +4,7 @@
|
||||
"private": true,
|
||||
"proxy": "https://localhost:8804",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.1.1",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.1.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||
@ -17,6 +18,9 @@
|
||||
"@testing-library/user-event": "^13.2.1",
|
||||
"axios": "^0.26.1",
|
||||
"bootstrap": "^5.1.3",
|
||||
"datatables.net": "^1.12.1",
|
||||
"datatables.net-bs5": "^1.12.1",
|
||||
"datatables.net-responsive-bs5": "^2.3.0",
|
||||
"highcharts": "^9.3.2",
|
||||
"i18next": "^21.6.14",
|
||||
"i18next-chained-backend": "^3.0.2",
|
||||
|
@ -24,6 +24,7 @@ import OnlineActivity from "./views/server/OnlineActivity";
|
||||
import ServerSessions from "./views/server/ServerSessions";
|
||||
import ServerPvpPve from "./views/server/ServerPvpPve";
|
||||
import PlayerbaseOverview from "./views/server/PlayerbaseOverview";
|
||||
import ServerPlayers from "./views/server/ServerPlayers";
|
||||
|
||||
const OverviewRedirect = () => {
|
||||
return (<Navigate to={"overview"} replace={true}/>)
|
||||
@ -72,7 +73,7 @@ function App() {
|
||||
<Route path="pvppve" element={<ServerPvpPve/>}/>
|
||||
<Route path="playerbase" element={<PlayerbaseOverview/>}/>
|
||||
<Route path="retention" element={<></>}/>
|
||||
<Route path="players" element={<></>}/>
|
||||
<Route path="players" element={<ServerPlayers/>}/>
|
||||
<Route path="geolocations" element={<></>}/>
|
||||
<Route path="performance" element={<></>}/>
|
||||
<Route path="plugins-overview" element={<></>}/>
|
||||
|
@ -0,0 +1,41 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||
import DataTablesTable from "../../table/DataTablesTable";
|
||||
import {CardLoader} from "../../navigation/Loader";
|
||||
|
||||
const PlayerListCard = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
const [options, setOptions] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
for (const row of data.data) {
|
||||
row.name = row.name.replace('../player/', '../../player/');
|
||||
}
|
||||
|
||||
setOptions({
|
||||
responsive: true,
|
||||
deferRender: true,
|
||||
columns: data.columns,
|
||||
data: data?.data,
|
||||
order: [[5, "desc"]]
|
||||
});
|
||||
}, [data])
|
||||
|
||||
if (!options) return <CardLoader/>
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black">
|
||||
<Fa icon={faUsers} className="col-black"/> {t('html.label.playerList')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<DataTablesTable id={"players-table"} options={options}/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default PlayerListCard;
|
@ -10,8 +10,8 @@ import {faGamepad, faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||
import {faClock} from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
const SessionInsightsCard = () => {
|
||||
const {identifier} = useParams();
|
||||
const {t} = useTranslation();
|
||||
const {identifier} = useParams();
|
||||
|
||||
const {data, loadingError} = useDataRequest(fetchSessionOverview, [identifier]);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import React, {useCallback, useEffect, useState} from "react";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import logo from '../../Flaticon_circle.png';
|
||||
import {faArrowLeft, faDoorOpen, faDownload, faPalette, faQuestionCircle} from "@fortawesome/free-solid-svg-icons";
|
||||
@ -208,11 +208,11 @@ const Sidebar = ({items, showBackButton}) => {
|
||||
}
|
||||
|
||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||
const updateWidth = () => setWindowWidth(window.innerWidth);
|
||||
const updateWidth = useCallback(() => setWindowWidth(window.innerWidth), []);
|
||||
useEffect(() => {
|
||||
window.addEventListener('resize', updateWidth);
|
||||
return () => window.removeEventListener('resize', updateWidth);
|
||||
}, []);
|
||||
}, [updateWidth]);
|
||||
|
||||
const collapseSidebar = () => setSidebarExpanded(windowWidth > 1350);
|
||||
useEffect(collapseSidebar, [windowWidth, currentTab, setSidebarExpanded]);
|
||||
|
33
Plan/react/dashboard/src/components/table/DataTablesTable.js
Normal file
33
Plan/react/dashboard/src/components/table/DataTablesTable.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import DataTable from 'datatables.net'
|
||||
import 'datatables.net-bs5'
|
||||
import 'datatables.net-responsive-bs5'
|
||||
import 'datatables.net-bs5/css/dataTables.bootstrap5.min.css';
|
||||
import 'datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css';
|
||||
|
||||
const DataTablesTable = ({id, options}) => {
|
||||
const [dataTable, setDataTable] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (dataTable) {
|
||||
dataTable.destroy();
|
||||
setDataTable(null);
|
||||
}
|
||||
|
||||
const createdDataTable = new DataTable(`#${id}`, options);
|
||||
setDataTable(createdDataTable);
|
||||
|
||||
return () => {
|
||||
if (dataTable) {
|
||||
dataTable.clear();
|
||||
dataTable.destroy();
|
||||
}
|
||||
};
|
||||
}, [id, options, dataTable]);
|
||||
|
||||
return (
|
||||
<table id={id} className="table table-bordered table-striped" style={{width: "100%"}}/>
|
||||
)
|
||||
};
|
||||
|
||||
export default DataTablesTable
|
@ -2,7 +2,8 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
import '@fortawesome/fontawesome-free/css/all.min.css'
|
||||
|
||||
import {library} from '@fortawesome/fontawesome-svg-core';
|
||||
import {fas} from '@fortawesome/free-solid-svg-icons';
|
||||
@ -20,16 +21,4 @@ localeService.init().then(() => ReactDOM.render(
|
||||
<App/>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
));
|
||||
|
||||
// ReactDOM.render(
|
||||
// <React.StrictMode>
|
||||
// <App/>
|
||||
// </React.StrictMode>,
|
||||
// document.getElementById('root')
|
||||
// );
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
));
|
@ -44,7 +44,7 @@ export const localeService = {
|
||||
this.languageVersions = data.languageVersions;
|
||||
} else {
|
||||
this.defaultLanguage = 'en'
|
||||
this.availableLanguages = [];
|
||||
this.availableLanguages = {};
|
||||
this.languageVersions = [];
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,12 @@ export const fetchKills = async (identifier) => {
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayers = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/players?server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayersOnlineGraph = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}`;
|
||||
|
26
Plan/react/dashboard/src/views/server/ServerPlayers.js
Normal file
26
Plan/react/dashboard/src/views/server/ServerPlayers.js
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import {useDataRequest} from "../../hooks/dataFetchHook";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {fetchPlayers} from "../../service/serverService";
|
||||
import ErrorView from "../ErrorView";
|
||||
import {Col, Row} from "react-bootstrap-v5";
|
||||
import PlayerListCard from "../../components/cards/common/PlayerListCard";
|
||||
|
||||
const ServerPlayers = () => {
|
||||
const {identifier} = useParams();
|
||||
|
||||
const {data, loadingError} = useDataRequest(fetchPlayers, [identifier]);
|
||||
|
||||
if (!data) return <></>;
|
||||
if (loadingError) return <ErrorView error={loadingError}/>
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<PlayerListCard data={data}/>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
};
|
||||
|
||||
export default ServerPlayers
|
@ -1153,6 +1153,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.1.tgz#7dc996042d21fc1ae850e3173b5c67b0549f9105"
|
||||
integrity sha512-wVn5WJPirFTnzN6tR95abCx+ocH+3IFLXAgyavnf9hUmN0CfWoDjPT/BAWsUVwSlYYVBeCLJxaqi7ZGe4uSjBA==
|
||||
|
||||
"@fortawesome/fontawesome-free@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.1.1.tgz#bf5d45611ab74890be386712a0e5d998c65ee2a1"
|
||||
integrity sha512-J/3yg2AIXc9wznaVqpHVX3Wa5jwKovVF0AMYSnbmcXTiL3PpRPfF58pzWucCwEiCJBp+hCNRLWClTomD8SseKg==
|
||||
|
||||
"@fortawesome/fontawesome-svg-core@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.1.tgz#3424ec6182515951816be9b11665d67efdce5b5f"
|
||||
@ -3465,6 +3470,38 @@ data-urls@^2.0.0:
|
||||
whatwg-mimetype "^2.3.0"
|
||||
whatwg-url "^8.0.0"
|
||||
|
||||
datatables.net-bs5@>=1.11.3, datatables.net-bs5@^1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-1.12.1.tgz#b05d4bcaed77f6b77df0b50eaf1d5ec8e5d476bd"
|
||||
integrity sha512-CcQCImfmH4YZk7I0aC0kTiNPyfHJ2ueGgOh/kFB9KqsZD8bNJy2A88gC6hn9A7TbmmenOL+K3Q1ti7G8yqi8SQ==
|
||||
dependencies:
|
||||
datatables.net ">=1.11.3"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net-responsive-bs5@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-responsive-bs5/-/datatables.net-responsive-bs5-2.3.0.tgz#f92b79b7d5995c8c6cdc31ab0a725c240bcec448"
|
||||
integrity sha512-OVe2y+WGbZNqwu0clpzjPGg85Y+8KW8pVXVZJEKKyHW0GYAU3Ewhk0f3ZdS0B6Al9Q4v3Gt6OzupVwuY5Ck1pA==
|
||||
dependencies:
|
||||
datatables.net-bs5 ">=1.11.3"
|
||||
datatables.net-responsive ">=2.2.9"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net-responsive@>=2.2.9:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-responsive/-/datatables.net-responsive-2.3.0.tgz#2b8d894af5456f8c8a320eeac5e837a24d84e033"
|
||||
integrity sha512-QA5QsD1sJQRQ7/IFi3rSd33O84f/Augz2KnaehjfuEANtK4KeC9Lbkut5tPuuMcK4jOpQPOOPYTbmfrt+tfh9w==
|
||||
dependencies:
|
||||
datatables.net ">=1.11.3"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net@>=1.11.3, datatables.net@^1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.12.1.tgz#3e625e49a3341f605b0efb519fae94e37b278f24"
|
||||
integrity sha512-e6XAMUoV41JdQPS/r9YRfRcmTPcCVvyZbWI+xog1Zg+kjVliMQbEkvWK5XFItmi64Cvwg+IqsZbTUJ1KSY3umA==
|
||||
dependencies:
|
||||
jquery ">=1.7"
|
||||
|
||||
debug@2.6.9, debug@^2.6.0, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@ -5634,6 +5671,11 @@ jest@^27.4.3:
|
||||
import-local "^3.0.2"
|
||||
jest-cli "^27.5.1"
|
||||
|
||||
jquery@>=1.7:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
|
||||
integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
|
Loading…
Reference in New Issue
Block a user