mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-05 07:58:08 +01:00
5.5.2100
This commit is contained in:
parent
09a9516c38
commit
8008131ad7
@ -13,13 +13,13 @@
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@fullcalendar/bootstrap": "^5.11.3",
|
||||
"@fullcalendar/daygrid": "^5.11.3",
|
||||
"@fullcalendar/react": "^5.11.2",
|
||||
"@fullcalendar/react": "^5.11.3",
|
||||
"@highcharts/map-collection": "^2.0.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^12.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"axios": "^1.1.3",
|
||||
"bootstrap": "^5.2.2",
|
||||
"axios": "^1.2.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"datatables.net": "^1.13.1",
|
||||
"datatables.net-bs5": "^1.12.1",
|
||||
"datatables.net-responsive-bs5": "^2.4.0",
|
||||
|
BIN
react/dashboard/dashboard/public/logo192.png
Normal file
BIN
react/dashboard/dashboard/public/logo192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
BIN
react/dashboard/dashboard/public/logo512.png
Normal file
BIN
react/dashboard/dashboard/public/logo512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
@ -12,6 +12,7 @@ import {MetadataContextProvider} from "./hooks/metadataHook";
|
||||
import {AuthenticationContextProvider} from "./hooks/authenticationHook";
|
||||
import {NavigationContextProvider} from "./hooks/navigationHook";
|
||||
import MainPageRedirect from "./components/navigation/MainPageRedirect";
|
||||
import {staticSite} from "./service/backendConfiguration";
|
||||
|
||||
const PlayerPage = React.lazy(() => import("./views/layout/PlayerPage"));
|
||||
const PlayerOverview = React.lazy(() => import("./views/player/PlayerOverview"));
|
||||
@ -28,7 +29,6 @@ const ServerPvpPve = React.lazy(() => import("./views/server/ServerPvpPve"));
|
||||
const PlayerbaseOverview = React.lazy(() => import("./views/server/PlayerbaseOverview"));
|
||||
const ServerPlayers = React.lazy(() => import("./views/server/ServerPlayers"));
|
||||
const ServerGeolocations = React.lazy(() => import("./views/server/ServerGeolocations"));
|
||||
const LoginPage = React.lazy(() => import("./views/layout/LoginPage"));
|
||||
const ServerPerformance = React.lazy(() => import("./views/server/ServerPerformance"));
|
||||
const ServerPluginData = React.lazy(() => import("./views/server/ServerPluginData"));
|
||||
const ServerWidePluginData = React.lazy(() => import("./views/server/ServerWidePluginData"));
|
||||
@ -50,6 +50,9 @@ const QueryPage = React.lazy(() => import("./views/layout/QueryPage"));
|
||||
const NewQueryView = React.lazy(() => import("./views/query/NewQueryView"));
|
||||
const QueryResultView = React.lazy(() => import("./views/query/QueryResultView"));
|
||||
|
||||
const LoginPage = React.lazy(() => import("./views/layout/LoginPage"));
|
||||
const RegisterPage = React.lazy(() => import("./views/layout/RegisterPage"));
|
||||
const ErrorPage = React.lazy(() => import("./views/layout/ErrorPage"));
|
||||
const ErrorsPage = React.lazy(() => import("./views/layout/ErrorsPage"));
|
||||
const SwaggerView = React.lazy(() => import("./views/SwaggerView"));
|
||||
|
||||
@ -89,7 +92,9 @@ function App() {
|
||||
<Routes>
|
||||
<Route path="" element={<MainPageRedirect/>}/>
|
||||
<Route path="/" element={<MainPageRedirect/>}/>
|
||||
<Route path="/login" element={<Lazy><LoginPage/></Lazy>}/>
|
||||
<Route path="index.html" element={<MainPageRedirect/>}/>
|
||||
{!staticSite && <Route path="/login" element={<Lazy><LoginPage/></Lazy>}/>}
|
||||
{!staticSite && <Route path="/register" element={<Lazy><RegisterPage/></Lazy>}/>}
|
||||
<Route path="/player/:identifier" element={<Lazy><PlayerPage/></Lazy>}>
|
||||
<Route path="" element={<Lazy><OverviewRedirect/></Lazy>}/>
|
||||
<Route path="overview" element={<Lazy><PlayerOverview/></Lazy>}/>
|
||||
@ -132,7 +137,8 @@ function App() {
|
||||
<Route path="overview" element={<Lazy><NetworkOverview/></Lazy>}/>
|
||||
<Route path="serversOverview" element={<Lazy><NetworkServers/></Lazy>}/>
|
||||
<Route path="sessions" element={<Lazy><NetworkSessions/></Lazy>}/>
|
||||
<Route path="performance" element={<Lazy><NetworkPerformance/></Lazy>}/>
|
||||
{!staticSite &&
|
||||
<Route path="performance" element={<Lazy><NetworkPerformance/></Lazy>}/>}
|
||||
<Route path="playerbase" element={<Lazy><NetworkPlayerbaseOverview/></Lazy>}/>
|
||||
<Route path="join-addresses" element={<Lazy><NetworkJoinAddresses/></Lazy>}/>
|
||||
<Route path="players" element={<Lazy><AllPlayers/></Lazy>}/>
|
||||
@ -145,13 +151,18 @@ function App() {
|
||||
icon: faMapSigns
|
||||
}}/>}/>
|
||||
</Route>
|
||||
<Route path="/query" element={<Lazy><QueryPage/></Lazy>}>
|
||||
{!staticSite && <Route path="/query" element={<Lazy><QueryPage/></Lazy>}>
|
||||
<Route path="" element={<NewRedirect/>}/>
|
||||
<Route path="new" element={<Lazy><NewQueryView/></Lazy>}/>
|
||||
<Route path="result" element={<Lazy><QueryResultView/></Lazy>}/>
|
||||
</Route>
|
||||
<Route path="/errors" element={<Lazy><ErrorsPage/></Lazy>}/>
|
||||
<Route path="/docs" element={<Lazy><SwaggerView/></Lazy>}/>
|
||||
</Route>}
|
||||
{!staticSite && <Route path="/errors" element={<Lazy><ErrorsPage/></Lazy>}/>}
|
||||
{!staticSite && <Route path="/docs" element={<Lazy><SwaggerView/></Lazy>}/>}
|
||||
<Route path="*" element={<Lazy><ErrorPage error={{
|
||||
message: 'Page not found, please correct the address',
|
||||
title: 'No such page',
|
||||
icon: faMapSigns
|
||||
}}/></Lazy>}/>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
|
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {useMetadata} from "../../hooks/metadataHook";
|
||||
import {Modal} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faHandPointRight} from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
const FinalizeRegistrationModal = ({show, toggle, registerCode}) => {
|
||||
const {t} = useTranslation();
|
||||
const {mainCommand} = useMetadata();
|
||||
|
||||
return (
|
||||
<Modal id={"finalizeModal"}
|
||||
aria-labelledby={"finalizeModalLable"}
|
||||
show={show}
|
||||
onHide={toggle}
|
||||
>
|
||||
<Modal.Header className="bg-white">
|
||||
<Modal.Title id={"finalizeModalLabel"}>
|
||||
<Fa icon={faHandPointRight}/> {t('html.register.completion')}
|
||||
</Modal.Title>
|
||||
<button aria-label="Close" className="btn-close" onClick={toggle}/>
|
||||
</Modal.Header>
|
||||
<Modal.Body className={"bg-white"}>
|
||||
<p>{t('html.register.completion1')} {t('html.register.completion2')}</p>
|
||||
<p>{t('html.register.completion3')}</p>
|
||||
<p><code>/{mainCommand} register --code {registerCode}</code></p>
|
||||
<p>{t('html.register.completion4')}</p>
|
||||
<p><code>{mainCommand} register superuser --code {registerCode}</code></p>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
)
|
||||
};
|
||||
|
||||
export default FinalizeRegistrationModal
|
@ -10,7 +10,7 @@ import DropdownToggle from "react-bootstrap-v5/lib/esm/DropdownToggle";
|
||||
import {localeService} from "../../service/localeService";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {useNavigation} from "../../hooks/navigationHook";
|
||||
import {baseAddress} from "../../service/backendConfiguration";
|
||||
import {baseAddress, staticSite} from "../../service/backendConfiguration";
|
||||
|
||||
const LanguageSelector = () => {
|
||||
const languages = localeService.getLanguages();
|
||||
@ -55,9 +55,9 @@ const Header = ({page, tab, hideUpdater}) => {
|
||||
{!hideUpdater && <>
|
||||
<span className="topbar-divider"/>
|
||||
<div className="refresh-element">
|
||||
<button onClick={requestUpdate}>
|
||||
{!staticSite && <button onClick={requestUpdate}>
|
||||
<Fa icon={faSyncAlt} spin={Boolean(updating)}/>
|
||||
</button>
|
||||
</button>}
|
||||
{' '}
|
||||
<span className="refresh-time">{lastUpdate.formatted}</span>
|
||||
</div>
|
||||
|
@ -230,7 +230,7 @@ const Sidebar = ({items, showBackButton}) => {
|
||||
<Item active={false} item={{href: "/", icon: faArrowLeft, name: t('html.label.toMainPage')}}/>
|
||||
<Divider showMargin={items.length && !items[0].contents && items[0].href === undefined}/>
|
||||
</>}
|
||||
{items.length ? items.map((item, i) => renderItem(item, i, openCollapse, toggleCollapse, t)) : ''}
|
||||
{items.length ? items.filter(item => item !== undefined).map((item, i) => renderItem(item, i, openCollapse, toggleCollapse, t)) : ''}
|
||||
<Divider/>
|
||||
<FooterButtons/>
|
||||
</ul>}
|
||||
|
@ -2,6 +2,7 @@ import {useEffect, useState} from "react";
|
||||
import {useNavigation} from "./navigationHook";
|
||||
import {useDataStore} from "./datastoreHook";
|
||||
import {useMetadata} from "./metadataHook";
|
||||
import {staticSite} from "../service/backendConfiguration";
|
||||
|
||||
export const useDataRequest = (fetchMethod, parameters) => {
|
||||
const [data, setData] = useState(undefined);
|
||||
@ -16,7 +17,7 @@ export const useDataRequest = (fetchMethod, parameters) => {
|
||||
const handleResponse = (json, error, skipOldData, timeout) => {
|
||||
if (json) {
|
||||
const timestamp = json.timestamp;
|
||||
if (timestamp) {
|
||||
if (staticSite || timestamp) {
|
||||
// Data has timestamp, the data may come from cache
|
||||
const acceptedTimestamp = timestamp + (refreshBarrierMs ? refreshBarrierMs : 15000);
|
||||
if (acceptedTimestamp < updateRequested) {
|
||||
|
@ -1,6 +1,9 @@
|
||||
import {doGetRequest, doSomePostRequest, standard200option} from "./backendConfiguration";
|
||||
import {doGetRequest, doSomePostRequest, standard200option, staticSite} from "./backendConfiguration";
|
||||
|
||||
export const fetchWhoAmI = async () => {
|
||||
if (staticSite) {
|
||||
return {authRequired: false, loggedIn: false}
|
||||
}
|
||||
const url = '/v1/whoami';
|
||||
return doGetRequest(url);
|
||||
}
|
||||
@ -8,4 +11,14 @@ export const fetchWhoAmI = async () => {
|
||||
export const fetchLogin = async (username, password) => {
|
||||
const url = '/auth/login';
|
||||
return doSomePostRequest(url, [standard200option], `user=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`);
|
||||
}
|
||||
|
||||
export const postRegister = async (username, password) => {
|
||||
const url = '/auth/register';
|
||||
return doSomePostRequest(url, [standard200option], `user=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`);
|
||||
}
|
||||
|
||||
export const fetchRegisterCheck = async (code) => {
|
||||
const url = `/auth/register?code=${encodeURIComponent(code)}`;
|
||||
return doGetRequest(url);
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
import axios from "axios";
|
||||
|
||||
const toBeReplaced = "PLAN_BASE_ADDRESS";
|
||||
const javaReplaced = {
|
||||
isStatic: "PLAN_EXPORTED_VERSION",
|
||||
address: "PLAN_BASE_ADDRESS"
|
||||
}
|
||||
|
||||
const isCurrentAddress = (address) => {
|
||||
const is = window.location.href.startsWith(address);
|
||||
@ -8,7 +11,8 @@ const isCurrentAddress = (address) => {
|
||||
return is;
|
||||
}
|
||||
|
||||
export const baseAddress = "PLAN_BASE_ADDRESS" === toBeReplaced || !isCurrentAddress(toBeReplaced) ? "" : toBeReplaced;
|
||||
export const baseAddress = javaReplaced.address.startsWith('PLAN_') || !isCurrentAddress(javaReplaced.address) ? "" : javaReplaced.address;
|
||||
export const staticSite = javaReplaced.isStatic === 'true';
|
||||
|
||||
export const doSomeGetRequest = async (url, statusOptions) => {
|
||||
return doSomeRequest(url, statusOptions, async () => axios.get(url));
|
||||
|
@ -4,6 +4,7 @@ import I18NextLocalStorageBackend from "i18next-localstorage-backend";
|
||||
import I18NextHttpBackend from 'i18next-http-backend';
|
||||
import {initReactI18next} from 'react-i18next';
|
||||
import {fetchAvailableLocales} from "./metadataService";
|
||||
import {baseAddress, staticSite} from "./backendConfiguration";
|
||||
|
||||
/**
|
||||
* A locale system for localizing the website.
|
||||
@ -53,6 +54,8 @@ export const localeService = {
|
||||
this.clientLocale = this.defaultLanguage;
|
||||
}
|
||||
|
||||
let loadPath = baseAddress + '/v1/locale/{{lng}}';
|
||||
if (staticSite) loadPath = baseAddress + '/locale/{{lng}}.json'
|
||||
await i18next
|
||||
.use(I18NextChainedBackend)
|
||||
.use(initReactI18next)
|
||||
@ -70,7 +73,7 @@ export const localeService = {
|
||||
expirationTime: 7 * 24 * 60 * 60 * 1000, // 7 days
|
||||
versions: this.languageVersions
|
||||
}, {
|
||||
loadPath: '/v1/locale/{{lng}}'
|
||||
loadPath: loadPath
|
||||
}]
|
||||
},
|
||||
}, () => {/* No need to initialize anything */
|
||||
|
@ -1,26 +1,30 @@
|
||||
import {doGetRequest} from "./backendConfiguration";
|
||||
import {doGetRequest, staticSite} from "./backendConfiguration";
|
||||
|
||||
export const fetchPlanMetadata = async () => {
|
||||
const url = '/v1/metadata';
|
||||
let url = '/v1/metadata';
|
||||
if (staticSite) url = '/metadata/metadata.json'
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlanVersion = async () => {
|
||||
const url = '/v1/version';
|
||||
let url = '/v1/version';
|
||||
if (staticSite) url = '/metadata/version.json'
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchAvailableLocales = async () => {
|
||||
const url = '/v1/locale';
|
||||
let url = '/v1/locale';
|
||||
if (staticSite) url = '/locale/locale.json'
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchErrorLogs = async () => {
|
||||
const url = '/v1/errors';
|
||||
let url = '/v1/errors';
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchNetworkMetadata = async () => {
|
||||
const url = '/v1/networkMetadata';
|
||||
let url = '/v1/networkMetadata';
|
||||
if (staticSite) url = '/metadata/networkMetadata.json'
|
||||
return doGetRequest(url);
|
||||
}
|
@ -1,36 +1,42 @@
|
||||
import {doGetRequest} from "./backendConfiguration";
|
||||
import {doGetRequest, staticSite} from "./backendConfiguration";
|
||||
|
||||
export const fetchNetworkOverview = async (updateRequested) => {
|
||||
const url = `/v1/network/overview?timestamp=${updateRequested}`;
|
||||
let url = `/v1/network/overview?timestamp=${updateRequested}`;
|
||||
if (staticSite) url = `/data/network-overview.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchServersOverview = async (updateRequested) => {
|
||||
const url = `/v1/network/servers?timestamp=${updateRequested}`;
|
||||
let url = `/v1/network/servers?timestamp=${updateRequested}`;
|
||||
if (staticSite) url = `/data/network-servers.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchServerPie = async (timestamp) => {
|
||||
const url = `/v1/graph?type=serverPie×tamp=${timestamp}`;
|
||||
let url = `/v1/graph?type=serverPie×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-serverPie.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchNetworkSessionsOverview = async (timestamp) => {
|
||||
const url = `/v1/network/sessionsOverview?timestamp=${timestamp}`;
|
||||
let url = `/v1/network/sessionsOverview?timestamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/network-sessionsOverview.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchNetworkPlayerbaseOverview = async (timestamp) => {
|
||||
const url = `/v1/network/playerbaseOverview?timestamp=${timestamp}`;
|
||||
let url = `/v1/network/playerbaseOverview?timestamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/network-playerbaseOverview.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchNetworkPingTable = async (timestamp) => {
|
||||
const url = `/v1/network/pingTable?timestamp=${timestamp}`;
|
||||
let url = `/v1/network/pingTable?timestamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/network-pingTable.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchNetworkPerformanceOverview = async (timestamp, serverUUIDs) => {
|
||||
const url = `/v1/network/performanceOverview?servers=${encodeURIComponent(JSON.stringify(serverUUIDs))}×tamp=${timestamp}`;
|
||||
let url = `/v1/network/performanceOverview?servers=${encodeURIComponent(JSON.stringify(serverUUIDs))}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
import {faMapSigns} from "@fortawesome/free-solid-svg-icons";
|
||||
import {doSomeGetRequest, standard200option} from "./backendConfiguration";
|
||||
import {doSomeGetRequest, standard200option, staticSite} from "./backendConfiguration";
|
||||
|
||||
export const fetchPlayer = async (timestamp, uuid) => {
|
||||
const url = `/v1/player?player=${uuid}×tamp=${timestamp}`;
|
||||
let url = `/v1/player?player=${uuid}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/player/${uuid}/player-${uuid}.json`
|
||||
return doSomeGetRequest(url, [
|
||||
standard200option,
|
||||
{
|
||||
status: 400,
|
||||
status: staticSite ? 404 : 400,
|
||||
get: () => ({
|
||||
message: 'Player not found: ' + uuid + ', try another player',
|
||||
message: 'Player not found: ' + uuid + ', try another player.' + (staticSite ? ' You can try the export players command.' : ''),
|
||||
title: '404 Player not found',
|
||||
icon: faMapSigns
|
||||
})
|
||||
|
@ -1,130 +1,270 @@
|
||||
import {doGetRequest} from "./backendConfiguration";
|
||||
|
||||
import {doGetRequest, staticSite} from "./backendConfiguration";
|
||||
|
||||
export const fetchServerIdentity = async (timestamp, identifier) => {
|
||||
const url = `/v1/serverIdentity?server=${identifier}`;
|
||||
let url = `/v1/serverIdentity?server=${identifier}`;
|
||||
if (staticSite) url = `/data/serverIdentity-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchServerOverview = async (timestamp, identifier) => {
|
||||
const url = `/v1/serverOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/serverOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/serverOverview-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchOnlineActivityOverview = async (timestamp, identifier) => {
|
||||
const url = `/v1/onlineOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/onlineOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/onlineOverview-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayerbaseOverview = async (timestamp, identifier) => {
|
||||
const url = `/v1/playerbaseOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/playerbaseOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/playerbaseOverview-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchSessionOverview = async (timestamp, identifier) => {
|
||||
const url = `/v1/sessionsOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/sessionsOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/sessionsOverview-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPvpPve = async (timestamp, identifier) => {
|
||||
const url = `/v1/playerVersus?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/playerVersus?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/playerVersus-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPerformanceOverview = async (timestamp, identifier) => {
|
||||
const url = `/v1/performanceOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/performanceOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/performanceOverview-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchExtensionData = async (timestamp, identifier) => {
|
||||
const url = `/v1/extensionData?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/extensionData?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/extensionData-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchSessions = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/sessions?server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/sessions?timestamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchSessionsServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchSessionsNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchSessionsServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/sessions?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/sessions-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchSessionsNetwork = async (timestamp) => {
|
||||
let url = `/v1/sessions?timestamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/sessions.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchKills = async (timestamp, identifier) => {
|
||||
const url = `/v1/kills?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/kills?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/kills-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayers = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/players?server=${identifier}×tamp=${timestamp}` : `/v1/players?timestamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchPlayersServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchPlayersNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
const fetchPlayersServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/players?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/players-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchPlayersNetwork = async (timestamp) => {
|
||||
let url = `/v1/players?timestamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/players.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPingTable = async (timestamp, identifier) => {
|
||||
const url = `/v1/pingTable?server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/pingTable?server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/pingTable-${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayersOnlineGraph = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=playersOnline×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchPlayersOnlineGraphServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchPlayersOnlineGraphNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchPlayersOnlineGraphServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-playersOnline_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchPlayersOnlineGraphNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=playersOnline×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-playersOnline.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayerbaseDevelopmentGraph = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=activity&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=activity×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchPlayerbaseDevelopmentGraphServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchPlayerbaseDevelopmentGraphNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchPlayerbaseDevelopmentGraphServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=activity&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-activity_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchPlayerbaseDevelopmentGraphNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=activity×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-activity.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchDayByDayGraph = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=uniqueAndNew&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=uniqueAndNew×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchDayByDayGraphServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchDayByDayGraphNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchDayByDayGraphServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=uniqueAndNew&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-uniqueAndNew_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchDayByDayGraphNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=uniqueAndNew×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-uniqueAndNew.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchHourByHourGraph = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=hourlyUniqueAndNew&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=hourlyUniqueAndNew×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchHourByHourGraphServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchHourByHourGraphNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchHourByHourGraphServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=hourlyUniqueAndNew&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-hourlyUniqueAndNew_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchHourByHourGraphNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=hourlyUniqueAndNew×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-hourlyUniqueAndNew.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchServerCalendarGraph = async (timestamp, identifier) => {
|
||||
const url = `/v1/graph?type=serverCalendar&server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/graph?type=serverCalendar&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-serverCalendar_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPunchCardGraph = async (timestamp, identifier) => {
|
||||
const url = `/v1/graph?type=punchCard&server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/graph?type=punchCard&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-punchCard_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchWorldPie = async (timestamp, identifier) => {
|
||||
const url = `/v1/graph?type=worldPie&server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/graph?type=worldPie&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-worldPie_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchGeolocations = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=geolocation&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=geolocation×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchGeolocationsServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchGeolocationsNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchGeolocationsServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=geolocation&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-geolocation_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchGeolocationsNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=geolocation×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-geolocation.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchOptimizedPerformance = async (timestamp, identifier, after) => {
|
||||
const url = `/v1/graph?type=optimizedPerformance&server=${identifier}×tamp=${timestamp}&after=${after}`;
|
||||
let url = `/v1/graph?type=optimizedPerformance&server=${identifier}×tamp=${timestamp}&after=${after}`;
|
||||
if (staticSite) url = `/data/graph-optimizedPerformance_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPingGraph = async (timestamp, identifier) => {
|
||||
const url = `/v1/graph?type=aggregatedPing&server=${identifier}×tamp=${timestamp}`;
|
||||
let url = `/v1/graph?type=aggregatedPing&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-aggregatedPing_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchJoinAddressPie = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=joinAddressPie&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=joinAddressPie×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchJoinAddressPieServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchJoinAddressPieNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchJoinAddressPieServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=joinAddressPie&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-joinAddressPie_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchJoinAddressPieNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=joinAddressPie×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-joinAddressPie.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchJoinAddressByDay = async (timestamp, identifier) => {
|
||||
const url = identifier ? `/v1/graph?type=joinAddressByDay&server=${identifier}×tamp=${timestamp}` :
|
||||
`/v1/graph?type=joinAddressByDay×tamp=${timestamp}`;
|
||||
if (identifier) {
|
||||
return await fetchJoinAddressByDayServer(timestamp, identifier);
|
||||
} else {
|
||||
return await fetchJoinAddressByDayNetwork(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchJoinAddressByDayServer = async (timestamp, identifier) => {
|
||||
let url = `/v1/graph?type=joinAddressByDay&server=${identifier}×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-joinAddressByDay_${identifier}.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
const fetchJoinAddressByDayNetwork = async (timestamp) => {
|
||||
let url = `/v1/graph?type=joinAddressByDay×tamp=${timestamp}`;
|
||||
if (staticSite) url = `/data/graph-joinAddressByDay.json`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ const ErrorPage = ({error}) => {
|
||||
<NightModeCss/>
|
||||
<Sidebar items={[]} showBackButton={true}/>
|
||||
<div className="d-flex flex-column" id="content-wrapper">
|
||||
<Header page={error.title ? error.title : 'Unexpected error occurred'}/>
|
||||
<Header page={error.title ? error.title : 'Unexpected error occurred'} hideUpdater/>
|
||||
<div id="content" style={{display: 'flex'}}>
|
||||
<main className="container-fluid mt-4">
|
||||
<ErrorView error={error}/>
|
||||
|
@ -125,6 +125,7 @@ const LoginPage = () => {
|
||||
|
||||
const [forgotPasswordModalOpen, setForgotPasswordModalOpen] = useState(false);
|
||||
|
||||
const [successMessage, setSuccessMessage] = useState('')
|
||||
const [failMessage, setFailMessage] = useState('');
|
||||
const [redirectTo, setRedirectTo] = useState(undefined);
|
||||
|
||||
@ -138,10 +139,13 @@ const LoginPage = () => {
|
||||
const cameFrom = urlParams.get('from');
|
||||
if (cameFrom) setRedirectTo(cameFrom);
|
||||
|
||||
const registerSuccess = urlParams.get('registerSuccess');
|
||||
if (registerSuccess) setSuccessMessage(t('html.register.success'))
|
||||
|
||||
return () => {
|
||||
document.body.classList.remove("bg-plan", "plan-bg-gradient");
|
||||
}
|
||||
}, [setRedirectTo])
|
||||
}, [setRedirectTo, setSuccessMessage, t])
|
||||
|
||||
const login = async (username, password) => {
|
||||
if (!username || username.length < 1) {
|
||||
@ -189,8 +193,9 @@ const LoginPage = () => {
|
||||
<Logo/>
|
||||
<LoginCard>
|
||||
{failMessage && <Alert className='alert-danger'>{failMessage}</Alert>}
|
||||
{successMessage && <Alert className='alert-success'>{successMessage}</Alert>}
|
||||
<LoginForm login={login}/>
|
||||
<hr className="bg-secondary"/>
|
||||
<hr className="col-secondary"/>
|
||||
<ForgotPasswordButton onClick={togglePasswordModal}/>
|
||||
<CreateAccountLink/>
|
||||
<ColorChooserButton/>
|
||||
|
@ -26,6 +26,7 @@ import {SwitchTransition} from "react-transition-group";
|
||||
import MainPageRedirect from "../../components/navigation/MainPageRedirect";
|
||||
import {ServerExtensionContextProvider, useServerExtensionContext} from "../../hooks/serverExtensionDataContext";
|
||||
import {iconTypeToFontAwesomeClass} from "../../util/icons";
|
||||
import {staticSite} from "../../service/backendConfiguration";
|
||||
|
||||
const NetworkSidebar = () => {
|
||||
const {t, i18n} = useTranslation();
|
||||
@ -49,7 +50,7 @@ const NetworkSidebar = () => {
|
||||
href: "serversOverview"
|
||||
},
|
||||
{name: 'html.label.sessions', icon: faCalendarCheck, href: "sessions"},
|
||||
{name: 'html.label.performance', icon: faCogs, href: "performance"},
|
||||
staticSite ? undefined : {name: 'html.label.performance', icon: faCogs, href: "performance"},
|
||||
{},
|
||||
...servers.map(server => {
|
||||
return {
|
||||
|
200
react/dashboard/dashboard/src/views/layout/RegisterPage.js
Normal file
200
react/dashboard/dashboard/src/views/layout/RegisterPage.js
Normal file
@ -0,0 +1,200 @@
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
|
||||
import logo from '../../Flaticon_circle.png'
|
||||
import {Alert, Card, Col, Row} from "react-bootstrap-v5";
|
||||
import {Link, useNavigate} from "react-router-dom";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faPalette} from "@fortawesome/free-solid-svg-icons";
|
||||
import {useTheme} from "../../hooks/themeHook";
|
||||
import ColorSelectorModal from "../../components/modal/ColorSelectorModal";
|
||||
import {useAuth} from "../../hooks/authenticationHook";
|
||||
import FinalizeRegistrationModal from "../../components/modal/FinalizeRegistrationModal";
|
||||
import {fetchRegisterCheck, postRegister} from "../../service/authenticationService";
|
||||
import {baseAddress} from "../../service/backendConfiguration";
|
||||
|
||||
const Logo = () => {
|
||||
return (
|
||||
<Col md={12} className='mt-5 text-center'>
|
||||
<img alt="logo" className="w-15" src={logo}/>
|
||||
</Col>
|
||||
)
|
||||
};
|
||||
|
||||
const RegisterCard = ({children}) => {
|
||||
return (
|
||||
<Row className="justify-content-center container-fluid">
|
||||
<Col xl={6} lg={7} md={9}>
|
||||
<Card className='o-hidden border-0 shadow-lg my-5'>
|
||||
<Card.Body className='p-0'>
|
||||
<Row>
|
||||
<Col lg={12}>
|
||||
<div className='p-5'>
|
||||
{children}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
||||
const RegisterForm = ({register}) => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
const onRegister = useCallback(event => {
|
||||
event.preventDefault();
|
||||
register(username, password).then(() => setPassword(''));
|
||||
}, [username, password, setPassword, register]);
|
||||
|
||||
return (
|
||||
<form className="user">
|
||||
<div className="mb-3">
|
||||
<input autoComplete="username" className="form-control form-control-user"
|
||||
id="inputUser"
|
||||
placeholder={t('html.login.username')} type="text"
|
||||
value={username} onChange={event => setUsername(event.target.value)}/>
|
||||
<div className={"form-text"}>{t('html.register.usernameTip')}</div>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<input autoComplete="current-password" className="form-control form-control-user"
|
||||
id="inputPassword" placeholder={t('html.login.password')} type="password"
|
||||
value={password} onChange={event => setPassword(event.target.value)}/>
|
||||
<div className={"form-text"}>{t('html.register.passwordTip')}</div>
|
||||
</div>
|
||||
<button className="btn bg-plan btn-user w-100" id="register-button" onClick={onRegister}>
|
||||
{t('html.register.register')}
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
const ColorChooserButton = () => {
|
||||
const {t} = useTranslation();
|
||||
const {toggleColorChooser} = useTheme();
|
||||
|
||||
return (
|
||||
<div className='text-center'>
|
||||
<button className="btn col-plan" onClick={toggleColorChooser}
|
||||
title={t('html.label.themeSelect')}>
|
||||
<Fa icon={faPalette}/>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const LoginLink = () => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
return (
|
||||
<div className='text-center'>
|
||||
<Link to='/login' className='col-plan small'>{t('html.register.login')}</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const RegisterPage = () => {
|
||||
const {t} = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const {authLoaded, authRequired, loggedIn} = useAuth();
|
||||
|
||||
const [finalizeRegistrationModalOpen, setFinalizeRegistrationModalOpen] = useState(false);
|
||||
|
||||
const [registerCode, setRegisterCode] = useState(undefined);
|
||||
const [failMessage, setFailMessage] = useState('');
|
||||
|
||||
const toggleRegistrationModal = useCallback(() => setFinalizeRegistrationModalOpen(!finalizeRegistrationModalOpen),
|
||||
[setFinalizeRegistrationModalOpen, finalizeRegistrationModalOpen])
|
||||
|
||||
useEffect(() => {
|
||||
document.body.classList.add("bg-plan", "plan-bg-gradient");
|
||||
|
||||
return () => {
|
||||
document.body.classList.remove("bg-plan", "plan-bg-gradient");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const checkRegistration = async (code) => {
|
||||
if (!code) {
|
||||
setFinalizeRegistrationModalOpen(false);
|
||||
return setFailMessage("Register code was not received.");
|
||||
}
|
||||
if (!finalizeRegistrationModalOpen) {
|
||||
setFinalizeRegistrationModalOpen(true);
|
||||
}
|
||||
|
||||
const {data, error} = await fetchRegisterCheck(code);
|
||||
if (error) {
|
||||
setFailMessage(t('html.register.error.checkFailed') + error)
|
||||
} else if (data && data.success) {
|
||||
navigate(baseAddress + '/login?registerSuccess=true');
|
||||
} else {
|
||||
setTimeout(() => checkRegistration(code), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
const register = async (username, password) => {
|
||||
if (!username || username.length < 1) {
|
||||
return setFailMessage(t('html.register.error.noUsername'));
|
||||
}
|
||||
if (username.length > 50) {
|
||||
return setFailMessage(t('html.register.error.usernameLength') + username.length);
|
||||
}
|
||||
if (!password || password.length < 1) {
|
||||
return setFailMessage(t('html.register.error.noPassword'));
|
||||
}
|
||||
|
||||
const {data, error} = await postRegister(username, password);
|
||||
|
||||
if (error) {
|
||||
setFailMessage(t('html.register.error.failed') + (error.data && error.data.error ? error.data.error : error.message));
|
||||
} else if (data && data.code) {
|
||||
setRegisterCode(data.code);
|
||||
setFinalizeRegistrationModalOpen(true);
|
||||
setTimeout(() => checkRegistration(data.code), 10000);
|
||||
} else {
|
||||
setFailMessage(t('html.register.error.failed') + data ? data.error : t('generic.noData'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!authLoaded) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
if (!authRequired || loggedIn) {
|
||||
navigate('../');
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main className="container">
|
||||
<Logo/>
|
||||
<RegisterCard>
|
||||
<div className="text-center">
|
||||
<h1 className="h4 text-gray-900 mb-4">{t('html.register.createNewUser')}</h1>
|
||||
</div>
|
||||
{failMessage && <Alert className='alert-danger'>{failMessage}</Alert>}
|
||||
<RegisterForm register={register}/>
|
||||
<hr className="col-secondary"/>
|
||||
<LoginLink/>
|
||||
<ColorChooserButton/>
|
||||
</RegisterCard>
|
||||
</main>
|
||||
<aside>
|
||||
<ColorSelectorModal/>
|
||||
<FinalizeRegistrationModal
|
||||
show={finalizeRegistrationModalOpen}
|
||||
toggle={toggleRegistrationModal}
|
||||
registerCode={registerCode}
|
||||
/>
|
||||
</aside>
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
export default RegisterPage
|
@ -1204,7 +1204,7 @@
|
||||
"@fullcalendar/common" "~5.11.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@fullcalendar/common@~5.11.2", "@fullcalendar/common@~5.11.3":
|
||||
"@fullcalendar/common@~5.11.3":
|
||||
version "5.11.3"
|
||||
resolved "https://registry.yarnpkg.com/@fullcalendar/common/-/common-5.11.3.tgz#6d555a06925b8a6d1556570c9f039960539908d5"
|
||||
integrity sha512-welVwyfQOXQQGfDwBMSfYEPbiO1cPfUD+C7jd3ZoweJR+dSO11ddFugxIQ7dGfABAGZ63oq/+LW9FsmAJezVNg==
|
||||
@ -1219,12 +1219,12 @@
|
||||
"@fullcalendar/common" "~5.11.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@fullcalendar/react@^5.11.2":
|
||||
version "5.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@fullcalendar/react/-/react-5.11.2.tgz#019e6a0573d869c2a52f63426e13593857ee2d30"
|
||||
integrity sha512-OnLvfV406VEQcK4QGN8xR4ro6Manp9dKE7/n9dhs19J1kKpqS1w1sIEYg1dT11njbk0Ob+TdF3cXLDFq73jUlA==
|
||||
"@fullcalendar/react@^5.11.3":
|
||||
version "5.11.3"
|
||||
resolved "https://registry.yarnpkg.com/@fullcalendar/react/-/react-5.11.3.tgz#34c076785ec8ea12cfbc29b7028cb5d923c2aecd"
|
||||
integrity sha512-pxk6da5V1Mn41M664phQ1cr+0QbhXqkDHUhAVp8OOBrtMW84nhs82IYWTZNA3cbFCn4aUgoG2oGnyxekSF3pYA==
|
||||
dependencies:
|
||||
"@fullcalendar/common" "~5.11.2"
|
||||
"@fullcalendar/common" "~5.11.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@highcharts/map-collection@^2.0.1":
|
||||
@ -2662,10 +2662,10 @@ axe-core@^4.3.5:
|
||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413"
|
||||
integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==
|
||||
|
||||
axios@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35"
|
||||
integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==
|
||||
axios@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.0.tgz#1cb65bd75162c70e9f8d118a905126c4a201d383"
|
||||
integrity sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
@ -2890,10 +2890,10 @@ boolbase@^1.0.0, boolbase@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
|
||||
|
||||
bootstrap@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.2.tgz#834e053eed584a65e244d8aa112a6959f56e27a0"
|
||||
integrity sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==
|
||||
bootstrap@^5.2.3:
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.3.tgz#54739f4414de121b9785c5da3c87b37ff008322b"
|
||||
integrity sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
|
Loading…
Reference in New Issue
Block a user