Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
89 changes: 9 additions & 80 deletions apps/web/modules/webhooks/components/CreateNewWebhookButton.tsx
Original file line number Diff line number Diff line change
@@ -1,95 +1,24 @@
"use client";

import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
import { trpc } from "@calcom/trpc/react";
import { Avatar, AvatarFallback, AvatarImage } from "@coss/ui/components/avatar";
import { Button } from "@coss/ui/components/button";
import { Menu, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuTrigger } from "@coss/ui/components/menu";
import { ChevronDownIcon, PlusIcon } from "lucide-react";
import { PlusIcon } from "lucide-react";
import { useRouter } from "next/navigation";

function getInitials(name: string): string {
return name
.split(" ")
.map((n) => n[0])
.join("")
.toUpperCase()
.slice(0, 2);
}

export const CreateNewWebhookButton = ({ isEmptyState }: { isEmptyState?: boolean }) => {
export const CreateNewWebhookButton = ({ isEmptyState }: { isEmptyState?: boolean }): JSX.Element => {
const router = useRouter();
const { t } = useLocale();
let variant: "default" | "outline" = "outline";

const query = trpc.viewer.loggedInViewerRouter.teamsAndUserProfilesQuery.useQuery({
includeOrg: true,
withPermission: {
permission: "webhook.create",
fallbackRoles: [MembershipRole.ADMIN, MembershipRole.OWNER],
},
});

if (!query.data) return null;

const options = query.data
.filter((profile) => !profile.readOnly)
.map((profile) => ({
teamId: profile.teamId,
label: profile.name || profile.slug,
image: profile.image,
slug: profile.slug,
}));

const handleSelect = (option: { teamId?: number | null; platform?: boolean }) => {
if (option.platform) {
router.push(`webhooks/new?platform=${option.platform}`);
} else {
router.push(`webhooks/new${option.teamId ? `?teamId=${option.teamId}` : ""}`);
}
};

if (options.length <= 1) {
return (
<Button
data-testid="new_webhook"
onClick={() => handleSelect(options[0] || {})}
variant={isEmptyState ? "default" : "outline"}>
<PlusIcon aria-hidden="true" />
{t("new")}
</Button>
);
if (isEmptyState) {
variant = "default";
}

return (
<Menu>
<MenuTrigger
render={<Button data-testid="new_webhook" variant={isEmptyState ? "default" : "outline"} />}>
{t("new")}
<ChevronDownIcon aria-hidden="true" />
</MenuTrigger>
<MenuPopup align={isEmptyState ? undefined : "end"}>
<MenuGroup>
<MenuGroupLabel>{t("create_for")}</MenuGroupLabel>
{options.map((option, idx) => (
<MenuItem
key={option.label}
data-testid={`option${option.teamId ? "-team" : ""}-${idx}`}
onClick={() => handleSelect(option)}>
<span className="flex items-center gap-2">
<Avatar className="size-5">
{option.image ? <AvatarImage alt={option.label || ""} src={option.image} /> : null}
<AvatarFallback className="text-[.625rem]">
{getInitials(option.label || "")}
</AvatarFallback>
</Avatar>
<span className="truncate">{option.label}</span>
</span>
</MenuItem>
))}
</MenuGroup>
</MenuPopup>
</Menu>
<Button data-testid="new_webhook" onClick={(): void => router.push("webhooks/new")} variant={variant}>
<PlusIcon aria-hidden="true" />
{t("new")}
</Button>
);
};

Expand Down
32 changes: 3 additions & 29 deletions apps/web/modules/webhooks/components/WebhookForm.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
"use client";

import { useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";

import SectionBottomActions from "@calcom/features/settings/SectionBottomActions";
import customTemplate, { hasTemplateIntegration } from "@calcom/features/webhooks/lib/integrationTemplate";
import { WebhookVersion } from "@calcom/features/webhooks/lib/interface/IWebhookRepository";
Expand All @@ -11,15 +8,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { TimeUnit, WebhookTriggerEvents } from "@calcom/prisma/enums";
import type { RouterOutputs } from "@calcom/trpc/react";
import { Button } from "@calcom/ui/components/button";
import { Select } from "@calcom/ui/components/form";
import { TextArea } from "@calcom/ui/components/form";
import { ToggleGroup } from "@calcom/ui/components/form";
import { Form } from "@calcom/ui/components/form";
import { Label } from "@calcom/ui/components/form";
import { TextField } from "@calcom/ui/components/form";
import { Switch } from "@calcom/ui/components/form";


import { Form, Label, Select, Switch, TextArea, TextField, ToggleGroup } from "@calcom/ui/components/form";
import { useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import WebhookTestDisclosure from "./WebhookTestDisclosure";

export type TWebhook = RouterOutputs["viewer"]["webhook"]["list"][number];
Expand Down Expand Up @@ -200,23 +191,6 @@ function getWebhookVariables(t: (key: string) => string) {
},
],
},
{
category: t("webhook_teams"),
variables: [
{
name: "team.name",
variable: "{{team.name}}",
type: "String",
description: t("webhook_team_name"),
},
{
name: "team.members",
variable: "{{team.members}}",
type: "String[]",
description: t("webhook_team_members"),
},
],
},
{
category: t("webhook_metadata"),
variables: [
Expand Down
179 changes: 84 additions & 95 deletions apps/web/modules/webhooks/components/WebhookListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,9 @@ import {
} from "@coss/ui/components/menu";
import { Switch } from "@coss/ui/components/switch";
import { toastManager } from "@coss/ui/components/toast";
import {
Tooltip,
TooltipPopup,
TooltipProvider,
TooltipTrigger,
} from "@coss/ui/components/tooltip";
import { Tooltip, TooltipPopup, TooltipProvider, TooltipTrigger } from "@coss/ui/components/tooltip";
import { useIsMobile } from "@coss/ui/hooks/use-mobile";
import { EllipsisIcon, ExternalLinkIcon, PencilIcon, TrashIcon, WebhookIcon } from "@coss/ui/icons";
import {
ListItem,
ListItemActions,
Expand All @@ -35,7 +31,6 @@ import {
ListItemTitle,
ListItemTitleLink,
} from "@coss/ui/shared/list-item";
import { EllipsisIcon, ExternalLinkIcon, PencilIcon, TrashIcon, WebhookIcon } from "@coss/ui/icons";
import Link from "next/link";
import { useEffect, useState } from "react";
import { DeleteWebhookDialog } from "./dialogs/DeleteWebhookDialog";
Expand Down Expand Up @@ -177,101 +172,98 @@ export default function WebhookListItem(props: {
<ListItemActions>
{!isMobile && (
<TooltipProvider delay={0}>
<div className="flex items-center gap-4">
{props.permissions.canEditWebhook ? (
<Tooltip>
<TooltipTrigger
render={
<Switch
checked={active}
data-testid="webhook-switch"
disabled={toggleWebhook.isPending}
onCheckedChange={(checked) => {
setActive(checked);
toggleWebhook.mutate({
id: webhook.id,
active: checked,
payloadTemplate: webhook.payloadTemplate,
eventTypeId: webhook.eventTypeId || undefined,
});
}}
/>
}
/>
<TooltipPopup sideOffset={11}>
{active ? t("disable_webhook") : t("enable_webhook")}
</TooltipPopup>
</Tooltip>
) : (
<Switch checked={active} disabled />
)}
<div className="flex items-center gap-2">
<div className="flex items-center gap-4">
{props.permissions.canEditWebhook ? (
props.editHref ? (
<Tooltip>
<TooltipTrigger
render={
<Button
aria-label={t("edit")}
data-testid="webhook-edit-button"
render={<Link href={props.editHref} />}
size="icon"
variant="outline"
>
<PencilIcon aria-hidden="true" />
</Button>
}
/>
<TooltipPopup>{t("edit")}</TooltipPopup>
</Tooltip>
<Tooltip>
<TooltipTrigger
render={
<Switch
checked={active}
data-testid="webhook-switch"
disabled={toggleWebhook.isPending}
onCheckedChange={(checked) => {
setActive(checked);
toggleWebhook.mutate({
id: webhook.id,
active: checked,
payloadTemplate: webhook.payloadTemplate,
eventTypeId: webhook.eventTypeId || undefined,
});
}}
/>
}
/>
<TooltipPopup sideOffset={11}>
{active ? t("disable_webhook") : t("enable_webhook")}
</TooltipPopup>
</Tooltip>
) : (
<Switch checked={active} disabled />
)}
<div className="flex items-center gap-2">
{props.permissions.canEditWebhook ? (
props.editHref ? (
<Tooltip>
<TooltipTrigger
render={
<Button
aria-label={t("edit")}
data-testid="webhook-edit-button"
render={<Link href={props.editHref} />}
size="icon"
variant="outline">
<PencilIcon aria-hidden="true" />
</Button>
}
/>
<TooltipPopup>{t("edit")}</TooltipPopup>
</Tooltip>
) : (
<Tooltip>
<TooltipTrigger
render={
<Button
aria-label={t("edit")}
data-testid="webhook-edit-button"
size="icon"
variant="outline"
onClick={props.onEditWebhookAction}>
<PencilIcon aria-hidden="true" />
</Button>
}
/>
<TooltipPopup>{t("edit")}</TooltipPopup>
</Tooltip>
)
) : (
<Button aria-label={t("edit")} disabled size="icon" variant="outline">
<PencilIcon aria-hidden="true" />
</Button>
)}
{props.permissions.canDeleteWebhook ? (
<Tooltip>
<TooltipTrigger
render={
<Button
aria-label={t("edit")}
data-testid="webhook-edit-button"
aria-label={t("delete")}
data-testid="delete-webhook"
size="icon"
variant="outline"
onClick={props.onEditWebhookAction}
>
<PencilIcon aria-hidden="true" />
variant="destructive-outline"
onClick={() => setDeleteDialogOpen(true)}
disabled={deleteWebhook.isPending}>
<TrashIcon aria-hidden="true" />
</Button>
}
/>
<TooltipPopup>{t("edit")}</TooltipPopup>
<TooltipPopup>{t("delete")}</TooltipPopup>
</Tooltip>
)
) : (
<Button aria-label={t("edit")} disabled size="icon" variant="outline">
<PencilIcon aria-hidden="true" />
</Button>
)}
{props.permissions.canDeleteWebhook ? (
<Tooltip>
<TooltipTrigger
render={
<Button
aria-label={t("delete")}
data-testid="delete-webhook"
size="icon"
variant="destructive-outline"
onClick={() => setDeleteDialogOpen(true)}
disabled={deleteWebhook.isPending}
>
<TrashIcon aria-hidden="true" />
</Button>
}
/>
<TooltipPopup>{t("delete")}</TooltipPopup>
</Tooltip>
) : (
<Button aria-label={t("delete")} disabled size="icon" variant="destructive-outline">
<TrashIcon aria-hidden="true" />
</Button>
)}
) : (
<Button aria-label={t("delete")} disabled size="icon" variant="destructive-outline">
<TrashIcon aria-hidden="true" />
</Button>
)}
</div>
</div>
</div>
</TooltipProvider>
)}

Expand All @@ -294,8 +286,7 @@ export default function WebhookListItem(props: {
eventTypeId: webhook.eventTypeId || undefined,
});
}}
variant="switch"
>
variant="switch">
{t("enable_webhook")}
</MenuCheckboxItem>
) : (
Expand Down Expand Up @@ -327,8 +318,7 @@ export default function WebhookListItem(props: {
<MenuItem
variant="destructive"
onClick={() => setDeleteDialogOpen(true)}
disabled={deleteWebhook.isPending}
>
disabled={deleteWebhook.isPending}>
<TrashIcon />
{t("delete")}
</MenuItem>
Expand All @@ -351,7 +341,6 @@ export default function WebhookListItem(props: {
deleteWebhook.mutate({
id: webhook.id,
eventTypeId: webhook.eventTypeId || undefined,
teamId: webhook.teamId || undefined,
});
}}
/>
Expand Down
Loading
Loading