Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: platform onboarding flow and dashboard (#14721)
* add endpoint to fetch managed user from client id * update typings * minor tweaks * custom hook to fetch managed users from client id * add translations for platform onboarding * add isPlatformOrg boolean to figure out which is platform and which is not * set isPlatform hook based on data obtained from org * add limitWidth prop to control component width * add props to shell to make sidebar display different tabs based on if the shell isPlattform or not * platform related pages * fix merge conflicts * fix merge conflicts * platform oauth client form and card * remove everything related to platform from organization * update oauth client card and form * fixup * fix imports and remove logs * fixup * update redirect url * split oauth client form into separate update and create forms * separate forms for create and edit oauth clients * fixup * fixup * dynamic routes for oauth client edit page * fixup fixup * fix to not show error when redirect uri is empty * refactor create handler for org * cleaup comments * add custom hook to check user billing * export managed user type * refactor platform index page * refactor edit and create pages * dashboard component containing oauth client list and managed user * common oauth client form used for create and edit form * platform pricing helper * platform pricing component * fix typing and data response for billing * use custom hook to check team billing info * fix type checks * upgrade conditional rendering for upgrade to org banner * add isLoading prop to check button loading state * pass in button handler * add custom hook to subscribe to stripe and typings * update typings * fix incorrect endpoint * pass in team id as prop * fix type check * update stripe success and cancel redirect url * add and pass redirect url param to custom hook * custom hooks for platform * cleanup * update imports * fix merge conflicts * fixup * fixup fixup * fixup * merge conflicts fixup * merge conlficts battle :( * minor fixes * skip admin checks for a platform client * fix typo * append slug with _platform for a platform user * PR feedback * dashboard refactor * bring back org form to its orginal state * add platform folder to ee * update typings * use new create platform form * fixup * fix typo and update plans * simplifying rendering * remove managed users endpoint since it already exists * url for endpoint * rename tabs * pr feedback * managed users endpoint * update endpoint * remove form --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: exception <erik@erosemberg.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>
- Loading branch information
1 parent
6d8fbfc
commit c2a07e2
Showing
31 changed files
with
1,258 additions
and
355 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export enum PlatformPlan { | ||
STARTER = "STARTER", | ||
ESSENTIALS = "ESSENTIALS", | ||
SCALE = "SCALE", | ||
ENTERPRISE = "ENTERPRISE", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
apps/web/components/settings/platform/dashboard/managed-user-header/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { PlatformOAuthClient } from "@calcom/prisma/client"; | ||
|
||
import { OAuthClientsDropdown } from "@components/settings/platform/dashboard/oauth-client-dropdown"; | ||
|
||
type ManagedUserHeaderProps = { | ||
oauthClients: PlatformOAuthClient[]; | ||
initialClientName: string; | ||
handleChange: (clientId: string, clientName: string) => void; | ||
}; | ||
|
||
export const ManagedUserHeader = ({ | ||
oauthClients, | ||
initialClientName, | ||
handleChange, | ||
}: ManagedUserHeaderProps) => { | ||
return ( | ||
<div className="border-subtle mx-auto block justify-between rounded-t-lg border px-4 py-6 sm:flex sm:px-6"> | ||
<div className="flex w-full flex-col"> | ||
<h1 className="font-cal text-emphasis mb-1 text-xl font-semibold leading-5 tracking-wide"> | ||
Managed Users | ||
</h1> | ||
<p className="text-default text-sm ltr:mr-4 rtl:ml-4"> | ||
See all the managed users created by your OAuth client. | ||
</p> | ||
</div> | ||
<OAuthClientsDropdown | ||
oauthClients={oauthClients} | ||
initialClientName={initialClientName} | ||
handleChange={handleChange} | ||
/> | ||
</div> | ||
); | ||
}; |
39 changes: 39 additions & 0 deletions
39
apps/web/components/settings/platform/dashboard/managed-user-list/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import type { PlatformOAuthClient } from "@calcom/prisma/client"; | ||
|
||
import type { ManagedUser } from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients"; | ||
|
||
import { ManagedUserHeader } from "@components/settings/platform/dashboard/managed-user-header"; | ||
import { ManagedUserTable } from "@components/settings/platform/dashboard/managed-user-table"; | ||
|
||
type ManagedUserListProps = { | ||
oauthClients: PlatformOAuthClient[]; | ||
managedUsers?: ManagedUser[]; | ||
initialClientName: string; | ||
initialClientId: string; | ||
isManagedUserLoading: boolean; | ||
handleChange: (clientId: string, clientName: string) => void; | ||
}; | ||
|
||
export const ManagedUserList = ({ | ||
initialClientName, | ||
initialClientId, | ||
oauthClients, | ||
managedUsers, | ||
isManagedUserLoading, | ||
handleChange, | ||
}: ManagedUserListProps) => { | ||
return ( | ||
<div> | ||
<ManagedUserHeader | ||
oauthClients={oauthClients} | ||
initialClientName={initialClientName} | ||
handleChange={handleChange} | ||
/> | ||
<ManagedUserTable | ||
managedUsers={managedUsers} | ||
isManagedUserLoading={isManagedUserLoading} | ||
initialClientId={initialClientId} | ||
/> | ||
</div> | ||
); | ||
}; |
60 changes: 60 additions & 0 deletions
60
apps/web/components/settings/platform/dashboard/managed-user-table/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { EmptyScreen } from "@calcom/ui"; | ||
|
||
import type { ManagedUser } from "@lib/hooks/settings/platform/oauth-clients/useOAuthClients"; | ||
|
||
type ManagedUserTableProps = { | ||
managedUsers?: ManagedUser[]; | ||
isManagedUserLoading: boolean; | ||
initialClientId: string; | ||
}; | ||
|
||
export const ManagedUserTable = ({ | ||
managedUsers, | ||
isManagedUserLoading, | ||
initialClientId, | ||
}: ManagedUserTableProps) => { | ||
const showUsers = !isManagedUserLoading && managedUsers?.length; | ||
|
||
return ( | ||
<div> | ||
{showUsers ? ( | ||
<> | ||
<table className="w-[100%] rounded-lg"> | ||
<colgroup className="border-subtle overflow-hidden rounded-b-lg border border-b-0" span={3} /> | ||
<tr> | ||
<td className="border-subtle border px-4 py-3 md:text-center">Id</td> | ||
<td className="border-subtle border px-4 py-3 md:text-center">Username</td> | ||
<td className="border-subtle border px-4 py-3 md:text-center">Email</td> | ||
</tr> | ||
{managedUsers.map((user) => { | ||
return ( | ||
<tr key={user.id} className=""> | ||
<td className="border-subtle overflow-hidden border px-4 py-3 md:text-center">{user.id}</td> | ||
<td className="border-subtle border px-4 py-3 md:text-center">{user.username}</td> | ||
<td className="border-subtle overflow-hidden border px-4 py-3 md:overflow-auto md:text-center"> | ||
{user.email} | ||
</td> | ||
</tr> | ||
); | ||
})} | ||
</table> | ||
</> | ||
) : ( | ||
<EmptyScreen | ||
limitWidth={false} | ||
headline={ | ||
initialClientId == undefined | ||
? "OAuth client is missing. You need to create an OAuth client first in order to create a managed user." | ||
: `OAuth client ${initialClientId} does not have a managed user present.` | ||
} | ||
description={ | ||
initialClientId == undefined | ||
? "Refer to the Platform Docs from the sidebar in order to create an OAuth client." | ||
: "Refer to the Platform Docs from the sidebar in order to create a managed user." | ||
} | ||
className="items-center border" | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; |
50 changes: 50 additions & 0 deletions
50
apps/web/components/settings/platform/dashboard/oauth-client-dropdown/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import type { PlatformOAuthClient } from "@calcom/prisma/client"; | ||
import { | ||
Button, | ||
Dropdown, | ||
DropdownMenuTrigger, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownItem, | ||
} from "@calcom/ui"; | ||
|
||
type OAuthClientsDropdownProps = { | ||
oauthClients: PlatformOAuthClient[]; | ||
initialClientName: string; | ||
handleChange: (clientId: string, clientName: string) => void; | ||
}; | ||
|
||
export const OAuthClientsDropdown = ({ | ||
oauthClients, | ||
initialClientName, | ||
handleChange, | ||
}: OAuthClientsDropdownProps) => { | ||
return ( | ||
<div> | ||
{Array.isArray(oauthClients) && oauthClients.length > 0 ? ( | ||
<Dropdown modal={false}> | ||
<DropdownMenuTrigger asChild> | ||
<Button color="secondary">{initialClientName}</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent> | ||
{oauthClients.map((client) => { | ||
return ( | ||
<div key={client.id}> | ||
{initialClientName !== client.name ? ( | ||
<DropdownMenuItem className="outline-none"> | ||
<DropdownItem type="button" onClick={() => handleChange(client.id, client.name)}> | ||
{client.name} | ||
</DropdownItem> | ||
</DropdownMenuItem> | ||
) : ( | ||
<></> | ||
)} | ||
</div> | ||
); | ||
})} | ||
</DropdownMenuContent> | ||
</Dropdown> | ||
) : null} | ||
</div> | ||
); | ||
}; |
81 changes: 81 additions & 0 deletions
81
apps/web/components/settings/platform/dashboard/oauth-clients-list/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { useRouter } from "next/navigation"; | ||
|
||
import type { PlatformOAuthClient } from "@calcom/prisma/client"; | ||
import { EmptyScreen, Button } from "@calcom/ui"; | ||
|
||
import { OAuthClientCard } from "@components/settings/platform/oauth-clients/OAuthClientCard"; | ||
|
||
type OAuthClientsListProps = { | ||
oauthClients: PlatformOAuthClient[]; | ||
isDeleting: boolean; | ||
handleDelete: (id: string) => Promise<void>; | ||
}; | ||
|
||
export const OAuthClientsList = ({ oauthClients, isDeleting, handleDelete }: OAuthClientsListProps) => { | ||
return ( | ||
<div className="mb-10"> | ||
<div className="border-subtle mx-auto block justify-between rounded-t-lg border px-4 py-6 sm:flex sm:px-6"> | ||
<div className="flex w-full flex-col"> | ||
<h1 className="font-cal text-emphasis mb-1 text-xl font-semibold leading-5 tracking-wide"> | ||
OAuth Clients | ||
</h1> | ||
<p className="text-default text-sm ltr:mr-4 rtl:ml-4"> | ||
Connect your platform to cal.com with OAuth | ||
</p> | ||
</div> | ||
<div> | ||
<NewOAuthClientButton redirectLink="/settings/platform/oauth-clients/create" /> | ||
</div> | ||
</div> | ||
{Array.isArray(oauthClients) && oauthClients.length ? ( | ||
<> | ||
<div className="border-subtle rounded-b-lg border border-t-0"> | ||
{oauthClients.map((client, index) => { | ||
return ( | ||
<OAuthClientCard | ||
name={client.name} | ||
redirectUris={client.redirectUris} | ||
bookingRedirectUri={client.bookingRedirectUri} | ||
bookingRescheduleRedirectUri={client.bookingRescheduleRedirectUri} | ||
bookingCancelRedirectUri={client.bookingCancelRedirectUri} | ||
permissions={client.permissions} | ||
key={index} | ||
lastItem={oauthClients.length === index + 1} | ||
id={client.id} | ||
secret={client.secret} | ||
isLoading={isDeleting} | ||
onDelete={handleDelete} | ||
areEmailsEnabled={client.areEmailsEnabled} | ||
/> | ||
); | ||
})} | ||
</div> | ||
</> | ||
) : ( | ||
<EmptyScreen | ||
headline="Create your first OAuth client" | ||
description="OAuth clients facilitate access to Cal.com on behalf of users" | ||
Icon="plus" | ||
className="" | ||
buttonRaw={<NewOAuthClientButton redirectLink="/settings/platform/oauth-clients/create" />} | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
const NewOAuthClientButton = ({ redirectLink, label }: { redirectLink: string; label?: string }) => { | ||
const router = useRouter(); | ||
|
||
return ( | ||
<Button | ||
onClick={(e) => { | ||
e.preventDefault(); | ||
router.push(redirectLink); | ||
}} | ||
color="secondary" | ||
StartIcon="plus"> | ||
{!!label ? label : "Add"} | ||
</Button> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.