feat: Org and Team ID on organisation and team pages (#20645)

* added org and team id on respective pages

* added error hadling on clipboard.writeText
This commit is contained in:
Gaurav Verma
2025-04-14 09:37:46 +05:30
committed by GitHub
parent 4383d23d4c
commit 7952cfc9e9
3 changed files with 81 additions and 3 deletions
@@ -670,9 +670,14 @@
"team_updated_successfully": "Team updated successfully",
"your_team_updated_successfully": "Your team has been updated successfully.",
"your_org_updated_successfully": "Your Org has been updated successfully.",
"error_copying_to_clipboard": "Error copying to clipboard",
"about": "About",
"team_description": "A few sentences about your team. This will appear on your team's url page.",
"organization_id": "Organization ID",
"organization_id_copied": "Organization ID copied.",
"org_description": "A few sentences about your organization. This will appear on your organization's url page.",
"team_id": "Team ID",
"team_id_copied": "Team ID copied.",
"members": "Members",
"organization_members": "Organization members",
"member": "Member",
@@ -36,6 +36,7 @@ import {
SkeletonAvatar,
} from "@calcom/ui/components/skeleton";
import { showToast } from "@calcom/ui/components/toast";
import { Tooltip } from "@calcom/ui/components/tooltip";
import { useOrgBranding } from "../../../organizations/context/provider";
@@ -48,6 +49,7 @@ const orgProfileFormSchema = z.object({
});
type FormValues = {
id: number;
name: string;
logoUrl: string | null;
banner: string | null;
@@ -111,6 +113,7 @@ const OrgProfileView = () => {
!currentOrganisation.bio.replace("<p><br></p>", "").length;
const defaultValues: FormValues = {
id: currentOrganisation?.id,
name: currentOrganisation?.name || "",
logoUrl: currentOrganisation?.logoUrl,
banner: currentOrganisation?.bannerUrl || "",
@@ -204,6 +207,14 @@ const OrgProfileForm = ({ defaultValues }: { defaultValues: FormValues }) => {
const isDisabled = isSubmitting || !isDirty;
const handleCopy = async (value: string) => {
try {
await navigator.clipboard.writeText(value);
showToast(t("organization_id_copied"), "success");
} catch (error) {
showToast(t("error_copying_to_clipboard"), "error");
}
};
return (
<Form
form={form}
@@ -368,6 +379,32 @@ const OrgProfileForm = ({ defaultValues }: { defaultValues: FormValues }) => {
</div>
)}
/>
<Controller
control={form.control}
name="id"
render={({ field: { value } }) => (
<div className="mt-8">
<TextField
name="id"
label={t("organization_id")}
value={value}
disabled={true}
addOnSuffix={
<Tooltip content={t("copy_to_clipboard")}>
<Button
color="minimal"
size="sm"
type="button"
aria-label="copy organization id"
onClick={() => handleCopy(value.toString())}>
<Icon name="copy" className="ml-1 h-4 w-4" />
</Button>
</Tooltip>
}
/>
</div>
)}
/>
<div className="mt-8">
<Label>{t("about")}</Label>
<Editor
@@ -32,6 +32,7 @@ import { Editor } from "@calcom/ui/components/editor";
import { Form } from "@calcom/ui/components/form";
import { Label } from "@calcom/ui/components/form";
import { TextField } from "@calcom/ui/components/form";
import { Icon } from "@calcom/ui/components/icon";
import { ImageUploader } from "@calcom/ui/components/image-uploader";
import {
SkeletonButton,
@@ -40,10 +41,12 @@ import {
SkeletonAvatar,
} from "@calcom/ui/components/skeleton";
import { showToast } from "@calcom/ui/components/toast";
import { Tooltip } from "@calcom/ui/components/tooltip";
const regex = new RegExp("^[a-zA-Z0-9-]*$");
const teamProfileFormSchema = z.object({
id: z.number(),
name: z.string(),
slug: z
.string()
@@ -162,7 +165,7 @@ const ProfileView = () => {
return (
<>
{isAdmin ? (
<TeamProfileForm team={team} />
<TeamProfileForm team={team} teamId={teamId} />
) : (
<div className="border-subtle flex rounded-b-xl border border-t-0 px-4 py-8 sm:px-6">
<div className="flex-grow">
@@ -248,9 +251,12 @@ const ProfileView = () => {
);
};
export type TeamProfileFormProps = { team: RouterOutputs["viewer"]["teams"]["get"] };
export type TeamProfileFormProps = {
team: RouterOutputs["viewer"]["teams"]["get"];
teamId: number;
};
const TeamProfileForm = ({ team }: TeamProfileFormProps) => {
const TeamProfileForm = ({ team, teamId }: TeamProfileFormProps) => {
const utils = trpc.useUtils();
const { t } = useLocale();
const router = useRouter();
@@ -275,6 +281,7 @@ const TeamProfileForm = ({ team }: TeamProfileFormProps) => {
});
const defaultValues: FormValues = {
id: team?.id,
name: team?.name || "",
logo: team?.logo || "",
bio: team?.bio || "",
@@ -306,6 +313,14 @@ const TeamProfileForm = ({ team }: TeamProfileFormProps) => {
},
});
const handleCopy = async (value: string) => {
try {
await navigator.clipboard.writeText(value);
showToast(t("team_id_copied"), "success");
} catch (error) {
showToast(t("error_copying_to_clipboard"), "error");
}
};
return (
<Form
form={form}
@@ -399,6 +414,27 @@ const TeamProfileForm = ({ team }: TeamProfileFormProps) => {
</div>
)}
/>
<div className="mt-8">
<TextField
name="id"
label={t("team_id")}
value={teamId}
disabled={true}
addOnSuffix={
<Tooltip content={t("copy_to_clipboard")}>
<Button
color="minimal"
size="sm"
type="button"
aria-label="copy team id"
onClick={() => handleCopy(teamId.toString())}>
<Icon name="copy" className="ml-1 h-4 w-4" />
</Button>
</Tooltip>
}
/>
</div>
<div className="mt-8">
<Label>{t("about")}</Label>
<Editor