mirror of
https://github.com/lukevella/rallly.git
synced 2025-07-06 19:17:27 +02:00
🔥 Remove deprecated event model (#1775)
This commit is contained in:
parent
b1b76b4bec
commit
37b7ed5e19
14 changed files with 85 additions and 248 deletions
|
@ -159,7 +159,6 @@ export default async function Page(props: {
|
||||||
title={event.title}
|
title={event.title}
|
||||||
start={event.start}
|
start={event.start}
|
||||||
end={event.end}
|
end={event.end}
|
||||||
status={event.status}
|
|
||||||
allDay={event.allDay}
|
allDay={event.allDay}
|
||||||
invites={event.invites}
|
invites={event.invites}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { Trans } from "@/components/trans";
|
||||||
import { IfCloudHosted } from "@/contexts/environment";
|
import { IfCloudHosted } from "@/contexts/environment";
|
||||||
import { getTranslation } from "@/i18n/server";
|
import { getTranslation } from "@/i18n/server";
|
||||||
import { prisma } from "@rallly/database";
|
import { prisma } from "@rallly/database";
|
||||||
|
import dayjs from "dayjs";
|
||||||
import { FeedbackAlert } from "./feedback-alert";
|
import { FeedbackAlert } from "./feedback-alert";
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
|
@ -34,7 +35,10 @@ async function loadData() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const todayStart = dayjs().startOf("day").toDate();
|
||||||
|
const todayEnd = dayjs().endOf("day").toDate();
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
const [livePollCount, upcomingEventCount] = await Promise.all([
|
const [livePollCount, upcomingEventCount] = await Promise.all([
|
||||||
prisma.poll.count({
|
prisma.poll.count({
|
||||||
where: {
|
where: {
|
||||||
|
@ -43,12 +47,16 @@ async function loadData() {
|
||||||
deleted: false,
|
deleted: false,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
prisma.event.count({
|
prisma.scheduledEvent.count({
|
||||||
where: {
|
where: {
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
start: {
|
OR: [
|
||||||
gte: now,
|
{ allDay: false, start: { gte: now } },
|
||||||
},
|
{
|
||||||
|
allDay: true,
|
||||||
|
start: { gte: todayStart, lte: todayEnd },
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { CalendarIcon } from "lucide-react";
|
||||||
|
|
||||||
import { AddToCalendarButton } from "@/components/add-to-calendar-button";
|
import { AddToCalendarButton } from "@/components/add-to-calendar-button";
|
||||||
import { ParticipantAvatarBar } from "@/components/participant-avatar-bar";
|
import { ParticipantAvatarBar } from "@/components/participant-avatar-bar";
|
||||||
import { useVisibleParticipants } from "@/components/participants-provider";
|
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { IfParticipantsVisible } from "@/components/visibility";
|
import { IfParticipantsVisible } from "@/components/visibility";
|
||||||
import { usePoll } from "@/contexts/poll";
|
import { usePoll } from "@/contexts/poll";
|
||||||
|
@ -49,15 +48,8 @@ function FinalTime({ start, duration }: { start: Date; duration: number }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function useAttendees() {
|
function useAttendees() {
|
||||||
const participants = useVisibleParticipants();
|
|
||||||
const poll = usePoll();
|
const poll = usePoll();
|
||||||
return participants.filter((participant) =>
|
return poll.event?.attendees ?? [];
|
||||||
participant.votes.some(
|
|
||||||
(vote) =>
|
|
||||||
vote.optionId === poll?.event?.optionId &&
|
|
||||||
(vote.type === "yes" || vote.type === "ifNeedBe"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Attendees() {
|
function Attendees() {
|
||||||
|
@ -117,8 +109,8 @@ export function ScheduledEvent() {
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
guests={attendees
|
guests={attendees
|
||||||
.filter((participant) => !!participant.email)
|
.filter((attendee) => !!attendee.email)
|
||||||
.map((participant) => participant.email as string)}
|
.map((attendee) => attendee.email as string)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,12 +48,6 @@ export async function getPolls({
|
||||||
image: true,
|
image: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
event: {
|
|
||||||
select: {
|
|
||||||
start: true,
|
|
||||||
duration: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
participants: {
|
participants: {
|
||||||
where: {
|
where: {
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
@ -95,7 +89,6 @@ export async function getPolls({
|
||||||
email: participant.email ?? undefined,
|
email: participant.email ?? undefined,
|
||||||
image: participant.user?.image ?? undefined,
|
image: participant.user?.image ?? undefined,
|
||||||
})),
|
})),
|
||||||
event: poll.event ?? undefined,
|
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
import type { Prisma } from "@rallly/database";
|
|
||||||
import { prisma } from "@rallly/database";
|
|
||||||
import { unstable_cache } from "next/cache";
|
|
||||||
|
|
||||||
type PollFilters = {
|
|
||||||
userId: string;
|
|
||||||
limit?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getRecentlyUpdatedPolls = async ({
|
|
||||||
userId,
|
|
||||||
limit = 3,
|
|
||||||
}: PollFilters) => {
|
|
||||||
// Build the where clause based on filters
|
|
||||||
const where: Prisma.PollWhereInput = {
|
|
||||||
userId,
|
|
||||||
deleted: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const data = await prisma.poll.findMany({
|
|
||||||
where,
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
status: true,
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true,
|
|
||||||
event: {
|
|
||||||
select: {
|
|
||||||
start: true,
|
|
||||||
duration: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
participants: {
|
|
||||||
where: {
|
|
||||||
deleted: false,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
user: {
|
|
||||||
select: {
|
|
||||||
image: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: "desc",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
startTime: true,
|
|
||||||
duration: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
updatedAt: "desc",
|
|
||||||
},
|
|
||||||
take: limit,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data.map((poll) => {
|
|
||||||
const { options, ...rest } = poll;
|
|
||||||
const durations = new Set<number>();
|
|
||||||
for (const option of options) {
|
|
||||||
durations.add(option.duration);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...rest,
|
|
||||||
participants: poll.participants.map((participant) => ({
|
|
||||||
id: participant.id,
|
|
||||||
name: participant.name,
|
|
||||||
image: participant.user?.image ?? undefined,
|
|
||||||
})),
|
|
||||||
dateOptions: {
|
|
||||||
first: options[0]?.startTime,
|
|
||||||
last: options[options.length - 1]?.startTime,
|
|
||||||
count: options.length,
|
|
||||||
duration:
|
|
||||||
durations.size === 1
|
|
||||||
? (durations.values().next().value as number)
|
|
||||||
: Array.from(durations),
|
|
||||||
},
|
|
||||||
event: poll.event ?? undefined,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getCachedRecentlyUpdatedPolls = unstable_cache(
|
|
||||||
getRecentlyUpdatedPolls,
|
|
||||||
undefined,
|
|
||||||
{
|
|
||||||
revalidate: 60 * 5,
|
|
||||||
tags: ["polls"],
|
|
||||||
},
|
|
||||||
);
|
|
|
@ -31,11 +31,24 @@ export async function getScheduledEvents({
|
||||||
}) {
|
}) {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
|
const todayStart = dayjs().startOf("day").toDate();
|
||||||
|
const todayEnd = dayjs().endOf("day").toDate();
|
||||||
|
|
||||||
const where: Prisma.ScheduledEventWhereInput = {
|
const where: Prisma.ScheduledEventWhereInput = {
|
||||||
userId,
|
userId,
|
||||||
deletedAt: null,
|
deletedAt: null,
|
||||||
...(status !== "past" && { start: { gte: now } }),
|
...(status === "upcoming" && {
|
||||||
...(status === "past" && { start: { lt: now } }),
|
OR: [
|
||||||
|
{ allDay: false, start: { gte: now } },
|
||||||
|
{ allDay: true, start: { gte: todayStart, lte: todayEnd } },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
...(status === "past" && {
|
||||||
|
OR: [
|
||||||
|
{ allDay: false, start: { lt: now } },
|
||||||
|
{ allDay: true, start: { lt: todayStart } },
|
||||||
|
],
|
||||||
|
}),
|
||||||
...(search && { title: { contains: search, mode: "insensitive" } }),
|
...(search && { title: { contains: search, mode: "insensitive" } }),
|
||||||
status: mapStatus[status],
|
status: mapStatus[status],
|
||||||
};
|
};
|
||||||
|
@ -76,10 +89,6 @@ export async function getScheduledEvents({
|
||||||
|
|
||||||
const events = rawEvents.map((event) => ({
|
const events = rawEvents.map((event) => ({
|
||||||
...event,
|
...event,
|
||||||
status:
|
|
||||||
event.status === "confirmed"
|
|
||||||
? ((event.start < now ? "past" : "upcoming") as Status)
|
|
||||||
: event.status,
|
|
||||||
invites: event.invites.map((invite) => ({
|
invites: event.invites.map((invite) => ({
|
||||||
id: invite.id,
|
id: invite.id,
|
||||||
inviteeName: invite.inviteeName,
|
inviteeName: invite.inviteeName,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { ParticipantAvatarBar } from "@/components/participant-avatar-bar";
|
import { ParticipantAvatarBar } from "@/components/participant-avatar-bar";
|
||||||
import { StackedList } from "@/components/stacked-list";
|
import { StackedList } from "@/components/stacked-list";
|
||||||
import { Trans } from "@/components/trans";
|
import { Trans } from "@/components/trans";
|
||||||
import { ScheduledEventStatusBadge } from "@/features/scheduled-event/components/scheduled-event-status-badge";
|
|
||||||
import type { Status } from "@/features/scheduled-event/schema";
|
|
||||||
import { FormattedDateTime } from "@/features/timezone/client/formatted-date-time";
|
import { FormattedDateTime } from "@/features/timezone/client/formatted-date-time";
|
||||||
|
|
||||||
export const ScheduledEventList = StackedList;
|
export const ScheduledEventList = StackedList;
|
||||||
|
@ -11,7 +9,6 @@ export function ScheduledEventListItem({
|
||||||
title,
|
title,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
status,
|
|
||||||
allDay,
|
allDay,
|
||||||
invites,
|
invites,
|
||||||
floating: isFloating,
|
floating: isFloating,
|
||||||
|
@ -20,7 +17,6 @@ export function ScheduledEventListItem({
|
||||||
title: string;
|
title: string;
|
||||||
start: Date;
|
start: Date;
|
||||||
end: Date;
|
end: Date;
|
||||||
status: Status;
|
|
||||||
allDay: boolean;
|
allDay: boolean;
|
||||||
invites: { id: string; inviteeName: string; inviteeImage?: string }[];
|
invites: { id: string; inviteeName: string; inviteeImage?: string }[];
|
||||||
floating: boolean;
|
floating: boolean;
|
||||||
|
@ -30,9 +26,6 @@ export function ScheduledEventListItem({
|
||||||
<div className="flex flex-1 flex-col gap-y-1 lg:flex-row-reverse lg:justify-end lg:gap-x-4">
|
<div className="flex flex-1 flex-col gap-y-1 lg:flex-row-reverse lg:justify-end lg:gap-x-4">
|
||||||
<div className="flex items-center gap-4 text-sm">
|
<div className="flex items-center gap-4 text-sm">
|
||||||
<div>{title}</div>
|
<div>{title}</div>
|
||||||
<div>
|
|
||||||
<ScheduledEventStatusBadge status={status} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center whitespace-nowrap text-sm lg:min-w-40">
|
<div className="flex items-center whitespace-nowrap text-sm lg:min-w-40">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { mergeRouters, router } from "../trpc";
|
||||||
import { auth } from "./auth";
|
import { auth } from "./auth";
|
||||||
import { dashboard } from "./dashboard";
|
import { dashboard } from "./dashboard";
|
||||||
import { polls } from "./polls";
|
import { polls } from "./polls";
|
||||||
import { scheduledEvents } from "./scheduled-events";
|
|
||||||
import { user } from "./user";
|
import { user } from "./user";
|
||||||
|
|
||||||
dayjs.extend(toArray); // used for creating ics
|
dayjs.extend(toArray); // used for creating ics
|
||||||
|
@ -16,7 +15,6 @@ dayjs.extend(utc);
|
||||||
|
|
||||||
export const appRouter = mergeRouters(
|
export const appRouter = mergeRouters(
|
||||||
router({
|
router({
|
||||||
scheduledEvents,
|
|
||||||
auth,
|
auth,
|
||||||
polls,
|
polls,
|
||||||
user,
|
user,
|
||||||
|
|
|
@ -461,18 +461,27 @@ export const polls = router({
|
||||||
userId: true,
|
userId: true,
|
||||||
guestId: true,
|
guestId: true,
|
||||||
deleted: true,
|
deleted: true,
|
||||||
event: {
|
|
||||||
select: {
|
|
||||||
start: true,
|
|
||||||
duration: true,
|
|
||||||
optionId: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watchers: {
|
watchers: {
|
||||||
select: {
|
select: {
|
||||||
userId: true,
|
userId: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
scheduledEvent: {
|
||||||
|
select: {
|
||||||
|
start: true,
|
||||||
|
end: true,
|
||||||
|
allDay: true,
|
||||||
|
invites: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
inviteeName: true,
|
||||||
|
inviteeEmail: true,
|
||||||
|
inviteeTimeZone: true,
|
||||||
|
status: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
id: input.urlId,
|
id: input.urlId,
|
||||||
|
@ -490,10 +499,33 @@ export const polls = router({
|
||||||
? userId === res.guestId
|
? userId === res.guestId
|
||||||
: userId === res.userId;
|
: userId === res.userId;
|
||||||
|
|
||||||
|
const event = res.scheduledEvent
|
||||||
|
? {
|
||||||
|
start: res.scheduledEvent.start,
|
||||||
|
duration: res.scheduledEvent.allDay
|
||||||
|
? 0
|
||||||
|
: dayjs(res.scheduledEvent.end).diff(
|
||||||
|
dayjs(res.scheduledEvent.start),
|
||||||
|
"minute",
|
||||||
|
),
|
||||||
|
attendees: res.scheduledEvent.invites
|
||||||
|
.map((invite) => ({
|
||||||
|
name: invite.inviteeName,
|
||||||
|
email: invite.inviteeEmail,
|
||||||
|
status: invite.status,
|
||||||
|
}))
|
||||||
|
.filter((invite) => invite.status === "accepted"),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
if (isOwner || res.adminUrlId === input.adminToken) {
|
if (isOwner || res.adminUrlId === input.adminToken) {
|
||||||
return { ...res, inviteLink };
|
return {
|
||||||
|
...res,
|
||||||
|
inviteLink,
|
||||||
|
event,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return { ...res, adminUrlId: "", inviteLink };
|
return { ...res, adminUrlId: "", inviteLink, event };
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
book: proProcedure
|
book: proProcedure
|
||||||
|
@ -626,15 +658,6 @@ export const polls = router({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
event: {
|
|
||||||
create: {
|
|
||||||
optionId: input.optionId,
|
|
||||||
start: eventStart.toDate(),
|
|
||||||
duration: option.duration,
|
|
||||||
title: poll.title,
|
|
||||||
userId: ctx.user.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -818,14 +841,6 @@ export const polls = router({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (poll.eventId) {
|
|
||||||
await prisma.event.delete({
|
|
||||||
where: {
|
|
||||||
id: poll.eventId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (poll.scheduledEventId) {
|
if (poll.scheduledEventId) {
|
||||||
await prisma.scheduledEvent.delete({
|
await prisma.scheduledEvent.delete({
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
import { prisma } from "@rallly/database";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import timezone from "dayjs/plugin/timezone";
|
|
||||||
import toArray from "dayjs/plugin/toArray";
|
|
||||||
import utc from "dayjs/plugin/utc";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
import { privateProcedure, router } from "../trpc";
|
|
||||||
|
|
||||||
dayjs.extend(toArray);
|
|
||||||
dayjs.extend(timezone);
|
|
||||||
dayjs.extend(utc);
|
|
||||||
|
|
||||||
export const scheduledEvents = router({
|
|
||||||
list: privateProcedure
|
|
||||||
.input(
|
|
||||||
z.object({
|
|
||||||
period: z.enum(["upcoming", "past"]).default("upcoming"),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.query(async ({ input, ctx }) => {
|
|
||||||
const events = await prisma.event.findMany({
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
title: true,
|
|
||||||
start: true,
|
|
||||||
duration: true,
|
|
||||||
poll: {
|
|
||||||
select: {
|
|
||||||
timeZone: true,
|
|
||||||
participants: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
where: {
|
|
||||||
userId: ctx.user.id,
|
|
||||||
start:
|
|
||||||
input.period === "upcoming"
|
|
||||||
? { gte: new Date() }
|
|
||||||
: { lt: new Date() },
|
|
||||||
},
|
|
||||||
orderBy: [
|
|
||||||
{
|
|
||||||
start: "desc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "asc",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
return events.map(({ poll, ...event }) => ({
|
|
||||||
...event,
|
|
||||||
timeZone: poll?.timeZone || null,
|
|
||||||
participants: poll?.participants ?? [],
|
|
||||||
}));
|
|
||||||
}),
|
|
||||||
});
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the `events` table. If the table is not empty, all the data it contains will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "events" DROP CONSTRAINT "events_user_id_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "polls" DROP CONSTRAINT "polls_event_id_fkey";
|
||||||
|
|
||||||
|
-- DropTable
|
||||||
|
DROP TABLE "events";
|
|
@ -1,23 +1,3 @@
|
||||||
/**
|
|
||||||
* Events are created when a user creates a new event
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
model Event {
|
|
||||||
id String @id @default(cuid())
|
|
||||||
userId String @map("user_id")
|
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
||||||
optionId String @map("option_id")
|
|
||||||
title String
|
|
||||||
start DateTime @db.Timestamp(0)
|
|
||||||
duration Int @default(0) @map("duration_minutes")
|
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
|
||||||
|
|
||||||
poll Poll?
|
|
||||||
|
|
||||||
@@index([userId], type: Hash)
|
|
||||||
@@map("events")
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ScheduledEventStatus {
|
enum ScheduledEventStatus {
|
||||||
confirmed
|
confirmed
|
||||||
canceled
|
canceled
|
||||||
|
|
|
@ -39,7 +39,6 @@ model Poll {
|
||||||
requireParticipantEmail Boolean @default(false) @map("require_participant_email")
|
requireParticipantEmail Boolean @default(false) @map("require_participant_email")
|
||||||
|
|
||||||
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
event Event? @relation(fields: [eventId], references: [id], onDelete: SetNull)
|
|
||||||
scheduledEvent ScheduledEvent? @relation(fields: [scheduledEventId], references: [id], onDelete: SetNull)
|
scheduledEvent ScheduledEvent? @relation(fields: [scheduledEventId], references: [id], onDelete: SetNull)
|
||||||
options Option[]
|
options Option[]
|
||||||
participants Participant[]
|
participants Participant[]
|
||||||
|
|
|
@ -53,7 +53,6 @@ model User {
|
||||||
comments Comment[]
|
comments Comment[]
|
||||||
polls Poll[]
|
polls Poll[]
|
||||||
watcher Watcher[]
|
watcher Watcher[]
|
||||||
events Event[]
|
|
||||||
accounts Account[]
|
accounts Account[]
|
||||||
participants Participant[]
|
participants Participant[]
|
||||||
paymentMethods PaymentMethod[]
|
paymentMethods PaymentMethod[]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue