Skip to content

Commit

Permalink
Merge branch 'main' into feat/add-csat-v2-api
Browse files Browse the repository at this point in the history
  • Loading branch information
supalarry authored Feb 14, 2025
2 parents 13bdf37 + b2763a6 commit 3ee5847
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 5 deletions.
2 changes: 1 addition & 1 deletion apps/web/app/(use-page-wrapper)/apps/[slug]/setup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
return <SetupView {...props} />;
};

export default ServerPage;
export default ServerPage;
11 changes: 9 additions & 2 deletions apps/web/modules/bookings/views/bookings-listing-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
getSortedRowModel,
createColumnHelper,
} from "@tanstack/react-table";
import { useMemo, useState } from "react";
import { useMemo, useState, useEffect } from "react";
import type { z } from "zod";

import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
Expand Down Expand Up @@ -95,12 +95,19 @@ type RowData =
};

function BookingsContent({ status }: BookingsProps) {
const { data: filterQuery } = useFilterQuery();
const { data: filterQuery, pushItemToKey } = useFilterQuery();

const { t } = useLocale();
const user = useMeQuery().data;
const [isFiltersVisible, setIsFiltersVisible] = useState<boolean>(false);

useEffect(() => {
if (user?.isTeamAdminOrOwner && !filterQuery.userIds?.length) {
setIsFiltersVisible(true);
pushItemToKey("userIds", user?.id);
}
}, [user, filterQuery.status]);

const query = trpc.viewer.bookings.get.useInfiniteQuery(
{
limit: 10,
Expand Down
93 changes: 92 additions & 1 deletion apps/web/playwright/bookings-list.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { expect } from "@playwright/test";

import { prisma } from "@calcom/prisma";
import { BookingStatus } from "@calcom/prisma/client";
import { MembershipRole } from "@calcom/prisma/enums";

import type { Fixtures } from "./lib/fixtures";
import { test } from "./lib/fixtures";
import { setupManagedEvent } from "./lib/testUtils";
import { localize, setupManagedEvent } from "./lib/testUtils";

test.afterEach(({ users }) => users.deleteAll());

Expand Down Expand Up @@ -207,6 +209,95 @@ test.describe("Bookings", () => {
webhookReceiver.close();
});
});
test("Admin bookings filtered by default", async ({ page, users, bookings }) => {
const t = await localize("en");
const firstUser = await users.create(
{ name: "First", email: "[email protected]" },
{
hasTeam: true,
teamRole: MembershipRole.ADMIN,
}
);
const teamId = (await firstUser.getFirstTeamMembership()).teamId;
const secondUser = await users.create({ name: "Second", email: "[email protected]" });
const thirdUser = await users.create({ name: "Third", email: "[email protected]" });
// Add teammates to the team
await prisma.membership.createMany({
data: [
{
teamId: teamId,
userId: secondUser.id,
role: MembershipRole.MEMBER,
accepted: true,
},
{
teamId: teamId,
userId: thirdUser.id,
role: MembershipRole.MEMBER,
accepted: true,
},
],
});

//Create a single booking for FirstUser(admin)
const firstUserBookingFixture = await createBooking({
title: "FirstUser as Organizer Meeting",
bookingsFixture: bookings,
relativeDate: 3,
organizer: firstUser,
organizerEventType: firstUser.eventTypes[0],
attendees: [
{ name: "Second", email: secondUser.email, timeZone: "Europe/Berlin" },
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
],
});
const firstUserBooking = await firstUserBookingFixture.self();

//Create 2 bookings for SecondUser
await createBooking({
title: "SecondUser as Organizer Meeting 1",
bookingsFixture: bookings,
organizer: secondUser,
relativeDate: 2,
organizerEventType: secondUser.eventTypes[0],
attendees: [
{ name: "First", email: firstUser.email, timeZone: "Europe/Berlin" },
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
],
});
await createBooking({
title: "SecondUser as Organizer Meeting 2",
bookingsFixture: bookings,
organizer: secondUser,
relativeDate: 4,
organizerEventType: secondUser.eventTypes[0],
attendees: [
{ name: "First", email: firstUser.email, timeZone: "Europe/Berlin" },
{ name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
],
});

//admin login
await firstUser.apiLogin();
await Promise.all([
page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url())),
page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url())),
page.goto(`/bookings/upcoming`),
page.waitForTimeout(10000),
page.waitForURL(`**\/upcoming?status=upcoming&userIds=${firstUser.id}`),
]);

//expect only 1 booking (of admin) to be shown in list due to default filtering for admin
const upcomingBookingsTable = page.locator('[data-testid="upcoming-bookings"]');
const bookingListItems = upcomingBookingsTable.locator('[data-testid="booking-item"]');
const bookingListCount = await bookingListItems.count();
expect(bookingListCount).toBe(1);
const firstUpcomingBooking = bookingListItems.nth(0);
await expect(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
firstUpcomingBooking.locator(`text=${firstUserBooking!.title}`)
).toBeVisible();
});
});

async function createBooking({
Expand Down
1 change: 1 addition & 0 deletions packages/features/bookings/components/FiltersContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function FiltersContainer({ isFiltersVisible }: FiltersContainerProps) {
<StartTimeFilters />
<Tooltip content={t("remove_filters")}>
<Button
data-testid="btn_bookings_list_remove_filters"
disabled={!hasValidQueryParams}
color="secondary"
type="button"
Expand Down
15 changes: 14 additions & 1 deletion packages/trpc/server/routers/loggedInViewer/me.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
import { ProfileRepository } from "@calcom/lib/server/repository/profile";
import { UserRepository } from "@calcom/lib/server/repository/user";
import prisma from "@calcom/prisma";
import { IdentityProvider } from "@calcom/prisma/enums";
import { IdentityProvider, MembershipRole } from "@calcom/prisma/enums";
import { userMetadata } from "@calcom/prisma/zod-utils";
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";

Expand Down Expand Up @@ -94,6 +94,18 @@ export const meHandler = async ({ ctx, input }: MeOptions) => {
organizationSettings: user?.profile?.organization?.organizationSettings,
};

const isTeamAdminOrOwner =
(await prisma.membership.findFirst({
where: {
userId: user.id,
accepted: true,
role: { in: [MembershipRole.ADMIN, MembershipRole.OWNER] },
},
select: {
id: true,
},
})) !== null;

return {
id: user.id,
name: user.name,
Expand Down Expand Up @@ -132,5 +144,6 @@ export const meHandler = async ({ ctx, input }: MeOptions) => {
secondaryEmails,
isPremium: userMetadataPrased?.isPremium,
...(passwordAdded ? { passwordAdded } : {}),
isTeamAdminOrOwner,
};
};

0 comments on commit 3ee5847

Please sign in to comment.