forked from simrail/simrail.pro
feat(backend, frontend): fix stats from singleplayer, fix admin men.
This commit is contained in:
parent
e2732c2008
commit
687fa01983
@ -59,9 +59,9 @@ export class AdminRoute
|
||||
);
|
||||
});
|
||||
|
||||
app.post("/profile/:playerId/clear", async (req, res) =>
|
||||
app.post("/profile/:playerId/hideLeaderboard", async (req, res) =>
|
||||
{
|
||||
const token = req.headers["x-auth-token"];
|
||||
const token = req.headers[ "x-auth-token" ];
|
||||
|
||||
if (!token)
|
||||
{
|
||||
@ -93,14 +93,58 @@ export class AdminRoute
|
||||
return;
|
||||
}
|
||||
|
||||
await MProfile.updateOne({id: player.id}, {
|
||||
dispatcherTime: 0,
|
||||
trainTime: 0,
|
||||
trainDistance: 0,
|
||||
trainPoints: 0,
|
||||
player.flags.push("leaderboard_hidden");
|
||||
|
||||
trainStats: {},
|
||||
dispatcherStats: {},
|
||||
await MProfile.updateOne({ id: player.id }, {
|
||||
flags: player.flags,
|
||||
});
|
||||
|
||||
res.json(
|
||||
new SuccessResponseBuilder()
|
||||
.setCode(200)
|
||||
.setData({})
|
||||
.toJSON(),
|
||||
);
|
||||
});
|
||||
|
||||
app.post("/profile/:playerId/showLeaderboard", async (req, res) =>
|
||||
{
|
||||
const token = req.headers[ "x-auth-token" ];
|
||||
|
||||
if (!token)
|
||||
{
|
||||
res.status(400).json(new ErrorResponseBuilder()
|
||||
.setCode(400)
|
||||
.setData("Missing token query").toJSON());
|
||||
return;
|
||||
}
|
||||
|
||||
const admin = await MAdmin.findOne({ token });
|
||||
|
||||
if (!admin)
|
||||
{
|
||||
res.status(401).json(new ErrorResponseBuilder()
|
||||
.setCode(401)
|
||||
.setData("Invalid token").toJSON());
|
||||
return;
|
||||
}
|
||||
|
||||
const player = await MProfile.findOne({
|
||||
id: req.params.playerId,
|
||||
});
|
||||
|
||||
if (!player)
|
||||
{
|
||||
res.status(401).json(new ErrorResponseBuilder()
|
||||
.setCode(401)
|
||||
.setData("Invalid playerId").toJSON());
|
||||
return;
|
||||
}
|
||||
|
||||
player.flags = player.flags.filter(x => x !== "leaderboard_hidden");
|
||||
|
||||
await MProfile.updateOne({ id: player.id }, {
|
||||
flags: player.flags,
|
||||
});
|
||||
|
||||
res.json(
|
||||
@ -113,7 +157,7 @@ export class AdminRoute
|
||||
|
||||
app.post("/profile/:playerId/hide", async (req, res) =>
|
||||
{
|
||||
const token = req.headers["x-auth-token"];
|
||||
const token = req.headers[ "x-auth-token" ];
|
||||
|
||||
if (!token)
|
||||
{
|
||||
@ -147,7 +191,7 @@ export class AdminRoute
|
||||
|
||||
player.flags.push("hidden");
|
||||
|
||||
await MProfile.updateOne({id: player.id}, {
|
||||
await MProfile.updateOne({ id: player.id }, {
|
||||
flags: player.flags,
|
||||
});
|
||||
|
||||
|
@ -48,7 +48,7 @@ export class LeaderboardRoute
|
||||
const filter: PipelineStage[] = [
|
||||
{
|
||||
$match: {
|
||||
flags: { $nin: ["hidden"] }
|
||||
flags: { $nin: ["hidden", "leaderboard_hidden"] }
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -83,7 +83,7 @@ export class LeaderboardRoute
|
||||
const filter: PipelineStage[] = [
|
||||
{
|
||||
$match: {
|
||||
flags: { $nin: ["hidden"] }
|
||||
flags: { $nin: ["hidden", "leaderboard_hidden"] }
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -85,6 +85,23 @@ export class StationsModule
|
||||
player.steamTrainScore = stats?.stats?.find(x => x.name === "SCORE")?.value ?? 0;
|
||||
|
||||
|
||||
if ((player.steamTrainDistance > player.trainDistance) || (player.trainPoints > player.steamTrainScore))
|
||||
{
|
||||
player.trainStats[ "N/A" ] = {
|
||||
time: 0, distance: player.steamTrainDistance > player.trainDistance ? player.steamTrainDistance - player.trainDistance : player.trainDistance,
|
||||
score: player.trainPoints > player.steamTrainScore ? player.steamTrainScore - player.trainPoints : player.trainPoints,
|
||||
};
|
||||
|
||||
if (player.steamTrainDistance > player.trainDistance)
|
||||
{
|
||||
player.trainDistance = player.steamTrainDistance;
|
||||
}
|
||||
if (player.trainPoints > player.steamTrainScore)
|
||||
{
|
||||
player.trainPoints = player.steamTrainScore;
|
||||
}
|
||||
}
|
||||
|
||||
player.flags = player.flags.filter(x => x !== "private");
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,23 @@ export class TrainsModule
|
||||
player.steamDispatcherTime = stats?.stats?.find(x => x.name === "DISPATCHER_TIME")?.value ?? 0;
|
||||
player.steamTrainScore = stats?.stats?.find(x => x.name === "SCORE")?.value ?? 0;
|
||||
|
||||
if ((player.steamTrainDistance > player.trainDistance) || (player.trainPoints > player.steamTrainScore))
|
||||
{
|
||||
player.trainStats[ "N/A" ] = {
|
||||
time: 0, distance: player.steamTrainDistance > player.trainDistance ? player.steamTrainDistance - player.trainDistance : player.trainDistance,
|
||||
score: player.trainPoints > player.steamTrainScore ? player.steamTrainScore - player.trainPoints : player.trainPoints,
|
||||
};
|
||||
|
||||
if (player.steamTrainDistance > player.trainDistance)
|
||||
{
|
||||
player.trainDistance = player.steamTrainDistance;
|
||||
}
|
||||
if (player.trainPoints > player.steamTrainScore)
|
||||
{
|
||||
player.trainPoints = player.steamTrainScore;
|
||||
}
|
||||
}
|
||||
|
||||
player.flags = player.flags.filter(x => x !== "private");
|
||||
}
|
||||
|
||||
|
24
packages/frontend/src/components/mini/util/UserIcons.tsx
Normal file
24
packages/frontend/src/components/mini/util/UserIcons.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Aleksander <alekswilc> Wilczyński (aleks@alekswilc.dev)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* See LICENSE for more.
|
||||
*/
|
||||
import { FaUserShield, FaUserSlash, FaUserLock } from "react-icons/fa6";
|
||||
|
||||
export const UserIcons = ({ flags }: { flags: string[] }) =>
|
||||
{
|
||||
return <> { flags.includes("administrator") &&
|
||||
<FaUserShield className={ "inline text-meta-1 ml-1" }/> } { flags.includes("leaderboard_hidden") &&
|
||||
<FaUserLock className={ "inline text-meta-6 ml-1" }/> } { flags.includes("hidden") &&
|
||||
<FaUserSlash className={ "inline text-meta-1 ml-1" }/> }</>;
|
||||
};
|
@ -16,8 +16,8 @@
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { TActiveStationPlayersData } from "../../../types/active.ts";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
export const ActiveStationTable = ({ stations }: { stations: TActiveStationPlayersData[] }) =>
|
||||
{
|
||||
@ -65,8 +65,8 @@ export const ActiveStationTable = ({ stations }: { stations: TActiveStationPlaye
|
||||
<div className="flex justify-center items-center gap-3 p-5 lg:p-5">
|
||||
<p className="text-black dark:text-white sm:block break-all">
|
||||
<Link to={ "/profile/" + station.steam }
|
||||
className="color-orchid">{ station.username }</Link> { station.player.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
className="color-orchid">{ station.username }</Link> <UserIcons
|
||||
flags={ station.player.flags }/>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { TActiveTrainPlayersData } from "../../../types/active.ts";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
export const ActiveTrainTable = ({ trains }: {
|
||||
trains: TActiveTrainPlayersData[],
|
||||
}) =>
|
||||
@ -70,8 +71,8 @@ export const ActiveTrainTable = ({ trains }: {
|
||||
<div className="flex items-center justify-center gap-3 p-5 lg:p-5">
|
||||
<p className="text-black dark:text-white sm:block break-all">
|
||||
<Link to={ "/profile/" + train.steam }
|
||||
className="color-orchid">{ train.username }</Link> { train.player.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
className="color-orchid">{ train.username }</Link> <UserIcons
|
||||
flags={ train.player.flags }/>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -18,7 +18,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { TLeaderboardRecord } from "../../../types/leaderboard.ts";
|
||||
import { formatTime } from "../../../util/time.ts";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
export const StationTable = ({ stations }: { stations: TLeaderboardRecord[] }) =>
|
||||
{
|
||||
@ -58,8 +58,8 @@ export const StationTable = ({ stations }: { stations: TLeaderboardRecord[] }) =
|
||||
<div className="flex justify-center items-center gap-3 p-5 lg:p-5">
|
||||
<p className="text-black dark:text-white sm:block break-all">
|
||||
<Link to={ "/profile/" + station.id }
|
||||
className="color-orchid">{ station.username }</Link> { station.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
className="color-orchid">{ station.username }</Link> <UserIcons flags={station.flags} />
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -18,9 +18,9 @@ import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { TLeaderboardRecord } from "../../../types/leaderboard.ts";
|
||||
import { formatTime } from "../../../util/time.ts";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import { FlexArrowIcon } from "../../mini/icons/ArrowIcon.tsx";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
export const TrainTable = ({ trains, setSortBy, sortBy }: {
|
||||
trains: TLeaderboardRecord[],
|
||||
@ -80,8 +80,7 @@ export const TrainTable = ({ trains, setSortBy, sortBy }: {
|
||||
<div className="flex items-center justify-center gap-3 p-5 lg:p-5">
|
||||
<p className="text-black dark:text-white sm:block break-all">
|
||||
<Link to={ "/profile/" + train.id }
|
||||
className="color-orchid">{ train.username }</Link> { train.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
className="color-orchid">{ train.username }</Link> <UserIcons flags={train.flags} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -19,7 +19,8 @@ import { TLogStationData } from "../../../types/log.ts";
|
||||
import dayjs from "dayjs";
|
||||
import { toast } from "react-toastify";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FaCheck } from 'react-icons/fa6';
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
|
||||
export const StationLog = ({ data }: { data: TLogStationData }) =>
|
||||
{
|
||||
@ -50,7 +51,7 @@ export const StationLog = ({ data }: { data: TLogStationData }) =>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<h3 className="mb-1.5 text-2xl font-semibold text-black dark:text-white">
|
||||
{ data.player.username }{ data.player.flags.includes('verified') && <FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
{ data.player.username } <UserIcons flags={data.player.flags} />
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -19,7 +19,7 @@ import { TLogTrainData } from "../../../types/log.ts";
|
||||
import dayjs from "dayjs";
|
||||
import { toast } from "react-toastify";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
|
||||
export const TrainLog = ({ data }: { data: TLogTrainData }) =>
|
||||
@ -51,8 +51,7 @@ export const TrainLog = ({ data }: { data: TLogTrainData }) =>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<h3 className="mb-1.5 text-2xl font-semibold text-black dark:text-white">
|
||||
{ data.player.username } { data.player.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
{ data.player.username } <UserIcons flags={data.player.flags} />
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -17,11 +17,8 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { TStationRecord } from "../../../types/station.ts";
|
||||
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
// setSearchItem: Dispatch<SetStateAction<string>>
|
||||
export const StationTable = ({ stations }: {
|
||||
@ -68,8 +65,7 @@ export const StationTable = ({ stations }: {
|
||||
<div className="flex items-center justify-center gap-3 p-2.5 lg:p-5">
|
||||
<p className="text-black dark:text-white sm:block break-all">
|
||||
<Link to={ "/profile/" + (station.steam ?? station.player.id) }
|
||||
className="color-orchid">{ station.username ?? station.player.username }</Link> { station.player.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
className="color-orchid">{ station.username ?? station.player.username }</Link> <UserIcons flags={station.player.flags} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -18,7 +18,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { TTrainRecord } from "../../../types/train.ts";
|
||||
import dayjs from "dayjs";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
// setSearchItem: Dispatch<SetStateAction<string>>
|
||||
export const TrainTable = ({ trains }: {
|
||||
@ -75,8 +75,7 @@ export const TrainTable = ({ trains }: {
|
||||
<div className="flex items-center justify-center gap-3 p-2.5 lg:p-5">
|
||||
<p className="text-black dark:text-white sm:block break-all">
|
||||
<Link to={ "/profile/" + (train.steam ?? train.player.id) }
|
||||
className="color-orchid">{ train.username ?? train.player.username }</Link> { train.player.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
className="color-orchid">{ train.username ?? train.player.username }</Link> <UserIcons flags={train.player.flags} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -19,12 +19,12 @@ import { TProfileData } from "../../../types/profile.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ArrowIcon, FlexArrowIcon } from "../../mini/icons/ArrowIcon.tsx";
|
||||
import { formatTime } from "../../../util/time.ts";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { useAuth } from "../../../hooks/useAuth.tsx";
|
||||
import { ConfirmModal } from "../../mini/modal/ConfirmModal.tsx";
|
||||
import { post } from "../../../util/fetcher.ts";
|
||||
import { toast } from "react-toastify";
|
||||
import dayjs from 'dayjs';
|
||||
import dayjs from "dayjs";
|
||||
import { UserIcons } from "../../mini/util/UserIcons.tsx";
|
||||
|
||||
export const ProfileCard = ({ data }: { data: TProfileData }) =>
|
||||
{
|
||||
@ -32,19 +32,19 @@ export const ProfileCard = ({ data }: { data: TProfileData }) =>
|
||||
const [ showTrains, setShowTrains ] = useState(false);
|
||||
const [ showStations, setShowStations ] = useState(false);
|
||||
const [ sortTrainsBy, setSortTrainsBy ] = useState<"time" | "score" | "distance">("distance");
|
||||
const [ clearStatsModal, setClearStatsModal ] = useState(false);
|
||||
const [ hideLeaderboardStatsModal, setHideLeaderboardStatsModal ] = useState(false);
|
||||
const [ hideProfileModal, setHideProfileModal ] = useState(false);
|
||||
|
||||
const { isAdmin, token } = useAuth();
|
||||
|
||||
const adminClearPlayerStats = () =>
|
||||
const adminToggleHideLeaderboardPlayerProfile = () =>
|
||||
{
|
||||
post(`/admin/profile/${ data.player.id }/clear`, {}, { "X-Auth-Token": token })
|
||||
post(`/admin/profile/${ data.player.id }/${ data.player.flags.includes("leaderboard_hidden") ? "showLeaderboard" : "hideLeaderboard" }`, {}, { "X-Auth-Token": token })
|
||||
.then((response) =>
|
||||
{
|
||||
if (response.code === 200)
|
||||
{
|
||||
toast.success(t("admin.clear.alert"));
|
||||
toast.success(t("admin.hideLeaderboard.alert"));
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -64,14 +64,12 @@ export const ProfileCard = ({ data }: { data: TProfileData }) =>
|
||||
|
||||
const { t } = useTranslation();
|
||||
return <>
|
||||
<ConfirmModal showModal={ clearStatsModal } setShowModal={ setClearStatsModal }
|
||||
onConfirm={ adminClearPlayerStats } title={ t("admin.clear.modal.title") }
|
||||
description={ t("admin.clear.modal.description") }/>
|
||||
|
||||
<ConfirmModal showModal={ hideLeaderboardStatsModal } setShowModal={ setHideLeaderboardStatsModal }
|
||||
onConfirm={ adminToggleHideLeaderboardPlayerProfile } title={ t("admin.hideLeaderboard.modal.title") }
|
||||
description={ t("admin.hideLeaderboard.modal.description") }/>
|
||||
<ConfirmModal showModal={ hideProfileModal } setShowModal={ setHideProfileModal }
|
||||
onConfirm={ adminHidePlayerProfile } title={ t("admin.hide.modal.title") }
|
||||
description={ t("admin.hide.modal.description") }/>
|
||||
|
||||
<div
|
||||
className="overflow-hidden rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark">
|
||||
<div className="px-4 pt-6 text-center lg:pb-8 xl:pb-11.5">
|
||||
@ -83,8 +81,7 @@ export const ProfileCard = ({ data }: { data: TProfileData }) =>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<h3 className="mb-1.5 text-2xl font-semibold text-black dark:text-white">
|
||||
{ data.player.username } { data.player.flags.includes("verified") &&
|
||||
<FaCheck className={ "inline text-meta-3 ml-1" }/> }
|
||||
{ data.player.username } <UserIcons flags={ data.player.flags }/>
|
||||
</h3>
|
||||
|
||||
<div
|
||||
@ -223,20 +220,24 @@ export const ProfileCard = ({ data }: { data: TProfileData }) =>
|
||||
|
||||
|
||||
{ isAdmin && <>
|
||||
|
||||
|
||||
<div className="shadow-default dark:bg-boxdark items-center justify-center p-2.5 flex flex-col xl:p-5 gap-2">
|
||||
<h1 className="text-xl text-black dark:text-white">Moderator actions</h1>
|
||||
<h1 className="text-xl text-black dark:text-white">{ t("admin.header") }</h1>
|
||||
|
||||
<div className="items-center justify-center p-2.5 flex xl:p-5 gap-2 flex-wrap sm:flex-nowrap">
|
||||
<button className="inline-flex items-center justify-center rounded-md bg-danger py-2 px-5 text-center font-medium text-white hover:bg-opacity-50 lg:px-4 xl:px-5"
|
||||
onClick={ () => setClearStatsModal(true) }>
|
||||
{t("admin.clear.button")}
|
||||
</button>
|
||||
|
||||
{ data.player.flags.includes("leaderboard_hidden") ?
|
||||
<button className={ "inline-flex items-center justify-center rounded-md py-2 px-5 text-center font-medium text-white hover:bg-opacity-50 lg:px-4 xl:px-5 bg-success" }
|
||||
onClick={ () => adminToggleHideLeaderboardPlayerProfile() }>
|
||||
{ t("admin.hideLeaderboard.button2") }
|
||||
</button> :
|
||||
<button className={ "inline-flex items-center justify-center rounded-md py-2 px-5 text-center font-medium text-white hover:bg-opacity-50 lg:px-4 xl:px-5 bg-danger" }
|
||||
onClick={ () => setHideLeaderboardStatsModal(true) }>
|
||||
{ t("admin.hideLeaderboard.button") }
|
||||
</button> }
|
||||
|
||||
<button className="inline-flex items-center justify-center rounded-md bg-danger py-2 px-5 text-center font-medium text-white hover:bg-opacity-50 lg:px-4 xl:px-5"
|
||||
onClick={ () => setHideProfileModal(true) }>
|
||||
{t("admin.hide.button")}
|
||||
{ t("admin.hide.button") }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -244,7 +245,7 @@ export const ProfileCard = ({ data }: { data: TProfileData }) =>
|
||||
|
||||
<div className="shadow-default dark:bg-boxdark items-center justify-center p-2.5 flex flex-col xl:p-5 gap-2">
|
||||
<h1 className="text-sm text-black dark:text-white">
|
||||
{t("profile.info", { date: dayjs(data.player.createdAt).format('DD/MM/YYYY') })}
|
||||
{ t("profile.info", { date: dayjs(data.player.createdAt).format("DD/MM/YYYY") }) }
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
@ -154,13 +154,15 @@
|
||||
"logout": "Log out"
|
||||
},
|
||||
"admin": {
|
||||
"clear": {
|
||||
"header": "Akcje moderacyjne",
|
||||
"hideLeaderboard": {
|
||||
"modal": {
|
||||
"title": "Are you sure?",
|
||||
"description": "This action will permanently clear user statistics."
|
||||
"description": "This action will hide user profile from leaderboard."
|
||||
},
|
||||
"button": "Clear profile",
|
||||
"alert": "Player stats cleared."
|
||||
"button": "Hide profile in leaderboard",
|
||||
"button2": "Show profile in leaderboard",
|
||||
"alert": "Player profile hidden."
|
||||
},
|
||||
"hide": {
|
||||
"modal": {
|
||||
|
@ -154,13 +154,15 @@
|
||||
"logout": "Wyloguj"
|
||||
},
|
||||
"admin": {
|
||||
"clear": {
|
||||
"header": "Moderator actions",
|
||||
"hideLeaderboard": {
|
||||
"modal": {
|
||||
"title": "Czy jesteś pewien?",
|
||||
"description": "Ta akcja permanentnie wyczyści wszystkie statystyki gracza."
|
||||
"description": "Ta akcja ukryje profil gracza w tablicy wyników."
|
||||
},
|
||||
"button": "Wyczyść profil",
|
||||
"alert": "Wyczyszczono statystyki gracza."
|
||||
"button": "Ukryj profil w tablicy wyników",
|
||||
"button2": "Pokaż profil w tablicy wyników",
|
||||
"alert": "Ukryto profil gracza w tablicy wyników."
|
||||
},
|
||||
"hide": {
|
||||
"modal": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user