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: New Organization Schema along with the ability to invite existing users to an organization #13002

Merged
merged 70 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
2e03d9a
Add profile table
hariombalhara Jan 13, 2024
04b91da
wip
hariombalhara Jan 3, 2024
367ede5
Get switcher working
hariombalhara Jan 3, 2024
cb94c67
Add organization seeder
hariombalhara Jan 4, 2024
442d430
wip
hariombalhara Jan 15, 2024
3e06263
Remove dead code
hariombalhara Jan 11, 2024
6ae0c24
Fix unit tests
hariombalhara Jan 11, 2024
deb6e03
relevantProfile -> profile
hariombalhara Jan 11, 2024
0a2d343
cache bust
hariombalhara Jan 13, 2024
c5010e9
One more comment
hariombalhara Jan 13, 2024
82529e0
Squash migrations
hariombalhara Jan 13, 2024
8a38cf9
Copy to profile table
hariombalhara Jan 13, 2024
99ba771
Update schema
hariombalhara Jan 14, 2024
7f69117
Fix existing user invite flow
hariombalhara Jan 14, 2024
cf7273d
Add profile table
hariombalhara Jan 13, 2024
03d9bae
Copy to profile table
hariombalhara Jan 13, 2024
11d4c6c
Update schema
hariombalhara Jan 14, 2024
dca50b6
Format
hariombalhara Jan 15, 2024
04c40f3
Add profile table
hariombalhara Jan 13, 2024
abe419c
Format
hariombalhara Jan 15, 2024
e119472
wip
hariombalhara Jan 3, 2024
2fc8cc0
wip
hariombalhara Jan 3, 2024
7cebdc1
Add profile relation everywhere
hariombalhara Jan 15, 2024
ffbd8a0
Merge branch '01-13-New_profile_table_and_data_copy_to_it' into organ…
hariombalhara Jan 16, 2024
40dc7bf
Fix schema
hariombalhara Jan 16, 2024
ade3a02
Merge remote-tracking branch 'origin/organizationId-column' into 01-1…
hariombalhara Jan 16, 2024
bf296f9
Merge branch '01-13-New_profile_table_and_data_copy_to_it' into organ…
hariombalhara Jan 16, 2024
c58ded3
Merge branch 'organizationId-column' into 01-15-feat_Add_relations_wi…
hariombalhara Jan 16, 2024
bf9d7ac
Fix invite handler
hariombalhara Jan 16, 2024
16bf486
Merge branch '01-15-feat_Add_relations_with_profile_wherever_needed' …
hariombalhara Jan 16, 2024
63f56ff
Add profileId during eventTypec reation
hariombalhara Jan 16, 2024
3267566
Get dashboard working with profile relatioon
hariombalhara Jan 19, 2024
50d1e33
Add workflow create repository
hariombalhara Jan 21, 2024
0f823e2
Add profileId to host
hariombalhara Jan 21, 2024
179f7af
Add profileId to credential table
hariombalhara Jan 22, 2024
d3cc068
Add destinationCalendar repository
hariombalhara Jan 22, 2024
a3cd4b8
Add profileId to membership
hariombalhara Jan 22, 2024
09774a5
Revert all profile related changes
hariombalhara Jan 23, 2024
5d74142
Add acme and dunder
hariombalhara Jan 23, 2024
1a9b3f9
Fix membership profileId usgae
hariombalhara Jan 23, 2024
44c755f
Various fixes
hariombalhara Jan 23, 2024
6dea2f1
Some renaming
hariombalhara Jan 24, 2024
6d41df2
Fix failing tests
hariombalhara Jan 24, 2024
ccdf507
Debugging next-aut
hariombalhara Jan 25, 2024
bd4c04c
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 26, 2024
fd8c3f9
Consolidate migrations
hariombalhara Jan 26, 2024
a4bfb8e
Testing fixes
hariombalhara Jan 26, 2024
b559b30
Fix unit tests
hariombalhara Jan 27, 2024
1f39f5a
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 27, 2024
1688ca4
Self review feedback
hariombalhara Jan 27, 2024
ebb1abb
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 28, 2024
c12a9c8
PR feedback
hariombalhara Jan 30, 2024
cb9b3be
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 30, 2024
1a86f2f
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 30, 2024
2729778
Fix orgMigration as well
hariombalhara Jan 30, 2024
423ee4f
Add profile schema and copy users to it
hariombalhara Jan 30, 2024
7cc3153
Remove migrations from here
hariombalhara Jan 30, 2024
9dd96f2
Fix type issues
hariombalhara Jan 30, 2024
2c777e9
Merge remote-tracking branch 'origin/01-13-New_profile_table_and_data…
hariombalhara Jan 30, 2024
b781030
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 30, 2024
4783b48
Fix type error after main merge
hariombalhara Jan 30, 2024
9d657f2
Remove movedFromUserId
hariombalhara Jan 30, 2024
82018db
Merge remote-tracking branch 'origin/main' into organizationId-column
hariombalhara Jan 31, 2024
f387434
Add missing migration file
hariombalhara Jan 31, 2024
1247de4
Self review addressed
hariombalhara Jan 31, 2024
72cea47
Merge branch 'main' into organizationId-column
joeauyeung Jan 31, 2024
07bc2eb
Joe's review addressed
hariombalhara Feb 1, 2024
c626a8e
Fix profile switcher
hariombalhara Feb 2, 2024
8ffb0a1
Merge branch 'main' into organizationId-column
joeauyeung Feb 2, 2024
f74ba88
Merge branch 'main' into organizationId-column
hariombalhara Feb 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions apps/web/components/getting-started/steps-views/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { md } from "@calcom/lib/markdownIt";
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import turndown from "@calcom/lib/turndownService";
import { trpc } from "@calcom/trpc/react";
import type { Ensure } from "@calcom/types/utils";
import { Button, Editor, ImageUploader, Label, showToast } from "@calcom/ui";
import { UserAvatar } from "@calcom/ui";
import { ArrowRight } from "@calcom/ui/components/icon";
Expand Down Expand Up @@ -97,18 +96,10 @@ const UserProfile = () => {
},
];

const organization =
user.organization && user.organization.id
? {
...(user.organization as Ensure<typeof user.organization, "id">),
slug: user.organization.slug || null,
requestedSlug: user.organization.metadata?.requestedSlug || null,
}
: null;
return (
<form onSubmit={onSubmit}>
<div className="flex flex-row items-center justify-start rtl:justify-end">
{user && <UserAvatar size="lg" user={user} previewSrc={imageSrc} organization={organization} />}
{user && <UserAvatar size="lg" user={user} previewSrc={imageSrc} />}
Copy link
Member Author

Choose a reason for hiding this comment

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

User already has profile now which has the organization

<input
ref={avatarRef}
type="hidden"
Expand Down
9 changes: 7 additions & 2 deletions apps/web/components/team/screens/Team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import { useRouterQuery } from "@calcom/lib/hooks/useRouterQuery";
import { md } from "@calcom/lib/markdownIt";
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
import type { TeamWithMembers } from "@calcom/lib/server/queries/teams";
import type { UserProfile } from "@calcom/types/UserProfile";
import { UserAvatar } from "@calcom/ui";

type TeamType = Omit<NonNullable<TeamWithMembers>, "inviteToken">;
type MembersType = TeamType["members"];
type MemberType = Pick<MembersType[number], "id" | "name" | "bio" | "username" | "organizationId"> & {
type MemberType = Pick<
MembersType[number],
"id" | "name" | "bio" | "username" | "organizationId" | "avatarUrl"
> & {
profile: Omit<UserProfile, "upId">;
safeBio: string | null;
bookerUrl: string;
};
Expand All @@ -27,7 +32,7 @@ const Member = ({ member, teamName }: { member: MemberType; teamName: string | n
key={member.id}
href={{ pathname: `${member.bookerUrl}/${member.username}`, query: queryParamsToForward }}>
<div className="sm:min-w-80 sm:max-w-80 bg-default hover:bg-muted border-subtle group flex min-h-full flex-col space-y-2 rounded-md border p-4 hover:cursor-pointer">
<UserAvatar size="md" user={member} />
<UserAvatar noOrganizationIndicator size="md" user={member} />
<section className="mt-2 line-clamp-4 w-full space-y-1">
<p className="text-default font-medium">{member.name}</p>
<div className="text-subtle line-clamp-3 overflow-ellipsis text-sm font-normal">
Expand Down
17 changes: 4 additions & 13 deletions apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { getBookingForReschedule, getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking";
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import { UserRepository } from "@calcom/lib/server/repository/user";
import slugify from "@calcom/lib/slugify";
import prisma from "@calcom/prisma";

Expand Down Expand Up @@ -56,19 +57,9 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
return notFound;
}

const user = await prisma.user.findFirst({
where: {
username,
organization: isValidOrgDomain
? {
slug: currentOrgDomain,
}
: null,
},
select: {
away: true,
hideBranding: true,
},
const [user] = await UserRepository.findUsersByUsername({
usernameList: [username],
orgSlug: org,
});

if (!user) {
Expand Down
7 changes: 5 additions & 2 deletions apps/web/lib/orgMigration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1589,17 +1589,20 @@ async function createTeamOutsideOrg(
});
}

async function createUserOutsideOrg(data: Omit<Prisma.UserCreateArgs["data"], "organization">) {
async function createUserOutsideOrg(
data: Omit<Prisma.UserCreateArgs["data"], "organization" | "movedToProfile">
) {
return await prismock.user.create({
data: {
...data,
movedToProfileId: null,
organizationId: null,
},
});
}

async function createUserInsideTheOrg(
data: Omit<Prisma.UserUncheckedCreateInput, "organization" | "organizationId" | "id">,
data: Omit<Prisma.UserUncheckedCreateInput, "organization" | "organizationId" | "id" | "movedToProfileId">,
orgId: number
) {
const org = await prismock.team.findUnique({
Expand Down
40 changes: 37 additions & 3 deletions apps/web/lib/orgMigration.ts
Copy link
Member

Choose a reason for hiding this comment

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

Should this get into main?

Copy link
Member Author

Choose a reason for hiding this comment

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

We would still need Team migrations. So, till the time we implement the new team -> Organization import, it is needed.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomai
import { HttpError } from "@calcom/lib/http-error";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import { ProfileRepository } from "@calcom/lib/server/repository/profile";
import prisma from "@calcom/prisma";
import type { Team, User } from "@calcom/prisma/client";
import { RedirectType } from "@calcom/prisma/client";
Expand Down Expand Up @@ -327,7 +328,7 @@ async function setOrgSlugIfNotSet(
slug: string | null;
},
orgMetadata: {
requestedSlug?: string | undefined;
requestedSlug?: string | null | undefined;
},
targetOrgId: number
) {
Expand All @@ -348,7 +349,7 @@ async function setOrgSlugIfNotSet(

function assertUserPartOfOrgAndRemigrationAllowed(
userToMoveToOrg: {
organizationId: User["organizationId"];
organizationId: number | null;
},
targetOrgId: number,
targetOrgUsername: string,
Expand Down Expand Up @@ -384,7 +385,7 @@ async function getTeamOrThrowError(targetOrgId: number) {

function assertUserPartOfOtherOrg(
userToMoveToOrg: {
organizationId: User["organizationId"];
organizationId: number | null;
} | null,
userName: string | undefined,
userId: number | undefined,
Expand Down Expand Up @@ -594,6 +595,35 @@ async function dbMoveUserToOrg({
},
},
});

await prisma.profile.upsert({
create: {
uid: ProfileRepository.generateProfileUid(),
userId: userToMoveToOrg.id,
organizationId: targetOrgId,
username: targetOrgUsername,
movedFromUser: {
connect: {
id: userToMoveToOrg.id,
},
},
},
update: {
organizationId: targetOrgId,
username: targetOrgUsername,
movedFromUser: {
connect: {
id: userToMoveToOrg.id,
},
},
},
where: {
userId_organizationId: {
userId: userToMoveToOrg.id,
organizationId: targetOrgId,
},
},
});
}

async function moveTeamsWithoutMembersToOrg({
Expand Down Expand Up @@ -841,6 +871,10 @@ async function dbRemoveUserFromOrg({
},
},
});

await ProfileRepository.deleteMany({
userIds: [userToRemoveFromOrg.id],
});
}

async function removeMembership({
Expand Down
2 changes: 2 additions & 0 deletions apps/web/lib/team/[slug]/getServerSideProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
return {
name: member.name,
id: member.id,
avatarUrl: member.avatarUrl,
bio: member.bio,
profile: member.profile,
subteams: member.subteams,
username: member.username,
accepted: member.accepted,
Expand Down
13 changes: 6 additions & 7 deletions apps/web/modules/event-types/views/event-types-listing-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -729,17 +729,17 @@ const EventTypeListHeading = ({
return (
<div className="mb-4 flex items-center space-x-2">
<Avatar
alt={profile?.name || ""}
alt={profile.name || ""}
href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}
imageSrc={`${bookerUrl}${teamId ? "/team" : ""}/${profile.slug}/avatar.png`}
imageSrc={profile.image}
size="md"
className="mt-1 inline-flex justify-center"
/>
<div>
<Link
href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}
className="text-emphasis font-bold">
{profile?.name || ""}
{profile.name || ""}
</Link>
{membershipCount && teamId && (
<span className="text-subtle relative -top-px me-2 ms-2 text-xs">
Expand All @@ -751,13 +751,13 @@ const EventTypeListHeading = ({
</Link>
</span>
)}
{profile?.slug && (
{profile.slug && (
<Link href={`${bookerUrl}/${profile.slug}`} className="text-subtle block text-xs">
{`${bookerUrl.replace("https://", "").replace("http://", "")}/${profile.slug}`}
</Link>
)}
</div>
{!profile?.slug && !!teamId && (
{!profile.slug && !!teamId && (
<button onClick={() => publishTeamMutation.mutate({ teamId })}>
<Badge variant="gray" className="-ml-2 mb-1">
{t("upgrade")}
Expand Down Expand Up @@ -816,7 +816,7 @@ const CTA = ({ data }: { data: GetByViewerResponse }) => {
const Actions = () => {
return (
<div className="hidden items-center md:flex">
<TeamsFilter popoverTriggerClassNames="mb-0" showVerticalDivider={true} />
<TeamsFilter useProfileFilter popoverTriggerClassNames="mb-0" showVerticalDivider={true} />
Copy link
Member Author

Choose a reason for hiding this comment

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

It is a way to opt-in to profile based DB querying. As event-type supports profileId now.

</div>
);
};
Expand Down Expand Up @@ -853,7 +853,6 @@ const Main = ({
}) => {
const isMobile = useMediaQuery("(max-width: 768px)");
const searchParams = useCompatSearchParams();
const orgBranding = useOrgBranding();

if (!data || status === "pending") {
return <SkeletonLoader />;
Expand Down
Loading