Convert dates automatically

This commit is contained in:
Luke Vella 2022-04-12 19:38:37 +02:00
parent e1e691a45d
commit fa0946705c
5 changed files with 160 additions and 37 deletions

View file

@ -32,7 +32,7 @@ const ManagePoll: React.VoidFunctionComponent<{
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { mutate: resetDates } = useMutation( const { mutate: resetDates } = useMutation(
async () => { async () => {
await axios.get(`/api/legacy/${poll.urlId}?reset=true`); await axios.get(`/api/legacy/${poll.urlId}/reset`);
}, },
{ {
onSettled: () => { onSettled: () => {

View file

@ -1,46 +1,11 @@
import { GetPollApiResponse } from "api-client/get-poll"; import { GetPollApiResponse } from "api-client/get-poll";
import { ObjectId } from "mongodb";
import { NextApiRequest, NextApiResponse } from "next"; import { NextApiRequest, NextApiResponse } from "next";
import { exclude, getQueryParam } from "utils/api-utils"; import { exclude, getQueryParam } from "utils/api-utils";
import { LegacyPoll } from "utils/legacy-utils";
import { getMongoClient } from "utils/mongodb-client"; import { getMongoClient } from "utils/mongodb-client";
import { nanoid } from "utils/nanoid"; import { nanoid } from "utils/nanoid";
import { prisma } from "../../../db"; import { prisma } from "../../../db";
interface LegacyPoll {
__private: {
verificationCode: string;
};
_id: string;
title: string;
location: string;
isExample: boolean;
isDeleted: boolean;
isClosed: boolean;
emails: string[];
description: string;
dates?: Date[];
creator: {
name: string;
email: string;
isVerified: boolean;
allowNotifications: boolean;
};
created: Date;
comments?: Array<{
_id: ObjectId;
author: {
name: string;
};
content: string;
created: Date;
}>;
participants?: Array<{
_id: ObjectId;
name: string;
votes?: boolean[];
}>;
}
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse<GetPollApiResponse>, res: NextApiResponse<GetPollApiResponse>,

View file

@ -0,0 +1,24 @@
import { GetPollApiResponse } from "api-client/get-poll";
import { NextApiRequest, NextApiResponse } from "next";
import { exclude, getQueryParam } from "utils/api-utils";
import { resetDates } from "utils/legacy-utils";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<GetPollApiResponse>,
) {
const urlId = getQueryParam(req, "urlId");
const poll = await resetDates(urlId);
if (!poll) {
return res.status(404);
}
return res.json({
...exclude(poll, "verificationCode"),
role: "admin",
urlId: poll.urlId,
pollId: poll.urlId,
});
}

View file

@ -1,5 +1,7 @@
import { GetPollApiResponse } from "api-client/get-poll"; import { GetPollApiResponse } from "api-client/get-poll";
import { NextApiResponse } from "next"; import { NextApiResponse } from "next";
import { resetDates } from "utils/legacy-utils";
import { getMongoClient } from "utils/mongodb-client";
import { UpdatePollPayload } from "../../../../api-client/update-poll"; import { UpdatePollPayload } from "../../../../api-client/update-poll";
import { prisma } from "../../../../db"; import { prisma } from "../../../../db";
import { exclude, withLink } from "../../../../utils/api-utils"; import { exclude, withLink } from "../../../../utils/api-utils";
@ -48,6 +50,25 @@ export default withLink(
.json({ status: 404, message: "Poll not found" }); .json({ status: 404, message: "Poll not found" });
} }
if (
poll.legacy &&
// has converted options without timezone
poll.options.some(({ value }) => value.indexOf("T") === -1)
) {
// We need to reset the dates for polls that lost their timezone data because some users
// of the old version will end up seeing the wrong dates
const fixedPoll = await resetDates(poll.urlId);
if (fixedPoll) {
return res.json({
...exclude(fixedPoll, "verificationCode"),
role: link.role,
urlId: link.urlId,
pollId: poll.urlId,
});
}
}
return res.json({ return res.json({
...exclude(poll, "verificationCode"), ...exclude(poll, "verificationCode"),
role: link.role, role: link.role,

113
utils/legacy-utils.ts Normal file
View file

@ -0,0 +1,113 @@
import { ObjectId } from "mongodb";
import { getMongoClient } from "./mongodb-client";
import { prisma } from "../db";
export interface LegacyPoll {
__private: {
verificationCode: string;
};
_id: string;
title: string;
location: string;
isExample: boolean;
isDeleted: boolean;
isClosed: boolean;
emails: string[];
description: string;
dates?: Date[];
creator: {
name: string;
email: string;
isVerified: boolean;
allowNotifications: boolean;
};
created: Date;
comments?: Array<{
_id: ObjectId;
author: {
name: string;
};
content: string;
created: Date;
}>;
participants?: Array<{
_id: ObjectId;
name: string;
votes?: boolean[];
}>;
}
export const resetDates = async (legacyPollId: string) => {
const client = await getMongoClient();
if (!client) {
return;
}
const db = client.db("rallly-db");
const collection = db.collection("events");
const legacyPoll = await collection.findOne<LegacyPoll>({
_id: legacyPollId,
});
if (!legacyPoll) {
return;
}
const existingOptions = await prisma.option.findMany({
where: { pollId: legacyPoll._id },
orderBy: {
value: "asc",
},
});
if (!existingOptions) {
return;
}
const promises = [];
for (let i = 0; i < existingOptions.length; i++) {
const legacyOption = legacyPoll.dates?.find(
(date) =>
date.toISOString().substring(0, 10) === existingOptions[i].value,
);
if (legacyOption) {
promises.push(
prisma.option.update({
where: { id: existingOptions[i].id },
data: {
value: legacyOption.toISOString(),
},
}),
);
}
}
await prisma.$transaction(promises);
const poll = await prisma.poll.findUnique({
where: {
urlId: legacyPoll._id,
},
include: {
options: {
include: {
votes: true,
},
},
participants: {
include: {
votes: true,
},
orderBy: [
{
createdAt: "desc",
},
{ name: "desc" },
],
},
user: true,
links: true,
},
});
return poll;
};