Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Manage Team ooo or crud and fetch past ooo records #16456

Open
wants to merge 54 commits into
base: main
Choose a base branch
from

Conversation

vijayraghav-io
Copy link
Contributor

@vijayraghav-io vijayraghav-io commented Sep 2, 2024

What does this PR do?

Approach to fetch past records:- Infinite scrolling with pagination is implemented to fetch additional records (10 at a time) when the user scrolls to the bottom of the table.
Also search by username and email is implemented to fetch past records of a member quickly.

https://www.loom.com/share/fe88b4739846419493fe26836daedf88?sid=96acca39-eaad-4fcc-89e9-c2153532e080

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • - N/A - I have added a Docs issue here if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Copy link

vercel bot commented Sep 2, 2024

@vijayraghav-io is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@graphite-app graphite-app bot requested a review from a team September 2, 2024 07:37
@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Sep 2, 2024
@github-actions github-actions bot added enterprise area: enterprise, audit log, organisation, SAML, SSO Medium priority Created by Linear-GitHub Sync organizations area: organizations, orgs teams area: teams, round robin, collective, managed event-types ✨ feature New feature or request labels Sep 2, 2024
@dosubot dosubot bot added the ui area: UI, frontend, button, form, input label Sep 2, 2024
@dosubot dosubot bot added this to the v4.5 milestone Sep 2, 2024
Copy link

graphite-app bot commented Sep 2, 2024

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (09/02/24)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add community label" took an action on this PR • (09/02/24)

1 label was added to this PR based on Keith Williams's automation.

"Add foundation team as reviewer" took an action on this PR • (09/23/24)

1 reviewer was added to this PR based on Keith Williams's automation.

Comment on lines 14 to 31
interface OutOfOfficeEntry {
id: number;
uuid: string;
start: Date;
end: Date;
toUserId: number | null;
toUser: {
username: string;
} | null;
reason: {
id: number;
emoji: string;
reason: string;
userId: number;
} | null;
notes: string | null;
user: { id: number; avatarUrl: string; username: string; email: string } | null;
}
Copy link
Contributor

@anikdhabal anikdhabal Sep 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is defined twice, can you pls reuse it another component?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it can be reused, will update

Comment on lines 49 to 50
listMembers
?.filter((member) => (oooType === "mine" ? me?.data?.id !== member.id : oooType === "team"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s better to use enum instead of hardcoded values like "mine" and "team."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Comment on lines 118 to 131
oooType={oooType}
setTeamOOOEntriesUpdated={setTeamOOOEntriesUpdated}
setMyOOOEntriesUpdated={setMyOOOEntriesUpdated}
/>
)}
{oooType === "team" ? (
<OutOfOfficeEntriesListForTeam
editOutOfOfficeEntry={editOutOfOfficeEntry}
teamOOOEntriesUpdated={teamOOOEntriesUpdated}
/>
) : (
<OutOfOfficeEntriesList
editOutOfOfficeEntry={editOutOfOfficeEntry}
myOOOEntriesUpdated={myOOOEntriesUpdated}
Copy link
Contributor

@Amit91848 Amit91848 Sep 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there separate components for Team and Mine view?

As far as I can tell both are same with same functionality and code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are similar, but differ in columns displayed. Wanted to avoid having many conditions within same file for team and mine and keep it separated , s

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handled in single component

@Amit91848
Copy link
Contributor

Unable to scroll Redirect To Member when editing an entry, can only scroll it while adding a new that too I have to close it and open it for it to work, can you also replicate it?

Recording.2024-09-02.133726.mp4

: false,
},
orderBy: {
end: "desc",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo it is better to sort by start date rather than end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Comment on lines 360 to 362
let deletingOooOfUserId = ctx.user.id;
let deletingOooOfEmail = ctx.user.email;
let deletingOooOfUserName = ctx.user.username;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the variable names in the whole file; they need to be improved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was trying to be more descriptive for purpose of new variables, updated, hope it is better now.

Copy link
Contributor

@Amit91848 Amit91848 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff as usual @vijayraghav-io , but this needs some more improvement.

For orgs I can add redirection from one team to another

Recording.2024-09-02.134712.mp4

Comment on lines 453 to 470
const members = await prisma.membership.findMany({
where: {
teamId: {
in: teams.map((team) => team.teamId),
},
userId: {
not: ctx.user.id,
},
},
select: {
userId: true,
},
});
if (members.length === 0) {
throw new TRPCError({ code: "NOT_FOUND", message: "no_team_members" });
}
fetchOOOEntriesForIds = members.map((member) => member.userId);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very performance-reducing operation. Need to be improved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

start: "asc",
});

const outOfOfficeEntries = await prisma.outOfOfficeEntry.findMany({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you not add _count in select for this, instead of having separate queries for count and actual data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first query gets the total count of matching records, while the second query fetches only limited records (say 10). I tried _count can't be used here.

Comment on lines 12 to 43
import type {
TOutOfOfficeDelete,
TOutOfOfficeEntriesListSchema,
TOutOfOfficeInputSchema,
} from "./outOfOffice.schema";

// function getTeam() checks if there is a team where 'adminUserId' is admin or owner
// and 'memberUserId' is a member.
// If exists returns the first found such team.
const getTeam = async (adminUserId: number, memberUserId: number) => {
return await prisma.team.findFirst({
where: {
AND: [
{
members: {
some: {
userId: adminUserId,
role: {
in: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
},
},
},
{
members: {
some: {
userId: memberUserId,
},
},
},
],
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many changes in the backend inside a single file. We definitely need to add tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Tests

Comment on lines 33 to 68
export const OutOfOfficeEntriesListForTeam = ({
editOutOfOfficeEntry,
teamOOOEntriesUpdated,
}: {
editOutOfOfficeEntry: (entry: BookingRedirectForm) => void;
teamOOOEntriesUpdated: number;
}) => {
const { t } = useLocale();
const tableContainerRef = useRef<HTMLDivElement>(null);
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
const [deletedEntry, setDeletedEntry] = useState(0);
const { data, isPending, fetchNextPage, isFetching, refetch } =
trpc.viewer.outOfOfficeEntriesList.useInfiniteQuery(
{
limit: 10,
fetchTeamMembersEntries: true,
searchTerm: debouncedSearchTerm,
},
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
placeholderData: keepPreviousData,
}
);

useEffect(() => {
refetch();
}, [teamOOOEntriesUpdated, deletedEntry, refetch]);

const totalDBRowCount = data?.pages?.[0]?.meta?.totalRowCount ?? 0;
//Flatten the array of arrays from the useInfiniteQuery hook
const flatData = useMemo(
() => data?.pages?.flatMap((page) => page.rows) ?? [],
[data]
) as OutOfOfficeEntry[];
const totalFetched = flatData.length;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, this is similar to the other component. I know there are a few different cases that don't match, but instead of doing the same things twice in two different components, can you please try to consolidate them into a single component? If things become too difficult and there are too many visible conditional changes, it's okay to define 2 components. However, in such cases, define things once and use them in another component. For example, EmptyScreen is defined twice, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handled in single component

Copy link
Contributor

@anikdhabal anikdhabal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @vijayraghav-io , don't test it locally but codewise I've some doubt.

@vijayraghav-io
Copy link
Contributor Author

vijayraghav-io commented Sep 2, 2024

Thankyou! 🙏 @Amit91848 @anikdhabal , sure will address the comments.

@vijayraghav-io
Copy link
Contributor Author

Unable to scroll Redirect To Member when editing an entry, can only scroll it while adding a new that too I have to close it and open it for it to work, can you also replicate it?

I checked multiple times, not able to recreate this for me. Able to search the list of members for redirect also.

Copy link
Member

@CarinaWolli CarinaWolli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't review the code but tested it locally, found the following issues:

}
columns.push({
id: "outOfOffice",
header: `OutOfOffice (${totalDBRowCount})`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be 'Out of office' with a translation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Copy link

vercel bot commented Dec 10, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
cal ⬜️ Ignored (Inspect) Visit Preview Dec 11, 2024 1:20pm
calcom-web-canary ⬜️ Ignored (Inspect) Visit Preview Dec 11, 2024 1:20pm

@vijayraghav-io
Copy link
Contributor Author

vijayraghav-io commented Dec 10, 2024

@vijayraghav-io unit tests are failing, please fix it 🙏

@anikdhabal , @Praashh resolved conflicts, updated tests due to changes from merges.
Also verified and tested again team OOO flow.

@anikdhabal
Copy link
Contributor

@vijayraghav-io great works man. But I am thinking of completely transferring all the E2E tests related to OOO into unit tests. Could you go through all the OOO E2E tests and add them to your current test file along with the other tests?

@vijayraghav-io
Copy link
Contributor Author

@vijayraghav-io great works man. But I am thinking of completely transferring all the E2E tests related to OOO into unit tests. Could you go through all the OOO E2E tests and add them to your current test file along with the other tests?

Thank you! @anikdhabal .
IMO replacing E2E tests with unit tests may reduce the current scope of testing for OOO.
As these are End to End tests testing both UI and backend functionalities.
Also the flakiness for OOO tests is reduced very much now, observing the E2E results from latest PRs merged after #18367

@anikdhabal
Copy link
Contributor

anikdhabal commented Dec 29, 2024

IMO replacing E2E tests with unit tests may reduce the current scope of testing for OOO.
As these are End to End tests testing both UI and backend functionalities.
Also the flakiness for OOO tests is reduced very much now, observing the E2E results from latest PRs merged after #18367

If this is the case, then why are we adding tests to the handler here? Can't we add e2e tests instead to verify both the UI and functionalities for this PR? I think it would make sense to create a single test file for OOO and add e2e tests for this. Let's make the change then

I've noticed that recent PRs failed due to OOO tests. Also, I have a query regarding that PR #18367, and we generally avoid any time dependency in e2e tests.

@vijayraghav-io
Copy link
Contributor Author

I've noticed that recent PRs failed due to OOO tests. Also, I have a query regarding that PR #18367, and we generally avoid any time dependency in e2e tests.

Can you please recheck again, recent PRs don't have flakiness due to OOO tests.
Yeah E2E tests for Team OOO can be added.

@vijayraghav-io
Copy link
Contributor Author

These are some of E2E results after OOO flakiness fix PR (#18367) was merged.

Screenshot 2024-12-29 at 9 56 24 PM Screenshot 2024-12-29 at 10 08 56 PM

This is the latest after above PR is reverted (OOO flakiness reappeared).

Screenshot 2024-12-29 at 10 02 18 PM

@vijayraghav-io
Copy link
Contributor Author

vijayraghav-io commented Dec 29, 2024

@anikdhabal , updated OOO E2E tests to remove flakiness without time dependency in this new PR #18412

@vijayraghav-io
Copy link
Contributor Author

vijayraghav-io commented Jan 16, 2025

@anikdhabal , resolved merge conflicts.

Also, I tried to create E2E tests for Team OOO instead of current unit tests, but currently there is some playwright limitations for this.
So, I think currently we can go with unit tests for Team OOO and once we have the solution from playwright we can create E2E tests.
The limitation is :
For Team OOO, the Create OOO Dialog is taller (because of member selection for For Member and To Member, and also have made it to be minimum possible) , hence playwright can't reach the create button and redirect member selection as playwright starts with default 100% browser zoom.
It will be possible if chromium browser is zoomed out.
Currently playwright does not support browser zoom out through its APIs.
There are some issues already raised in playwright repo, refs - microsoft/playwright#2497 , microsoft/playwright#32352

PFB the Loom showing the issue with a team OOO E2E test, here i have manually zoomed out chromium browser while playwright is trying to reach down. (Here test is passing because of manul zoom out during test)

https://www.loom.com/share/10a0e9474d534f1b9a99b0564a8b4e98?sid=16eab3c0-6281-4de3-b0af-63443c17dc04

Hope, with this all concerns are addressed.

@dosubot dosubot bot modified the milestones: v4.9, v4.10 Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Created by Linear-GitHub Sync enterprise area: enterprise, audit log, organisation, SAML, SSO ✨ feature New feature or request Medium priority Created by Linear-GitHub Sync organizations area: organizations, orgs ready-for-e2e Stale teams area: teams, round robin, collective, managed event-types ui area: UI, frontend, button, form, input
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[CAL-4527] OOO: Show your own history and give Admins CRUD and see all team members history
6 participants