Add recent events to map pool templates

This commit is contained in:
Remmy Cat Stock
2022-10-26 01:18:32 +02:00
parent 63154e507e
commit 0a85ad08d2
7 changed files with 101 additions and 7 deletions

View File

@@ -14,12 +14,19 @@ import { split, startsWith } from "~/utils/strings";
import { CrossIcon } from "./icons/Cross";
import { ArrowLongLeftIcon } from "./icons/ArrowLongLeft";
import * as React from "react";
import type { CalendarEvent } from "~/db/types";
export type MapPoolSelectorProps = {
mapPool: MapPool;
handleRemoval?: () => void;
handleMapPoolChange: (mapPool: MapPool) => void;
handleMapPoolChange: (
mapPool: MapPool,
event?: Pick<CalendarEvent, "id" | "name">
) => void;
className?: string;
recentEvents?: Array<
Pick<CalendarEvent, "id" | "name"> & { serializedMapPool: string }
>;
};
export function MapPoolSelector({
@@ -27,6 +34,7 @@ export function MapPoolSelector({
handleMapPoolChange,
handleRemoval,
className,
recentEvents,
}: MapPoolSelectorProps) {
const { t } = useTranslation();
@@ -56,6 +64,17 @@ export function MapPoolSelector({
handleMapPoolChange(MapPool[presetId]);
return;
}
if (startsWith(template, "recent-event:")) {
const [, eventId] = split(template, ":");
const event = recentEvents?.find((e) => e.id.toString() === eventId);
if (event) {
handleMapPoolChange(new MapPool(event.serializedMapPool), event);
}
return;
}
};
return (
@@ -80,6 +99,7 @@ export function MapPoolSelector({
<MapPoolTemplateSelect
value={template}
handleChange={handleTemplateChange}
recentEvents={recentEvents}
/>
</div>
<MapPoolStages
@@ -256,7 +276,10 @@ type MapModePresetId = "ANARCHY" | "ALL" | ModeShort;
const presetIds: MapModePresetId[] = ["ANARCHY", "ALL", ...modesShort];
type MapPoolTemplateValue = "none" | `preset:${MapModePresetId}`;
type MapPoolTemplateValue =
| "none"
| `preset:${MapModePresetId}`
| `recent-event:${string}`;
function detectTemplate(mapPool: MapPool): MapPoolTemplateValue {
for (const presetId of presetIds) {
@@ -270,11 +293,13 @@ function detectTemplate(mapPool: MapPool): MapPoolTemplateValue {
type MapPoolTemplateSelectProps = {
value: MapPoolTemplateValue;
handleChange: (newValue: MapPoolTemplateValue) => void;
recentEvents?: Pick<CalendarEvent, "id" | "name">[];
};
function MapPoolTemplateSelect({
handleChange,
value,
recentEvents,
}: MapPoolTemplateSelectProps) {
const { t } = useTranslation(["game-misc", "common"]);
@@ -302,6 +327,15 @@ function MapPoolTemplateSelect({
</option>
))}
</optgroup>
{recentEvents && recentEvents.length > 0 && (
<optgroup label={t("common:maps.template.yourRecentEvents")}>
{recentEvents.map((event) => (
<option key={event.id} value={`recent-event:${event.id}`}>
{event.name}
</option>
))}
</optgroup>
)}
</select>
</label>
);

View File

@@ -0,0 +1,21 @@
select
"CalendarEvent"."id",
"CalendarEvent"."name",
json_group_array(
json_object(
'stageId',
"MapPoolMap"."stageId",
'mode',
"MapPoolMap"."mode"
)
) as "mapPool"
from
"CalendarEvent"
join "MapPoolMap" on "CalendarEvent"."id" = "MapPoolMap"."calendarEventId"
where
"CalendarEvent"."authorId" = @authorId
group by
"CalendarEvent"."id"
order by
"CalendarEvent"."id" desc
limit 5

View File

@@ -36,6 +36,7 @@ import upcomingEventsSql from "./upcomingEvents.sql";
import createMapPoolMapSql from "./createMapPoolMap.sql";
import deleteMapPoolMapsSql from "./deleteMapPoolMaps.sql";
import findMapPoolByEventIdSql from "./findMapPoolByEventId.sql";
import findRecentMapPoolsByAuthorIdSql from "./findRecentMapPoolsByAuthorId.sql";
const createStm = sql.prepare(createSql);
const updateStm = sql.prepare(updateSql);
@@ -467,3 +468,22 @@ export function eventsToReport(authorId?: CalendarEvent["authorId"]) {
}) as Array<Pick<CalendarEvent, "id" | "name">>
).map((row) => ({ id: row.id, name: row.name }));
}
const findRecentMapPoolsByAuthorIdStm = sql.prepare(
findRecentMapPoolsByAuthorIdSql
);
export function findRecentMapPoolsByAuthorId(
authorId: CalendarEvent["authorId"]
) {
return (
findRecentMapPoolsByAuthorIdStm.all({ authorId }) as Array<
Pick<CalendarEvent, "id" | "name"> & {
mapPool: string;
}
>
).map((row) => ({
id: row.id,
name: row.name,
serializedMapPool: MapPool.serialize(JSON.parse(row.mapPool)),
}));
}

View File

@@ -192,6 +192,9 @@ export const loader = async ({ request }: LoaderArgs) => {
return json({
managedBadges: db.badges.managedByUserId(user.id),
recentEventsWithMapPools: db.calendarEvents.findRecentMapPoolsByAuthorId(
user.id
),
eventToEdit: canEditEvent
? {
...eventToEdit,
@@ -520,7 +523,8 @@ function BadgesAdder() {
function MapPoolSection() {
const { t } = useTranslation(["game-misc", "common"]);
const { eventToEdit } = useLoaderData<typeof loader>();
const { eventToEdit, recentEventsWithMapPools } =
useLoaderData<typeof loader>();
const [mapPool, setMapPool] = React.useState<MapPool>(
eventToEdit?.mapPool ? new MapPool(eventToEdit.mapPool) : MapPool.EMPTY
);
@@ -539,6 +543,7 @@ function MapPoolSection() {
mapPool={mapPool}
handleRemoval={() => setIncludeMapPool(false)}
handleMapPoolChange={setMapPool}
recentEvents={recentEventsWithMapPools}
/>
</>
) : (

View File

@@ -31,6 +31,8 @@ import { type SendouRouteHandle } from "~/utils/remix";
import { MapPoolSelector, MapPoolStages } from "~/components/MapPoolSelector";
import { EditIcon } from "~/components/icons/Edit";
import { useOnce } from "~/hooks/useOnce";
import { getUser } from "~/modules/auth";
import type { CalendarEvent } from "~/db/types";
const AMOUNT_OF_MAPS_IN_MAP_LIST = stageIds.length * 2;
@@ -61,6 +63,7 @@ export const handle: SendouRouteHandle = {
};
export const loader = async ({ request }: LoaderArgs) => {
const user = await getUser(request);
const url = new URL(request.url);
const calendarEventId = url.searchParams.get("eventId");
const t = await i18next.getFixedT(request);
@@ -79,6 +82,9 @@ export const loader = async ({ request }: LoaderArgs) => {
mapPool: event
? db.calendarEvents.findMapPoolByEventId(event.eventId)
: null,
recentEventsWithMapPools: user
? db.calendarEvents.findRecentMapPoolsByAuthorId(user.id)
: undefined,
title: makeTitle([t("pages.maps")]),
};
};
@@ -118,6 +124,7 @@ export default function MapListPage() {
<MapPoolSelector
mapPool={mapPool}
handleMapPoolChange={handleMapPoolChange}
recentEvents={data.recentEventsWithMapPools}
/>
)}
<a
@@ -151,12 +158,17 @@ function useSearchParamPersistedMapPool() {
const [mapPool, setMapPool] = React.useState(initialMapPool);
const handleMapPoolChange = (newMapPool: MapPool) => {
const handleMapPoolChange = (
newMapPool: MapPool,
event?: Pick<CalendarEvent, "id" | "name">
) => {
setMapPool(newMapPool);
setSearchParams(
{
pool: newMapPool.serialized,
},
event
? { eventId: event.id.toString() }
: {
pool: newMapPool.serialized,
},
{ replace: true, state: { scroll: false } }
);
};

View File

@@ -44,6 +44,7 @@
"maps.template": "Vorlage",
"maps.template.none": "Keine",
"maps.template.presets": "Voreinstellungen",
"maps.template.yourRecentEvents": "Deine Events",
"maps.template.preset.ANARCHY": "Anarchie-Modi",
"maps.template.preset.ALL": "Alle Modi",
"maps.template.preset.onlyMode": "Nur {{modeName}}",

View File

@@ -46,6 +46,7 @@
"maps.template": "Template",
"maps.template.none": "None",
"maps.template.presets": "Presets",
"maps.template.yourRecentEvents": "Recent Events",
"maps.template.preset.ANARCHY": "Anarchy Modes",
"maps.template.preset.ALL": "All Modes",
"maps.template.preset.onlyMode": "Only {{modeName}}",