mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-08 12:16:12 -05:00
Merge branch 'rewrite' of https://github.com/Sendouc/sendou.ink into patch-2
This commit is contained in:
@@ -8,6 +8,7 @@ export function Input({
|
||||
defaultValue,
|
||||
leftAddon,
|
||||
pattern,
|
||||
list,
|
||||
"data-cy": dataCy,
|
||||
}: {
|
||||
name: string;
|
||||
@@ -17,6 +18,7 @@ export function Input({
|
||||
defaultValue?: string;
|
||||
leftAddon?: string;
|
||||
pattern?: string;
|
||||
list?: string;
|
||||
"data-cy"?: string;
|
||||
}) {
|
||||
return (
|
||||
@@ -27,8 +29,9 @@ export function Input({
|
||||
minLength={minLength}
|
||||
maxLength={maxLength}
|
||||
defaultValue={defaultValue}
|
||||
data-cy={dataCy}
|
||||
pattern={pattern}
|
||||
list={list}
|
||||
data-cy={dataCy}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
{ "name": "builds", "url": "builds" },
|
||||
{ "name": "analyzer", "url": "analyzer" },
|
||||
{ "name": "calendar", "url": "calendar" },
|
||||
{ "name": "maps", "url": "maps" },
|
||||
{ "name": "badges", "url": "badges" },
|
||||
{
|
||||
"name": "plus",
|
||||
|
||||
@@ -4,7 +4,6 @@ import * as plusVotes from "./models/plusVotes/queries.server";
|
||||
import * as badges from "./models/badges/queries.server";
|
||||
import * as calendarEvents from "./models/calendar/queries.server";
|
||||
import * as builds from "./models/builds/queries.server";
|
||||
import * as maps from "./models/maps/queries.server";
|
||||
|
||||
export const db = {
|
||||
users,
|
||||
@@ -13,5 +12,4 @@ export const db = {
|
||||
badges,
|
||||
calendarEvents,
|
||||
builds,
|
||||
maps,
|
||||
};
|
||||
|
||||
4
app/db/models/calendar/createMapPoolMap.sql
Normal file
4
app/db/models/calendar/createMapPoolMap.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
insert into
|
||||
"MapPoolMap" ("calendarEventId", "stageId", "mode")
|
||||
values
|
||||
(@calendarEventId, @stageId, @mode)
|
||||
4
app/db/models/calendar/deleteMapPoolMaps.sql
Normal file
4
app/db/models/calendar/deleteMapPoolMaps.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
delete from
|
||||
"MapPoolMap"
|
||||
where
|
||||
"calendarEventId" = @calendarEventId
|
||||
7
app/db/models/calendar/findMapPoolByEventId.sql
Normal file
7
app/db/models/calendar/findMapPoolByEventId.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
select
|
||||
"stageId",
|
||||
"mode"
|
||||
from
|
||||
"MapPoolMap"
|
||||
where
|
||||
"calendarEventId" = @calendarEventId
|
||||
@@ -9,7 +9,9 @@ import type {
|
||||
CalendarEventBadge,
|
||||
CalendarEventResultTeam,
|
||||
CalendarEventResultPlayer,
|
||||
MapPoolMap,
|
||||
} from "../../types";
|
||||
import { mapPoolListToMapPoolObject } from "~/modules/map-list-generator";
|
||||
|
||||
import createSql from "./create.sql";
|
||||
import updateSql from "./update.sql";
|
||||
@@ -31,6 +33,9 @@ import findBadgesByEventIdSql from "./findBadgesByEventId.sql";
|
||||
import eventsToReportSql from "./eventsToReport.sql";
|
||||
import recentWinnersSql from "./recentWinners.sql";
|
||||
import upcomingEventsSql from "./upcomingEvents.sql";
|
||||
import createMapPoolMapSql from "./createMapPoolMap.sql";
|
||||
import deleteMapPoolMapsSql from "./deleteMapPoolMaps.sql";
|
||||
import findMapPoolByEventIdSql from "./findMapPoolByEventId.sql";
|
||||
|
||||
const createStm = sql.prepare(createSql);
|
||||
const updateStm = sql.prepare(updateSql);
|
||||
@@ -38,6 +43,9 @@ const createDateStm = sql.prepare(createDateSql);
|
||||
const deleteDatesByEventIdStm = sql.prepare(deleteDatesByEventIdSql);
|
||||
const createBadgeStm = sql.prepare(createBadgeSql);
|
||||
const deleteBadgesByEventIdStm = sql.prepare(deleteBadgesByEventIdSql);
|
||||
const createMapPoolMapStm = sql.prepare(createMapPoolMapSql);
|
||||
const deleteMapPoolMapsStm = sql.prepare(deleteMapPoolMapsSql);
|
||||
const findMapPoolByEventIdStm = sql.prepare(findMapPoolByEventIdSql);
|
||||
|
||||
export type CreateArgs = Pick<
|
||||
CalendarEvent,
|
||||
@@ -50,9 +58,15 @@ export type CreateArgs = Pick<
|
||||
> & {
|
||||
startTimes: Array<CalendarEventDate["startTime"]>;
|
||||
badges: Array<CalendarEventBadge["badgeId"]>;
|
||||
mapPoolMaps?: Array<Pick<MapPoolMap, "mode" | "stageId">>;
|
||||
};
|
||||
export const create = sql.transaction(
|
||||
({ startTimes, badges, ...calendarEventArgs }: CreateArgs) => {
|
||||
({
|
||||
startTimes,
|
||||
badges,
|
||||
mapPoolMaps = [],
|
||||
...calendarEventArgs
|
||||
}: CreateArgs) => {
|
||||
const createdEvent = createStm.get(calendarEventArgs) as CalendarEvent;
|
||||
|
||||
for (const startTime of startTimes) {
|
||||
@@ -69,6 +83,13 @@ export const create = sql.transaction(
|
||||
});
|
||||
}
|
||||
|
||||
for (const mapPoolArgs of mapPoolMaps) {
|
||||
createMapPoolMapStm.run({
|
||||
calendarEventId: createdEvent.id,
|
||||
...mapPoolArgs,
|
||||
});
|
||||
}
|
||||
|
||||
return createdEvent.id;
|
||||
}
|
||||
);
|
||||
@@ -78,6 +99,7 @@ export const update = sql.transaction(
|
||||
startTimes,
|
||||
badges,
|
||||
eventId,
|
||||
mapPoolMaps = [],
|
||||
...calendarEventArgs
|
||||
}: Omit<CreateArgs, "authorId"> & { eventId: CalendarEvent["id"] }) => {
|
||||
updateStm.run({ ...calendarEventArgs, eventId });
|
||||
@@ -97,6 +119,14 @@ export const update = sql.transaction(
|
||||
badgeId,
|
||||
});
|
||||
}
|
||||
|
||||
deleteMapPoolMapsStm.run({ calendarEventId: eventId });
|
||||
for (const mapPoolArgs of mapPoolMaps) {
|
||||
createMapPoolMapStm.run({
|
||||
calendarEventId: eventId,
|
||||
...mapPoolArgs,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -410,6 +440,16 @@ export function findBadgesByEventId(eventId: CalendarEvent["id"]) {
|
||||
>;
|
||||
}
|
||||
|
||||
export function findMapPoolByEventId(calendarEventId: CalendarEvent["id"]) {
|
||||
const rows = findMapPoolByEventIdStm.all({ calendarEventId }) as Array<
|
||||
Pick<MapPoolMap, "stageId" | "mode">
|
||||
>;
|
||||
|
||||
if (rows.length === 0) return;
|
||||
|
||||
return mapPoolListToMapPoolObject(rows);
|
||||
}
|
||||
|
||||
const eventsToReportStm = sql.prepare(eventsToReportSql);
|
||||
export function eventsToReport(authorId?: CalendarEvent["authorId"]) {
|
||||
if (!authorId) return [];
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
insert into
|
||||
"MapPool" ("code", "ownerId")
|
||||
values
|
||||
(@code, @ownerId) returning *
|
||||
@@ -1,4 +0,0 @@
|
||||
insert into
|
||||
"MapPoolMap" ("mapPoolId", "stageId", "mode")
|
||||
values
|
||||
(@mapPoolId, @stageId, @mode)
|
||||
@@ -1,22 +0,0 @@
|
||||
select
|
||||
"MapPool"."id",
|
||||
"MapPool"."code",
|
||||
"MapPool"."ownerId",
|
||||
"User"."discordName",
|
||||
"User"."discordDiscriminator",
|
||||
json_group_array(
|
||||
json_object(
|
||||
'stageId',
|
||||
"MapPoolMap"."stageId",
|
||||
'mode',
|
||||
"MapPoolMap"."mode"
|
||||
)
|
||||
) as "maps"
|
||||
from
|
||||
"MapPool"
|
||||
left join "MapPoolMap" on "MapPoolMap"."mapPoolId" = "MapPool"."id"
|
||||
left join "User" on "User"."id" = "MapPool"."ownerId"
|
||||
where
|
||||
code = lower(@code)
|
||||
group by
|
||||
"MapPool"."id"
|
||||
@@ -1,55 +0,0 @@
|
||||
import { sql } from "~/db/sql";
|
||||
import type { MapPool, MapPoolMap, User } from "~/db/types";
|
||||
import createMapPoolSql from "./createMapPool.sql";
|
||||
import createMapPoolMapSql from "./createMapPoolMap.sql";
|
||||
import findMapPoolByCodeSql from "./findMapPoolByCode.sql";
|
||||
|
||||
const createMapPoolStm = sql.prepare(createMapPoolSql);
|
||||
const createMapPoolMapStm = sql.prepare(createMapPoolMapSql);
|
||||
const findMapPoolByCodeStm = sql.prepare(findMapPoolByCodeSql);
|
||||
|
||||
export const addMapPool = sql.transaction(
|
||||
({
|
||||
ownerId,
|
||||
code,
|
||||
maps,
|
||||
}: {
|
||||
ownerId: MapPool["id"];
|
||||
code: MapPool["code"];
|
||||
maps: Array<Pick<MapPoolMap, "mode" | "stageId">>;
|
||||
}) => {
|
||||
const mapPool = createMapPoolStm.get({ ownerId, code }) as MapPool;
|
||||
|
||||
for (const args of maps) {
|
||||
createMapPoolMapStm.run({
|
||||
mapPoolId: mapPool.id,
|
||||
...args,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export function findMapPoolByCode(code: MapPool["code"]) {
|
||||
const row = findMapPoolByCodeStm.get({ code });
|
||||
if (!row) return;
|
||||
|
||||
return {
|
||||
id: row.id,
|
||||
code: row.code,
|
||||
owner: {
|
||||
id: row.ownerId,
|
||||
discordName: row.discordName,
|
||||
discordDiscriminator: row.discordDiscriminator,
|
||||
},
|
||||
maps: JSON.parse(row.maps),
|
||||
} as {
|
||||
id: MapPool["id"];
|
||||
code: MapPool["code"];
|
||||
owner: {
|
||||
id: User["id"];
|
||||
discordName: User["discordName"];
|
||||
discordDiscriminator: User["discordDiscriminator"];
|
||||
};
|
||||
maps: Array<Pick<MapPoolMap, "mode" | "stageId">>;
|
||||
};
|
||||
}
|
||||
@@ -155,14 +155,8 @@ export interface BuildAbility {
|
||||
slotIndex: 0 | 1 | 2 | 3;
|
||||
}
|
||||
|
||||
export interface MapPool {
|
||||
id: number;
|
||||
code: string;
|
||||
ownerId: number;
|
||||
}
|
||||
|
||||
export interface MapPoolMap {
|
||||
mapPoolId: number;
|
||||
calendarEventId?: number;
|
||||
stageId: StageId;
|
||||
mode: ModeShort;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { generateMapList } from "./map-list";
|
||||
export { modesOrder } from "./modes";
|
||||
export { mapPoolToNonEmptyModes } from "./utils";
|
||||
export { mapPoolToNonEmptyModes, mapPoolListToMapPoolObject } from "./utils";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { MapPoolMap } from "~/db/types";
|
||||
import type { ModeShort } from "../in-game-lists";
|
||||
import type { MapPool } from "../map-pool-serializer";
|
||||
|
||||
@@ -12,3 +13,21 @@ export function mapPoolToNonEmptyModes(mapPool: MapPool) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mapPoolListToMapPoolObject(
|
||||
mapPoolList: Array<Pick<MapPoolMap, "stageId" | "mode">>
|
||||
) {
|
||||
const result: MapPool = {
|
||||
TW: [],
|
||||
SZ: [],
|
||||
TC: [],
|
||||
RM: [],
|
||||
CB: [],
|
||||
};
|
||||
|
||||
for (const { stageId, mode } of mapPoolList) {
|
||||
result[mode].push(stageId);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { ModeShort } from "../in-game-lists";
|
||||
import type { StageId } from "../in-game-lists";
|
||||
|
||||
// xxx: rename - same name as DB table
|
||||
export type MapPool = Record<ModeShort, StageId[]>;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { LinkButton } from "~/components/Button";
|
||||
import { Image } from "~/components/Image";
|
||||
import { Main } from "~/components/Main";
|
||||
import { Section } from "~/components/Section";
|
||||
import { db } from "~/db";
|
||||
@@ -23,21 +24,28 @@ import {
|
||||
canEditCalendarEvent,
|
||||
canReportCalendarEventWinners,
|
||||
} from "~/permissions";
|
||||
import styles from "~/styles/calendar-event.css";
|
||||
import calendarStyles from "~/styles/calendar-event.css";
|
||||
import mapsStyles from "~/styles/maps.css";
|
||||
import { databaseTimestampToDate } from "~/utils/dates";
|
||||
import { notFoundIfFalsy } from "~/utils/remix";
|
||||
import { discordFullName, makeTitle, placementString } from "~/utils/strings";
|
||||
import {
|
||||
calendarEditPage,
|
||||
calendarReportWinnersPage,
|
||||
mapsPage,
|
||||
navIconUrl,
|
||||
resolveBaseUrl,
|
||||
userPage,
|
||||
} from "~/utils/urls";
|
||||
import { actualNumber, id } from "~/utils/zod";
|
||||
import { MapPoolSelector } from "../components/MapPoolSelector";
|
||||
import { Tags } from "../components/Tags";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
return [
|
||||
{ rel: "stylesheet", href: calendarStyles },
|
||||
{ rel: "stylesheet", href: mapsStyles },
|
||||
];
|
||||
};
|
||||
|
||||
export const meta: MetaFunction = (args) => {
|
||||
@@ -52,7 +60,7 @@ export const meta: MetaFunction = (args) => {
|
||||
};
|
||||
|
||||
export const handle = {
|
||||
i18n: "calendar",
|
||||
i18n: ["calendar", "game-misc"],
|
||||
};
|
||||
|
||||
export const loader = async ({ params, request }: LoaderArgs) => {
|
||||
@@ -67,6 +75,7 @@ export const loader = async ({ params, request }: LoaderArgs) => {
|
||||
badgePrizes: db.calendarEvents.findBadgesByEventId(parsedParams.id),
|
||||
title: makeTitle([event.name, t("pages.calendar")]),
|
||||
results: db.calendarEvents.findResultsByEventId(parsedParams.id),
|
||||
mapPool: db.calendarEvents.findMapPoolByEventId(parsedParams.id),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -159,6 +168,7 @@ export default function CalendarEventPage() {
|
||||
</div>
|
||||
</section>
|
||||
<Results />
|
||||
<MapPoolInfo />
|
||||
<Description />
|
||||
</Main>
|
||||
);
|
||||
@@ -222,6 +232,30 @@ function Results() {
|
||||
);
|
||||
}
|
||||
|
||||
function MapPoolInfo() {
|
||||
const { t } = useTranslation(["calendar"]);
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
if (!data.mapPool) return null;
|
||||
|
||||
return (
|
||||
<Section title="Map pool">
|
||||
<div className="event__map-pool-section">
|
||||
<MapPoolSelector mapPool={data.mapPool} />
|
||||
<LinkButton
|
||||
className="event__create-map-list-link"
|
||||
to={mapsPage(data.event.eventId)}
|
||||
variant="outlined"
|
||||
tiny
|
||||
>
|
||||
<Image alt="" path={navIconUrl("maps")} width={22} height={22} />
|
||||
{t("calendar:createMapList")}
|
||||
</LinkButton>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function Description() {
|
||||
const { t } = useTranslation();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
@@ -233,9 +267,11 @@ function Description() {
|
||||
<Avatar user={data.event} size="xs" />
|
||||
{discordFullName(data.event)}
|
||||
</div>
|
||||
<div data-cy="event-description" className="whitespace-pre-wrap">
|
||||
{data.event.description}
|
||||
</div>
|
||||
{data.event.description && (
|
||||
<div data-cy="event-description" className="whitespace-pre-wrap">
|
||||
{data.event.description}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
|
||||
96
app/routes/calendar/components/MapPoolSelector.tsx
Normal file
96
app/routes/calendar/components/MapPoolSelector.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import clsx from "clsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Image } from "~/components/Image";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import { modes, stageIds } from "~/modules/in-game-lists";
|
||||
import { type MapPool } from "~/modules/map-pool-serializer";
|
||||
import { modeImageUrl, stageImageUrl } from "~/utils/urls";
|
||||
|
||||
export function MapPoolSelector({
|
||||
mapPool,
|
||||
handleMapPoolChange,
|
||||
}: {
|
||||
mapPool: MapPool;
|
||||
handleMapPoolChange?: ({
|
||||
mode,
|
||||
stageId,
|
||||
}: {
|
||||
mode: ModeShort;
|
||||
stageId: StageId;
|
||||
}) => void;
|
||||
}) {
|
||||
const { t } = useTranslation(["game-misc", "calendar"]);
|
||||
|
||||
const isPresentational = !handleMapPoolChange;
|
||||
|
||||
const stageRowIsVisible = (stageId: StageId) => {
|
||||
if (!isPresentational) return true;
|
||||
|
||||
return modes.some((mode) => mapPool[mode.short].includes(stageId));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="stack md">
|
||||
{stageIds.filter(stageRowIsVisible).map((stageId) => (
|
||||
<div key={stageId} className="maps__stage-row">
|
||||
<Image
|
||||
className="maps__stage-image"
|
||||
alt=""
|
||||
path={stageImageUrl(stageId)}
|
||||
width={80}
|
||||
height={45}
|
||||
/>
|
||||
<div className="maps__stage-name-row">
|
||||
<div>{t(`game-misc:STAGE_${stageId}`)}</div>
|
||||
<div className="maps__mode-buttons-container">
|
||||
{modes.map((mode) => {
|
||||
const selected = (mapPool[mode.short] as StageId[]).includes(
|
||||
stageId
|
||||
);
|
||||
|
||||
if (isPresentational && !selected) return null;
|
||||
if (isPresentational && selected) {
|
||||
return (
|
||||
<Image
|
||||
key={mode.short}
|
||||
className={clsx("maps__mode", {
|
||||
selected,
|
||||
})}
|
||||
alt={mode.long}
|
||||
path={modeImageUrl(mode.short)}
|
||||
width={33}
|
||||
height={33}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
key={mode.short}
|
||||
className={clsx("maps__mode-button", "outline-theme", {
|
||||
selected,
|
||||
})}
|
||||
onClick={() =>
|
||||
handleMapPoolChange?.({ mode: mode.short, stageId })
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<Image
|
||||
className={clsx("maps__mode", {
|
||||
selected,
|
||||
})}
|
||||
alt={mode.long}
|
||||
path={modeImageUrl(mode.short)}
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,31 +1,52 @@
|
||||
import { Form, useLoaderData } from "@remix-run/react";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import * as React from "react";
|
||||
import type { Badge as BadgeType, CalendarEventTag } from "~/db/types";
|
||||
import { CALENDAR_EVENT } from "~/constants";
|
||||
import { Button } from "~/components/Button";
|
||||
import type { SerializeFrom } from "@remix-run/node";
|
||||
import {
|
||||
json,
|
||||
redirect,
|
||||
type MetaFunction,
|
||||
type ActionFunction,
|
||||
type LinksFunction,
|
||||
type LoaderArgs,
|
||||
type MetaFunction,
|
||||
} from "@remix-run/node";
|
||||
import styles from "~/styles/calendar-new.css";
|
||||
import { Form, useLoaderData } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { Badge } from "~/components/Badge";
|
||||
import { Button } from "~/components/Button";
|
||||
import { DateInput } from "~/components/DateInput";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { TrashIcon } from "~/components/icons/Trash";
|
||||
import { Input } from "~/components/Input";
|
||||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import { Tags } from "./components/Tags";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { Toggle } from "~/components/Toggle";
|
||||
import { CALENDAR_EVENT } from "~/constants";
|
||||
import { db } from "~/db";
|
||||
import type { Badge as BadgeType, CalendarEventTag } from "~/db/types";
|
||||
import { useIsMounted } from "~/hooks/useIsMounted";
|
||||
import { requireUser } from "~/modules/auth";
|
||||
import { Badge } from "~/components/Badge";
|
||||
import { z } from "zod";
|
||||
import { i18next } from "~/modules/i18n";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import {
|
||||
mapPoolToSerializedString,
|
||||
serializedStringToMapPool,
|
||||
type MapPool,
|
||||
} from "~/modules/map-pool-serializer";
|
||||
import { canEditCalendarEvent } from "~/permissions";
|
||||
import calendarNewStyles from "~/styles/calendar-new.css";
|
||||
import mapsStyles from "~/styles/maps.css";
|
||||
import {
|
||||
databaseTimestampToDate,
|
||||
dateToDatabaseTimestamp,
|
||||
} from "~/utils/dates";
|
||||
import {
|
||||
badRequestIfFalsy,
|
||||
parseRequestFormData,
|
||||
validate,
|
||||
} from "~/utils/remix";
|
||||
import { makeTitle } from "~/utils/strings";
|
||||
import { calendarEventPage } from "~/utils/urls";
|
||||
import {
|
||||
actualNumber,
|
||||
date,
|
||||
@@ -36,20 +57,8 @@ import {
|
||||
safeJSONParse,
|
||||
toArray,
|
||||
} from "~/utils/zod";
|
||||
import {
|
||||
badRequestIfFalsy,
|
||||
parseRequestFormData,
|
||||
validate,
|
||||
} from "~/utils/remix";
|
||||
import {
|
||||
databaseTimestampToDate,
|
||||
dateToDatabaseTimestamp,
|
||||
} from "~/utils/dates";
|
||||
import { calendarEventPage } from "~/utils/urls";
|
||||
import { makeTitle } from "~/utils/strings";
|
||||
import { i18next } from "~/modules/i18n";
|
||||
import { canEditCalendarEvent } from "~/permissions";
|
||||
import { DateInput } from "~/components/DateInput";
|
||||
import { MapPoolSelector } from "./components/MapPoolSelector";
|
||||
import { Tags } from "./components/Tags";
|
||||
|
||||
const MIN_DATE = new Date(Date.UTC(2015, 4, 28));
|
||||
|
||||
@@ -57,7 +66,10 @@ const MAX_DATE = new Date();
|
||||
MAX_DATE.setFullYear(MAX_DATE.getFullYear() + 1);
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
return [
|
||||
{ rel: "stylesheet", href: calendarNewStyles },
|
||||
{ rel: "stylesheet", href: mapsStyles },
|
||||
];
|
||||
};
|
||||
|
||||
export const meta: MetaFunction = (args) => {
|
||||
@@ -108,6 +120,7 @@ const newCalendarEventActionSchema = z.object({
|
||||
processMany(safeJSONParse, removeDuplicates),
|
||||
z.array(id).nullable()
|
||||
),
|
||||
pool: z.string().optional(),
|
||||
});
|
||||
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
@@ -134,6 +147,16 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
: data.tags,
|
||||
badges: data.badges ?? [],
|
||||
};
|
||||
|
||||
const deserializedMaps = (() => {
|
||||
if (!data.pool) return;
|
||||
|
||||
const mapPool = serializedStringToMapPool(data.pool);
|
||||
return Object.entries(mapPool).flatMap(([mode, stages]) =>
|
||||
stages.flatMap((stageId) => ({ mode: mode as ModeShort, stageId }))
|
||||
);
|
||||
})();
|
||||
|
||||
if (data.eventToEditId) {
|
||||
const eventToEdit = badRequestIfFalsy(
|
||||
db.calendarEvents.findById(data.eventToEditId)
|
||||
@@ -142,6 +165,7 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
|
||||
db.calendarEvents.update({
|
||||
eventId: data.eventToEditId,
|
||||
mapPoolMaps: deserializedMaps,
|
||||
...commonArgs,
|
||||
});
|
||||
|
||||
@@ -149,6 +173,7 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
} else {
|
||||
const createdEventId = db.calendarEvents.create({
|
||||
authorId: user.id,
|
||||
mapPoolMaps: deserializedMaps,
|
||||
...commonArgs,
|
||||
});
|
||||
|
||||
@@ -181,6 +206,7 @@ export const loader = async ({ request }: LoaderArgs) => {
|
||||
// "BADGE" tag is special and can't be edited like other tags
|
||||
tags: eventToEdit.tags.filter((tag) => tag !== "BADGE"),
|
||||
badges: db.calendarEvents.findBadgesByEventId(eventId),
|
||||
mapPool: db.calendarEvents.findMapPoolByEventId(eventId),
|
||||
}
|
||||
: undefined,
|
||||
title: makeTitle([canEditEvent ? "Edit" : "New", t("pages.calendar")]),
|
||||
@@ -192,7 +218,7 @@ export default function CalendarNewEventPage() {
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<Main halfWidth>
|
||||
<Main className="calendar-new__container">
|
||||
<Form className="stack md items-start" method="post">
|
||||
{eventToEdit && (
|
||||
<input
|
||||
@@ -208,6 +234,7 @@ export default function CalendarNewEventPage() {
|
||||
<DiscordLinkInput />
|
||||
<TagsAdder />
|
||||
<BadgesAdder />
|
||||
<MapPoolSection />
|
||||
<Button type="submit" className="mt-4" data-cy="submit-button">
|
||||
{t("actions.submit")}
|
||||
</Button>
|
||||
@@ -497,3 +524,64 @@ function BadgesAdder() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const DEFAULT_MAP_POOL = {
|
||||
SZ: [],
|
||||
TC: [],
|
||||
CB: [],
|
||||
RM: [],
|
||||
TW: [],
|
||||
};
|
||||
function MapPoolSection() {
|
||||
const { t } = useTranslation(["game-misc", "calendar"]);
|
||||
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const [mapPool, setMapPool] = React.useState<MapPool>(
|
||||
data.eventToEdit?.mapPool ?? DEFAULT_MAP_POOL
|
||||
);
|
||||
const [includeMapPool, setIncludeMapPool] = React.useState(
|
||||
Boolean(data.eventToEdit?.mapPool)
|
||||
);
|
||||
|
||||
const handleMapPoolChange = ({
|
||||
mode,
|
||||
stageId,
|
||||
}: {
|
||||
mode: ModeShort;
|
||||
stageId: StageId;
|
||||
}) => {
|
||||
const newMapPool = mapPool[mode].includes(stageId)
|
||||
? {
|
||||
...mapPool,
|
||||
[mode]: mapPool[mode].filter((id) => id !== stageId),
|
||||
}
|
||||
: {
|
||||
...mapPool,
|
||||
[mode]: [...mapPool[mode], stageId],
|
||||
};
|
||||
|
||||
setMapPool(newMapPool);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
{includeMapPool && (
|
||||
<input
|
||||
type="hidden"
|
||||
name="pool"
|
||||
value={mapPoolToSerializedString(mapPool)}
|
||||
/>
|
||||
)}
|
||||
<Label>{t("calendar:forms.mapPool")}</Label>
|
||||
<div className="stack md">
|
||||
<Toggle checked={includeMapPool} setChecked={setIncludeMapPool} tiny />
|
||||
{includeMapPool && (
|
||||
<MapPoolSelector
|
||||
mapPool={mapPool}
|
||||
handleMapPoolChange={handleMapPoolChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
BUILDS_PAGE,
|
||||
calendarEventPage,
|
||||
CALENDAR_PAGE,
|
||||
mapsPage,
|
||||
navIconUrl,
|
||||
plusSuggestionPage,
|
||||
userPage,
|
||||
@@ -85,6 +86,12 @@ export default function Index() {
|
||||
description={t("front:badges.description")}
|
||||
to={BADGES_PAGE}
|
||||
/>
|
||||
<FeatureCard
|
||||
navItem="maps"
|
||||
title={t("common:pages.maps")}
|
||||
description={t("front:maps.description")}
|
||||
to={mapsPage()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Main>
|
||||
|
||||
@@ -1,50 +1,47 @@
|
||||
import type {
|
||||
ActionFunction,
|
||||
LinksFunction,
|
||||
LoaderArgs,
|
||||
} from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import type { LinksFunction, LoaderArgs } from "@remix-run/node";
|
||||
import type { ShouldReloadFunction } from "@remix-run/react";
|
||||
import { Link } from "@remix-run/react";
|
||||
import { useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import clsx from "clsx";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCopyToClipboard } from "react-use";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Image } from "~/components/Image";
|
||||
import { Label } from "~/components/Label";
|
||||
import { Main } from "~/components/Main";
|
||||
import { Toggle } from "~/components/Toggle";
|
||||
import { db } from "~/db";
|
||||
import {
|
||||
modesShort,
|
||||
modes,
|
||||
stageIds,
|
||||
type ModeShort,
|
||||
type ModeWithStage,
|
||||
type StageId,
|
||||
} from "~/modules/in-game-lists";
|
||||
import { modes, stageIds } from "~/modules/in-game-lists";
|
||||
import type { MapPool } from "~/modules/map-pool-serializer/types";
|
||||
import styles from "~/styles/maps.css";
|
||||
import { mapsPage, modeImageUrl, stageImageUrl } from "~/utils/urls";
|
||||
import clsx from "clsx";
|
||||
import { Form, useLoaderData, useSearchParams } from "@remix-run/react";
|
||||
import {
|
||||
mapPoolToSerializedString,
|
||||
serializedStringToMapPool,
|
||||
} from "~/modules/map-pool-serializer";
|
||||
import { requireUser, useUser } from "~/modules/auth";
|
||||
import { ADMIN_DISCORD_ID, MAPS } from "~/constants";
|
||||
import { Button } from "~/components/Button";
|
||||
import { Input } from "~/components/Input";
|
||||
import { Label } from "~/components/Label";
|
||||
import { DownloadIcon } from "~/components/icons/Download";
|
||||
import { Toggle } from "~/components/Toggle";
|
||||
import {
|
||||
generateMapList,
|
||||
mapPoolToNonEmptyModes,
|
||||
modesOrder,
|
||||
} from "~/modules/map-list-generator";
|
||||
import * as React from "react";
|
||||
import invariant from "tiny-invariant";
|
||||
import { z } from "zod";
|
||||
import { parseRequestFormData } from "~/utils/remix";
|
||||
import { db } from "~/db";
|
||||
import { discordFullName } from "~/utils/strings";
|
||||
import { UploadIcon } from "~/components/icons/Upload";
|
||||
import {
|
||||
mapPoolToSerializedString,
|
||||
serializedStringToMapPool,
|
||||
} from "~/modules/map-pool-serializer";
|
||||
import type { MapPool } from "~/modules/map-pool-serializer/types";
|
||||
import styles from "~/styles/maps.css";
|
||||
import {
|
||||
calendarEventPage,
|
||||
ipLabsMaps,
|
||||
modeImageUrl,
|
||||
stageImageUrl,
|
||||
} from "~/utils/urls";
|
||||
|
||||
const AMOUNT_OF_MAPS_IN_MAP_LIST = stageIds.length * 2;
|
||||
|
||||
export const unstable_shouldReload: ShouldReloadFunction = () => false;
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
};
|
||||
@@ -53,41 +50,25 @@ export const handle = {
|
||||
i18n: "game-misc",
|
||||
};
|
||||
|
||||
// xxx: next -> define user flow after submitting a map pool
|
||||
// xxx: code can't have spaces or special characters also convert upper case to lower case
|
||||
const mapsActionSchema = z.object({
|
||||
code: z.string().min(MAPS.CODE_MIN_LENGTH).max(MAPS.CODE_MAX_LENGTH),
|
||||
pool: z.string(),
|
||||
});
|
||||
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
const user = await requireUser(request);
|
||||
const data = await parseRequestFormData({
|
||||
request,
|
||||
schema: mapsActionSchema,
|
||||
});
|
||||
|
||||
const mapPool = serializedStringToMapPool(data.pool);
|
||||
const maps = Object.entries(mapPool).flatMap(([mode, stages]) =>
|
||||
stages.flatMap((stageId) => ({ mode: mode as ModeShort, stageId }))
|
||||
);
|
||||
|
||||
db.maps.addMapPool({
|
||||
ownerId: user.id,
|
||||
code: data.code,
|
||||
maps,
|
||||
});
|
||||
|
||||
return redirect(mapsPage(data.code));
|
||||
};
|
||||
|
||||
export const loader = ({ request }: LoaderArgs) => {
|
||||
const url = new URL(request.url);
|
||||
const code = url.searchParams.get("code");
|
||||
const calendarEventId = url.searchParams.get("eventId");
|
||||
|
||||
if (!code) return null;
|
||||
const event = calendarEventId
|
||||
? db.calendarEvents.findById(Number(calendarEventId))
|
||||
: undefined;
|
||||
|
||||
return db.maps.findMapPoolByCode(code) ?? null;
|
||||
return {
|
||||
calendarEvent: event
|
||||
? {
|
||||
id: event.eventId,
|
||||
name: event.name,
|
||||
}
|
||||
: undefined,
|
||||
mapPool: event
|
||||
? db.calendarEvents.findMapPoolByEventId(event.eventId)
|
||||
: null,
|
||||
};
|
||||
};
|
||||
|
||||
const DEFAULT_MAP_POOL = {
|
||||
@@ -99,23 +80,33 @@ const DEFAULT_MAP_POOL = {
|
||||
};
|
||||
|
||||
export default function MapListPage() {
|
||||
const user = useUser();
|
||||
const { t } = useTranslation(["common"]);
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const [searchParams] = useSearchParams();
|
||||
const { mapPool, handleMapPoolChange } = useSearchParamMapPool();
|
||||
|
||||
if (
|
||||
process.env.NODE_ENV !== "development" &&
|
||||
user?.discordId !== ADMIN_DISCORD_ID
|
||||
) {
|
||||
return <Main>Coming soon :)</Main>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Main className="maps__container stack lg">
|
||||
<MapPoolLoaderSaver mapPool={mapPool} />
|
||||
{data.calendarEvent && !searchParams.has("pool") && (
|
||||
<div className="maps__pool-info">
|
||||
{t("common:maps.mapPool")}:{" "}
|
||||
<Link to={calendarEventPage(data.calendarEvent.id)}>
|
||||
{data.calendarEvent.name}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<MapPoolSelector
|
||||
mapPool={mapPool}
|
||||
handleMapPoolChange={handleMapPoolChange}
|
||||
/>
|
||||
<a
|
||||
href={ipLabsMaps(mapPoolToSerializedString(mapPool))}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="maps__tournament-map-list-link"
|
||||
>
|
||||
{t("common:maps.tournamentMaplist")}
|
||||
</a>
|
||||
<MapListCreator mapPool={mapPool} />
|
||||
</Main>
|
||||
);
|
||||
@@ -126,20 +117,14 @@ function useSearchParamMapPool() {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const mapPool = (() => {
|
||||
if (data?.maps) {
|
||||
return {
|
||||
TW: data.maps.filter((m) => m.mode === "TW").map((m) => m.stageId),
|
||||
SZ: data.maps.filter((m) => m.mode === "SZ").map((m) => m.stageId),
|
||||
TC: data.maps.filter((m) => m.mode === "TC").map((m) => m.stageId),
|
||||
CB: data.maps.filter((m) => m.mode === "CB").map((m) => m.stageId),
|
||||
RM: data.maps.filter((m) => m.mode === "RM").map((m) => m.stageId),
|
||||
};
|
||||
}
|
||||
|
||||
if (searchParams.has("pool")) {
|
||||
return serializedStringToMapPool(searchParams.get("pool")!);
|
||||
}
|
||||
|
||||
if (data?.mapPool) {
|
||||
return data.mapPool;
|
||||
}
|
||||
|
||||
return DEFAULT_MAP_POOL;
|
||||
})();
|
||||
|
||||
@@ -181,11 +166,8 @@ function MapPoolSelector({
|
||||
mapPool: MapPool;
|
||||
handleMapPoolChange: (args: { mode: ModeShort; stageId: StageId }) => void;
|
||||
}) {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const { t } = useTranslation(["game-misc"]);
|
||||
|
||||
const editMode = !data;
|
||||
|
||||
return (
|
||||
<div className="stack md">
|
||||
{stageIds.map((stageId) => (
|
||||
@@ -208,12 +190,10 @@ function MapPoolSelector({
|
||||
key={mode.short}
|
||||
className={clsx("maps__mode-button", "outline-theme", {
|
||||
selected,
|
||||
hidden: !editMode && !selected,
|
||||
})}
|
||||
onClick={() =>
|
||||
handleMapPoolChange({ mode: mode.short, stageId })
|
||||
}
|
||||
disabled={!editMode}
|
||||
type="button"
|
||||
>
|
||||
<Image
|
||||
@@ -236,69 +216,12 @@ function MapPoolSelector({
|
||||
);
|
||||
}
|
||||
|
||||
// xxx: show "log in to save map pools" if not logged in
|
||||
function MapPoolLoaderSaver({ mapPool }: { mapPool: MapPool }) {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
if (data) {
|
||||
return (
|
||||
<div className="maps__pool_info">
|
||||
Code: <code>{data.code}</code> - Made by: {discordFullName(data.owner)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const hasChanges = (() => {
|
||||
for (const mode of modesShort) {
|
||||
if (mapPool[mode].length !== DEFAULT_MAP_POOL[mode].length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const stageId of mapPool[mode]) {
|
||||
if (!(DEFAULT_MAP_POOL[mode] as StageId[]).includes(stageId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})();
|
||||
|
||||
return (
|
||||
<Form
|
||||
className="maps__pool-loader-saver"
|
||||
method={hasChanges ? "post" : "get"}
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="pool"
|
||||
value={mapPoolToSerializedString(mapPool)}
|
||||
/>
|
||||
<div>
|
||||
<Label>Code</Label>
|
||||
<Input
|
||||
name="code"
|
||||
minLength={MAPS.CODE_MIN_LENGTH}
|
||||
maxLength={MAPS.CODE_MAX_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
icon={hasChanges ? <UploadIcon /> : <DownloadIcon />}
|
||||
variant="outlined"
|
||||
type="submit"
|
||||
>
|
||||
{hasChanges ? "Save map pool" : "Load map pool"}
|
||||
</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
// xxx: crashes if only one map in mode
|
||||
// xxx: presentational mode
|
||||
function MapListCreator({ mapPool }: { mapPool: MapPool }) {
|
||||
const { t } = useTranslation(["game-misc"]);
|
||||
const { t } = useTranslation(["game-misc", "common"]);
|
||||
const [mapList, setMapList] = React.useState<ModeWithStage[]>();
|
||||
const [szEveryOther, setSzEveryOther] = React.useState(false);
|
||||
const [, copyToClipboard] = useCopyToClipboard();
|
||||
|
||||
const handleCreateMaplist = () => {
|
||||
const [list] = generateMapList(
|
||||
@@ -318,19 +241,41 @@ function MapListCreator({ mapPool }: { mapPool: MapPool }) {
|
||||
return (
|
||||
<div className="maps__map-list-creator">
|
||||
<div className="maps__toggle-container">
|
||||
<Label>50% SZ</Label>
|
||||
<Label>{t("common:maps.halfSz")}</Label>
|
||||
<Toggle checked={szEveryOther} setChecked={setSzEveryOther} tiny />
|
||||
</div>
|
||||
<Button onClick={handleCreateMaplist}>Create map list</Button>
|
||||
<Button onClick={handleCreateMaplist}>
|
||||
{t("common:maps.createMapList")}
|
||||
</Button>
|
||||
{mapList && (
|
||||
<ol className="maps__map-list">
|
||||
{mapList.map(({ mode, stageId }, i) => (
|
||||
<li key={i}>
|
||||
{t(`game-misc:MODE_SHORT_${mode}`)}{" "}
|
||||
{t(`game-misc:STAGE_${stageId}`)}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
<>
|
||||
<ol className="maps__map-list">
|
||||
{mapList.map(({ mode, stageId }, i) => (
|
||||
<li key={i}>
|
||||
{t(`game-misc:MODE_SHORT_${mode}`)}{" "}
|
||||
{t(`game-misc:STAGE_${stageId}`)}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
<Button
|
||||
tiny
|
||||
variant="outlined"
|
||||
onClick={() =>
|
||||
copyToClipboard(
|
||||
mapList
|
||||
.map(
|
||||
({ mode, stageId }, i) =>
|
||||
`${i + 1}) ${t(`game-misc:MODE_SHORT_${mode}`)} ${t(
|
||||
`game-misc:STAGE_${stageId}`
|
||||
)}`
|
||||
)
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
>
|
||||
{t("common:actions.copyToClipboard")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,6 +17,24 @@
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.event__map-pool-section {
|
||||
display: flex;
|
||||
max-width: 32rem;
|
||||
flex-direction: column;
|
||||
padding: var(--s-2);
|
||||
margin: 0 auto;
|
||||
gap: var(--s-4);
|
||||
}
|
||||
|
||||
.event__create-map-list-link {
|
||||
display: flex;
|
||||
width: max-content;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
font-size: var(--fonts-xs);
|
||||
gap: var(--s-1-5);
|
||||
}
|
||||
|
||||
.event__author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
.calendar-new__container {
|
||||
max-width: 32rem;
|
||||
}
|
||||
|
||||
.calendar-new__select {
|
||||
max-width: 16rem;
|
||||
}
|
||||
|
||||
@@ -205,6 +205,10 @@ input[type="checkbox"] {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-size: var(--fonts-xs);
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
max-width: 32rem;
|
||||
}
|
||||
|
||||
.maps__pool-loader-saver {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
gap: var(--s-4);
|
||||
.maps__pool-info {
|
||||
font-size: var(--fonts-xxs);
|
||||
font-weight: var(--semi-bold);
|
||||
}
|
||||
|
||||
.maps__tournament-map-list-link {
|
||||
font-size: var(--fonts-xxs);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.maps__stage-row {
|
||||
@@ -18,6 +21,7 @@
|
||||
|
||||
.maps__stage-name-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -25,11 +29,17 @@
|
||||
border-radius: var(--rounded);
|
||||
font-size: var(--fonts-xs);
|
||||
font-weight: var(--semi-bold);
|
||||
gap: var(--s-0-5);
|
||||
gap: var(--s-2);
|
||||
padding-block: var(--s-1-5);
|
||||
padding-inline: var(--s-3);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
.maps__stage-name-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.maps__mode-buttons-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -72,11 +82,6 @@
|
||||
gap: var(--s-4);
|
||||
}
|
||||
|
||||
.maps__pool_info {
|
||||
font-size: var(--fonts-xs);
|
||||
font-weight: var(--semi-bold);
|
||||
}
|
||||
|
||||
.maps__toggle-container {
|
||||
--label-margin: 0;
|
||||
|
||||
@@ -89,4 +94,5 @@
|
||||
.maps__map-list {
|
||||
font-size: var(--fonts-xs);
|
||||
font-weight: var(--semi-bold);
|
||||
margin-block-start: var(--s-4);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import slugify from "slugify";
|
||||
import type { Badge, GearType, MapPool, User } from "~/db/types";
|
||||
import type { Badge, GearType, MapPoolMap, User } from "~/db/types";
|
||||
import type { ModeShort, weaponCategories } from "~/modules/in-game-lists";
|
||||
import type {
|
||||
Ability,
|
||||
@@ -23,6 +23,9 @@ export const GITHUB_CONTRIBUTORS_URL =
|
||||
export const BORZOIC_TWITTER = "https://twitter.com/borzoic_";
|
||||
export const LEAN_TWITTER = "https://twitter.com/LeanYoshi";
|
||||
export const UBERU_TWITTER = "https://twitter.com/uberu5";
|
||||
export const ipLabsMaps = (pool: string) =>
|
||||
`https://maps.iplabs.ink/?3&pool=${pool}`;
|
||||
|
||||
export const LOG_IN_URL = "/auth";
|
||||
export const LOG_OUT_URL = "/auth/logout";
|
||||
export const ADMIN_PAGE = "/admin";
|
||||
@@ -64,8 +67,8 @@ export const calendarEditPage = (eventId?: number) =>
|
||||
`/calendar/new${eventId ? `?eventId=${eventId}` : ""}`;
|
||||
export const calendarReportWinnersPage = (eventId: number) =>
|
||||
`/calendar/${eventId}/report-winners`;
|
||||
export const mapsPage = (code?: MapPool["code"]) =>
|
||||
`/maps${code ? `?code=${code}` : ""}`;
|
||||
export const mapsPage = (eventId?: MapPoolMap["calendarEventId"]) =>
|
||||
`/maps${eventId ? `?eventId=${eventId}` : ""}`;
|
||||
export const articlePage = (slug: string) => `/a/${slug}`;
|
||||
export const analyzerPage = (args?: {
|
||||
weaponId: MainWeaponId;
|
||||
|
||||
64
migrations/010-fix-maps.js
Normal file
64
migrations/010-fix-maps.js
Normal file
@@ -0,0 +1,64 @@
|
||||
module.exports.up = function (db) {
|
||||
for (const table of ["MapPool", "MapPoolMap"]) {
|
||||
db.prepare(`drop table "${table}"`).run();
|
||||
}
|
||||
|
||||
db.prepare(`drop index calendar_event_map_pool_id`).run();
|
||||
db.prepare(`alter table "CalendarEvent" drop column "mapPoolId"`).run();
|
||||
|
||||
// ---
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
create table "MapPoolMap" (
|
||||
"calendarEventId" integer,
|
||||
"stageId" integer not null,
|
||||
"mode" text not null,
|
||||
foreign key ("calendarEventId") references "CalendarEvent"("id") on delete cascade,
|
||||
unique("calendarEventId", "stageId", "mode") on conflict rollback
|
||||
) strict
|
||||
`
|
||||
).run();
|
||||
db.prepare(
|
||||
`create index map_pool_map_calendar_event_id on "MapPoolMap"("calendarEventId")`
|
||||
).run();
|
||||
};
|
||||
|
||||
module.exports.down = function (db) {
|
||||
db.prepare(`drop table "MapPoolMap"`).run();
|
||||
|
||||
// ---
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
create table "MapPool" (
|
||||
"id" integer primary key,
|
||||
"code" text not null,
|
||||
"ownerId" integer not null,
|
||||
foreign key ("ownerId") references "User"("id") on delete restrict
|
||||
) strict
|
||||
`
|
||||
).run();
|
||||
db.prepare(`create index map_pool_owner_id on "MapPool"("ownerId")`).run();
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
create table "MapPoolMap" (
|
||||
"mapPoolId" integer not null,
|
||||
"stageId" integer not null,
|
||||
"mode" text not null,
|
||||
foreign key ("mapPoolId") references "MapPool"("id") on delete cascade
|
||||
) strict
|
||||
`
|
||||
).run();
|
||||
db.prepare(
|
||||
`create index map_pool_map_map_pool_id on "MapPoolMap"("mapPoolId")`
|
||||
).run();
|
||||
|
||||
db.prepare(
|
||||
`alter table "CalendarEvent" add "mapPoolId" integer references "MapPool"("id") on delete set null`
|
||||
).run();
|
||||
db.prepare(
|
||||
`create index calendar_event_map_pool_id on "CalendarEvent"("mapPoolId")`
|
||||
).run();
|
||||
};
|
||||
467
package-lock.json
generated
467
package-lock.json
generated
@@ -32,6 +32,7 @@
|
||||
"react-flip-toolkit": "^7.0.16",
|
||||
"react-i18next": "^11.18.6",
|
||||
"react-popper": "^2.3.0",
|
||||
"react-use": "^17.4.0",
|
||||
"remix-auth": "^3.3.0",
|
||||
"remix-auth-oauth2": "^1.3.0",
|
||||
"remix-i18next": "^4.1.1",
|
||||
@@ -2923,6 +2924,11 @@
|
||||
"i18next": "^21.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/js-cookie": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
|
||||
"integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="
|
||||
},
|
||||
"node_modules/@types/json-buffer": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
|
||||
@@ -3386,6 +3392,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz",
|
||||
"integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw=="
|
||||
},
|
||||
"node_modules/@xobotyi/scrollbar-width": {
|
||||
"version": "1.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
|
||||
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
|
||||
},
|
||||
"node_modules/@yarnpkg/esbuild-plugin-pnp": {
|
||||
"version": "3.0.0-rc.11",
|
||||
"resolved": "https://registry.npmjs.org/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.11.tgz",
|
||||
@@ -5025,6 +5036,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/copy-to-clipboard": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz",
|
||||
"integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==",
|
||||
"dependencies": {
|
||||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js-compat": {
|
||||
"version": "3.23.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.1.tgz",
|
||||
@@ -5140,6 +5159,35 @@
|
||||
"node": ">=12.22"
|
||||
}
|
||||
},
|
||||
"node_modules/css-in-js-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
|
||||
"dependencies": {
|
||||
"hyphenate-style-name": "^1.0.2",
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
|
||||
"integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
|
||||
"dependencies": {
|
||||
"mdn-data": "2.0.14",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
@@ -5155,8 +5203,7 @@
|
||||
"node_modules/csstype": {
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
|
||||
"integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
|
||||
},
|
||||
"node_modules/cypress": {
|
||||
"version": "10.8.0",
|
||||
@@ -5793,6 +5840,14 @@
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/error-stack-parser": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
|
||||
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
|
||||
"dependencies": {
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.0.tgz",
|
||||
@@ -7638,6 +7693,11 @@
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-shallow-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
|
||||
"integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="
|
||||
},
|
||||
"node_modules/fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
|
||||
@@ -7647,6 +7707,11 @@
|
||||
"node": ">= 4.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/fastest-stable-stringify": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
|
||||
"integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
@@ -8602,6 +8667,11 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "21.9.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz",
|
||||
@@ -8759,6 +8829,14 @@
|
||||
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inline-style-prefixer": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.1.tgz",
|
||||
"integrity": "sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ==",
|
||||
"dependencies": {
|
||||
"css-in-js-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inquirer": {
|
||||
"version": "8.2.4",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz",
|
||||
@@ -9344,7 +9422,6 @@
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -9355,6 +9432,11 @@
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js-cookie": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
|
||||
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
|
||||
},
|
||||
"node_modules/js-sdsl": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
||||
@@ -10262,6 +10344,11 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||
"integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="
|
||||
},
|
||||
"node_modules/mdurl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
@@ -11212,6 +11299,25 @@
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nano-css": {
|
||||
"version": "5.3.5",
|
||||
"resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.3.5.tgz",
|
||||
"integrity": "sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==",
|
||||
"dependencies": {
|
||||
"css-tree": "^1.1.2",
|
||||
"csstype": "^3.0.6",
|
||||
"fastest-stable-stringify": "^2.0.2",
|
||||
"inline-style-prefixer": "^6.0.0",
|
||||
"rtl-css-js": "^1.14.0",
|
||||
"sourcemap-codec": "^1.4.8",
|
||||
"stacktrace-js": "^2.0.2",
|
||||
"stylis": "^4.0.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
|
||||
@@ -12443,6 +12549,40 @@
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-universal-interface": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
|
||||
"integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"tslib": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-use": {
|
||||
"version": "17.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-use/-/react-use-17.4.0.tgz",
|
||||
"integrity": "sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==",
|
||||
"dependencies": {
|
||||
"@types/js-cookie": "^2.2.6",
|
||||
"@xobotyi/scrollbar-width": "^1.9.5",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-shallow-equal": "^1.0.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"nano-css": "^5.3.1",
|
||||
"react-universal-interface": "^0.6.2",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"screenfull": "^5.1.0",
|
||||
"set-harmonic-interval": "^1.0.1",
|
||||
"throttle-debounce": "^3.0.1",
|
||||
"ts-easing": "^0.2.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||
@@ -12908,6 +13048,11 @@
|
||||
"node": ">=0.10.5"
|
||||
}
|
||||
},
|
||||
"node_modules/resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
|
||||
@@ -13039,6 +13184,14 @@
|
||||
"estree-walker": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/rtl-css-js": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.0.tgz",
|
||||
"integrity": "sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
@@ -13133,6 +13286,17 @@
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/screenfull": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz",
|
||||
"integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/section-matter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||
@@ -13222,6 +13386,14 @@
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz",
|
||||
"integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg=="
|
||||
},
|
||||
"node_modules/set-harmonic-interval": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
|
||||
"integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==",
|
||||
"engines": {
|
||||
"node": ">=6.9"
|
||||
}
|
||||
},
|
||||
"node_modules/set-value": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
|
||||
@@ -13645,8 +13817,7 @@
|
||||
"node_modules/sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
|
||||
},
|
||||
"node_modules/space-separated-tokens": {
|
||||
"version": "2.0.1",
|
||||
@@ -13744,6 +13915,46 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/stack-generator": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
|
||||
"integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
|
||||
"dependencies": {
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/stackframe": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
|
||||
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
|
||||
},
|
||||
"node_modules/stacktrace-gps": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
|
||||
"integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
|
||||
"dependencies": {
|
||||
"source-map": "0.5.6",
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/stacktrace-gps/node_modules/source-map": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
|
||||
"integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stacktrace-js": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
|
||||
"integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
|
||||
"dependencies": {
|
||||
"error-stack-parser": "^2.0.6",
|
||||
"stack-generator": "^2.0.5",
|
||||
"stacktrace-gps": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/static-extend": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
|
||||
@@ -14290,6 +14501,11 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.2.tgz",
|
||||
"integrity": "sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA=="
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
@@ -14500,6 +14716,14 @@
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/throttle-debounce": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
|
||||
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/throttleit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
|
||||
@@ -14599,6 +14823,11 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toggle-selection": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
|
||||
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
@@ -14659,6 +14888,11 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-easing": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
|
||||
"integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ=="
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
@@ -14737,8 +14971,7 @@
|
||||
"node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/tsm": {
|
||||
"version": "2.2.2",
|
||||
@@ -17783,6 +18016,11 @@
|
||||
"i18next": "^21.0.1"
|
||||
}
|
||||
},
|
||||
"@types/js-cookie": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
|
||||
"integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="
|
||||
},
|
||||
"@types/json-buffer": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
|
||||
@@ -18126,6 +18364,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz",
|
||||
"integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw=="
|
||||
},
|
||||
"@xobotyi/scrollbar-width": {
|
||||
"version": "1.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
|
||||
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
|
||||
},
|
||||
"@yarnpkg/esbuild-plugin-pnp": {
|
||||
"version": "3.0.0-rc.11",
|
||||
"resolved": "https://registry.npmjs.org/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.11.tgz",
|
||||
@@ -19346,6 +19589,14 @@
|
||||
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
|
||||
"dev": true
|
||||
},
|
||||
"copy-to-clipboard": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz",
|
||||
"integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==",
|
||||
"requires": {
|
||||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.23.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.1.tgz",
|
||||
@@ -19433,6 +19684,31 @@
|
||||
"integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==",
|
||||
"dev": true
|
||||
},
|
||||
"css-in-js-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
|
||||
"requires": {
|
||||
"hyphenate-style-name": "^1.0.2",
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"css-tree": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
|
||||
"integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
|
||||
"requires": {
|
||||
"mdn-data": "2.0.14",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
@@ -19442,8 +19718,7 @@
|
||||
"csstype": {
|
||||
"version": "3.0.11",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
|
||||
"integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
|
||||
},
|
||||
"cypress": {
|
||||
"version": "10.8.0",
|
||||
@@ -19931,6 +20206,14 @@
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"error-stack-parser": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
|
||||
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
|
||||
"requires": {
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"es-abstract": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.0.tgz",
|
||||
@@ -21221,12 +21504,22 @@
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-shallow-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
|
||||
"integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="
|
||||
},
|
||||
"fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
|
||||
"integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
|
||||
"dev": true
|
||||
},
|
||||
"fastest-stable-stringify": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
|
||||
"integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
|
||||
},
|
||||
"fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
@@ -21961,6 +22254,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
|
||||
},
|
||||
"i18next": {
|
||||
"version": "21.9.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz",
|
||||
@@ -22069,6 +22367,14 @@
|
||||
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"inline-style-prefixer": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.1.tgz",
|
||||
"integrity": "sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ==",
|
||||
"requires": {
|
||||
"css-in-js-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "8.2.4",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz",
|
||||
@@ -22478,8 +22784,7 @@
|
||||
"isobject": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
@@ -22487,6 +22792,11 @@
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"dev": true
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
|
||||
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
|
||||
},
|
||||
"js-sdsl": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
||||
@@ -23202,6 +23512,11 @@
|
||||
"integrity": "sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==",
|
||||
"dev": true
|
||||
},
|
||||
"mdn-data": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||
"integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="
|
||||
},
|
||||
"mdurl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
@@ -23807,6 +24122,21 @@
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"nano-css": {
|
||||
"version": "5.3.5",
|
||||
"resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.3.5.tgz",
|
||||
"integrity": "sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==",
|
||||
"requires": {
|
||||
"css-tree": "^1.1.2",
|
||||
"csstype": "^3.0.6",
|
||||
"fastest-stable-stringify": "^2.0.2",
|
||||
"inline-style-prefixer": "^6.0.0",
|
||||
"rtl-css-js": "^1.14.0",
|
||||
"sourcemap-codec": "^1.4.8",
|
||||
"stacktrace-js": "^2.0.2",
|
||||
"stylis": "^4.0.6"
|
||||
}
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
|
||||
@@ -24707,6 +25037,33 @@
|
||||
"react-router": "6.3.0"
|
||||
}
|
||||
},
|
||||
"react-universal-interface": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
|
||||
"integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-use": {
|
||||
"version": "17.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-use/-/react-use-17.4.0.tgz",
|
||||
"integrity": "sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==",
|
||||
"requires": {
|
||||
"@types/js-cookie": "^2.2.6",
|
||||
"@xobotyi/scrollbar-width": "^1.9.5",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-shallow-equal": "^1.0.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"nano-css": "^5.3.1",
|
||||
"react-universal-interface": "^0.6.2",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"screenfull": "^5.1.0",
|
||||
"set-harmonic-interval": "^1.0.1",
|
||||
"throttle-debounce": "^3.0.1",
|
||||
"ts-easing": "^0.2.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||
@@ -25068,6 +25425,11 @@
|
||||
"integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
|
||||
"dev": true
|
||||
},
|
||||
"resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
|
||||
@@ -25172,6 +25534,14 @@
|
||||
"estree-walker": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"rtl-css-js": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.0.tgz",
|
||||
"integrity": "sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
@@ -25232,6 +25602,11 @@
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"screenfull": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz",
|
||||
"integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA=="
|
||||
},
|
||||
"section-matter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||
@@ -25307,6 +25682,11 @@
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz",
|
||||
"integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg=="
|
||||
},
|
||||
"set-harmonic-interval": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
|
||||
"integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g=="
|
||||
},
|
||||
"set-value": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
|
||||
@@ -25627,8 +26007,7 @@
|
||||
"sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
|
||||
},
|
||||
"space-separated-tokens": {
|
||||
"version": "2.0.1",
|
||||
@@ -25708,6 +26087,45 @@
|
||||
"minipass": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"stack-generator": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
|
||||
"integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
|
||||
"requires": {
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"stackframe": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
|
||||
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
|
||||
},
|
||||
"stacktrace-gps": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
|
||||
"integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
|
||||
"requires": {
|
||||
"source-map": "0.5.6",
|
||||
"stackframe": "^1.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
|
||||
"integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"stacktrace-js": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
|
||||
"integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
|
||||
"requires": {
|
||||
"error-stack-parser": "^2.0.6",
|
||||
"stack-generator": "^2.0.5",
|
||||
"stacktrace-gps": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"static-extend": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
|
||||
@@ -26123,6 +26541,11 @@
|
||||
"postcss-sorting": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"stylis": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.2.tgz",
|
||||
"integrity": "sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA=="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
@@ -26301,6 +26724,11 @@
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"throttle-debounce": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
|
||||
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg=="
|
||||
},
|
||||
"throttleit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
|
||||
@@ -26384,6 +26812,11 @@
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"toggle-selection": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
|
||||
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
@@ -26428,6 +26861,11 @@
|
||||
"integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-easing": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
|
||||
"integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ=="
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
@@ -26479,8 +26917,7 @@
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"tsm": {
|
||||
"version": "2.2.2",
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"react-flip-toolkit": "^7.0.16",
|
||||
"react-i18next": "^11.18.6",
|
||||
"react-popper": "^2.3.0",
|
||||
"react-use": "^17.4.0",
|
||||
"remix-auth": "^3.3.0",
|
||||
"remix-auth-oauth2": "^1.3.0",
|
||||
"remix-i18next": "^4.1.1",
|
||||
|
||||
BIN
public/img/layout/maps.avif
Normal file
BIN
public/img/layout/maps.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
public/img/layout/maps.png
Normal file
BIN
public/img/layout/maps.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -8,6 +8,7 @@
|
||||
"participatedCount": "{{count}} teams participated",
|
||||
"members": "Members",
|
||||
"results": "Results",
|
||||
"createMapList": "Create map list",
|
||||
|
||||
"forms.dates": "Dates",
|
||||
"forms.bracketUrl": "Bracket URL",
|
||||
@@ -17,6 +18,7 @@
|
||||
"forms.tags.info": "\"Badge prizes\" tag is added automatically if applicable",
|
||||
"forms.badges": "Badge prizes",
|
||||
"forms.badges.placeholder": "Choose a badge prize",
|
||||
"forms.mapPool": "Map pool",
|
||||
|
||||
"forms.participantCount": "Participant count",
|
||||
"forms.reportResultsHeader": "Reporting results for {{eventName}}",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"pages.faq": "FAQ",
|
||||
"pages.builds": "Builds",
|
||||
"pages.analyzer": "Build Analyzer",
|
||||
"pages.maps": "Map Lists",
|
||||
|
||||
"header.profile": "Profile",
|
||||
"header.logout": "Log out",
|
||||
@@ -27,6 +28,12 @@
|
||||
"actions.remove": "Remove",
|
||||
"actions.delete": "Delete",
|
||||
"actions.loadMore": "Load more",
|
||||
"actions.copyToClipboard": "Copy to clipboard",
|
||||
|
||||
"maps.createMapList": "Create map list",
|
||||
"maps.halfSz": "50% SZ",
|
||||
"maps.mapPool": "Map pool",
|
||||
"maps.tournamentMaplist": "Create tournament map list (maps.iplabs.ink)",
|
||||
|
||||
"results": "Results",
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"plus.description": "View Plus Server voting history and more",
|
||||
"badges.description": "List of all the badges you can earn for your profile",
|
||||
"analyzer.description": "Find out what your builds actually do",
|
||||
"maps.description": "Turn pool of maps into a list to play on",
|
||||
"recentWinners": "Recent winners",
|
||||
"upcomingEvents": "Upcoming events",
|
||||
"articleBy": "by {{author}}"
|
||||
|
||||
@@ -23,18 +23,32 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**48/49**
|
||||
**48/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.maps
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
|
||||
</details>
|
||||
|
||||
@@ -46,13 +60,31 @@
|
||||
|
||||
**6/6**
|
||||
|
||||
### 🟢 front.json
|
||||
### 🟡 front.json
|
||||
|
||||
**10/10**
|
||||
**10/11**
|
||||
|
||||
### 🟢 game-misc.json
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
**12/12**
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -78,7 +110,85 @@
|
||||
|
||||
---
|
||||
|
||||
## /de (🟢 Done)
|
||||
## /de (🟡 In progress)
|
||||
|
||||
### 🟢 analyzer.json
|
||||
|
||||
**94/94**
|
||||
|
||||
### 🟢 badges.json
|
||||
|
||||
**7/7**
|
||||
|
||||
### 🟢 builds.json
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**49/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.maps
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 contributions.json
|
||||
|
||||
**6/6**
|
||||
|
||||
### 🟢 faq.json
|
||||
|
||||
**6/6**
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**10/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 user.json
|
||||
|
||||
**19/19**
|
||||
|
||||
---
|
||||
|
||||
@@ -105,18 +215,32 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**48/49**
|
||||
**48/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.maps
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
|
||||
</details>
|
||||
|
||||
@@ -128,13 +252,31 @@
|
||||
|
||||
**6/6**
|
||||
|
||||
### 🟢 front.json
|
||||
### 🟡 front.json
|
||||
|
||||
**10/10**
|
||||
**10/11**
|
||||
|
||||
### 🟢 game-misc.json
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
**12/12**
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -183,20 +325,34 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**46/49**
|
||||
**46/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
|
||||
</details>
|
||||
|
||||
@@ -218,19 +374,31 @@
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**8/10**
|
||||
**8/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- buildsGoTo
|
||||
- analyzer.description
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -272,11 +440,11 @@
|
||||
|
||||
### 🔴 calendar.json
|
||||
|
||||
**0/44**
|
||||
**0/46**
|
||||
|
||||
### 🔴 common.json
|
||||
|
||||
**0/49**
|
||||
**0/55**
|
||||
|
||||
### 🔴 contributions.json
|
||||
|
||||
@@ -288,11 +456,22 @@
|
||||
|
||||
### 🔴 front.json
|
||||
|
||||
**0/10**
|
||||
**0/11**
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🔴 user.json
|
||||
|
||||
@@ -402,20 +581,34 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**46/49**
|
||||
**46/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
|
||||
</details>
|
||||
|
||||
@@ -436,19 +629,31 @@
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**8/10**
|
||||
**8/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- buildsGoTo
|
||||
- analyzer.description
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -488,20 +693,34 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**35/49**
|
||||
**35/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
- weapon.category.SHOOTERS
|
||||
- weapon.category.BLASTERS
|
||||
- weapon.category.ROLLERS
|
||||
@@ -533,19 +752,31 @@
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**8/10**
|
||||
**8/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- buildsGoTo
|
||||
- analyzer.description
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -615,19 +846,33 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**36/49**
|
||||
**36/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.maps
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
- weapon.category.SHOOTERS
|
||||
- weapon.category.BLASTERS
|
||||
- weapon.category.ROLLERS
|
||||
@@ -659,19 +904,31 @@
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**8/10**
|
||||
**8/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- buildsGoTo
|
||||
- analyzer.description
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -711,20 +968,34 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**35/49**
|
||||
**35/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
- weapon.category.SHOOTERS
|
||||
- weapon.category.BLASTERS
|
||||
- weapon.category.ROLLERS
|
||||
@@ -756,19 +1027,31 @@
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**8/10**
|
||||
**8/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- buildsGoTo
|
||||
- analyzer.description
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
@@ -808,20 +1091,34 @@
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
### 🟡 calendar.json
|
||||
|
||||
**44/44**
|
||||
**44/46**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- createMapList
|
||||
- forms.mapPool
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**35/49**
|
||||
**35/55**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
- maps.tournamentMaplist
|
||||
- weapon.category.SHOOTERS
|
||||
- weapon.category.BLASTERS
|
||||
- weapon.category.ROLLERS
|
||||
@@ -853,19 +1150,31 @@
|
||||
|
||||
### 🟡 front.json
|
||||
|
||||
**8/10**
|
||||
**8/11**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- buildsGoTo
|
||||
- analyzer.description
|
||||
- maps.description
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 game-misc.json
|
||||
### 🟡 game-misc.json
|
||||
|
||||
**12/12**
|
||||
**12/17**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- MODE_SHORT_TW
|
||||
- MODE_SHORT_SZ
|
||||
- MODE_SHORT_TC
|
||||
- MODE_SHORT_RM
|
||||
- MODE_SHORT_CB
|
||||
|
||||
</details>
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
|
||||
Reference in New Issue
Block a user