Skip to content

Commit 15f8037

Browse files
authored
Merge branch 'main' into fix-add-more-data-to-stripe-payment-metadata-10678-cal-2327
2 parents 9bed30f + acaa79b commit 15f8037

20 files changed

Lines changed: 1484 additions & 4291 deletions

File tree

apps/web/pages/event-types/index.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ import {
5252
Skeleton,
5353
Switch,
5454
Tooltip,
55+
ArrowButton,
5556
} from "@calcom/ui";
5657
import {
57-
ArrowDown,
58-
ArrowUp,
5958
Clipboard,
6059
Code,
6160
Copy,
@@ -378,19 +377,11 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
378377
<div className="hover:bg-muted flex w-full items-center justify-between">
379378
<div className="group flex w-full max-w-full items-center justify-between overflow-hidden px-4 py-4 sm:px-6">
380379
{!(firstItem && firstItem.id === type.id) && (
381-
<button
382-
className="bg-default text-muted hover:text-emphasis border-default hover:border-emphasis invisible absolute left-[5px] -ml-4 -mt-4 mb-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[36px]"
383-
onClick={() => moveEventType(index, -1)}>
384-
<ArrowUp className="h-5 w-5" />
385-
</button>
380+
<ArrowButton onClick={() => moveEventType(index, -1)} arrowDirection="up" />
386381
)}
387382

388383
{!(lastItem && lastItem.id === type.id) && (
389-
<button
390-
className="bg-default text-muted border-default hover:text-emphasis hover:border-emphasis invisible absolute left-[5px] -ml-4 mt-8 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[36px]"
391-
onClick={() => moveEventType(index, 1)}>
392-
<ArrowDown className="h-5 w-5" />
393-
</button>
384+
<ArrowButton onClick={() => moveEventType(index, 1)} arrowDirection="down" />
394385
)}
395386
<MemoizedItem type={type} group={group} readOnly={readOnly} />
396387
<div className="mt-4 hidden sm:mt-0 sm:flex">

packages/app-store/routing-forms/pages/forms/[...appPages].tsx

Lines changed: 152 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// TODO: i18n
2+
import { useAutoAnimate } from "@formkit/auto-animate/react";
23
import { useEffect } from "react";
34
import { useFormContext } from "react-hook-form";
45

@@ -30,6 +31,7 @@ import {
3031
List,
3132
ListLinkItem,
3233
Tooltip,
34+
ArrowButton,
3335
} from "@calcom/ui";
3436
import {
3537
BarChart,
@@ -83,6 +85,20 @@ export default function RoutingForms({
8385
const { hasPaidPlan } = useHasPaidPlan();
8486
const routerQuery = useRouterQuery();
8587
const hookForm = useFormContext<RoutingFormWithResponseCount>();
88+
const utils = trpc.useContext();
89+
const [parent] = useAutoAnimate<HTMLUListElement>();
90+
91+
const mutation = trpc.viewer.routingFormOrder.useMutation({
92+
onError: async (err) => {
93+
console.error(err.message);
94+
await utils.viewer.appRoutingForms.forms.cancel();
95+
await utils.viewer.appRoutingForms.invalidate();
96+
},
97+
onSettled: () => {
98+
utils.viewer.appRoutingForms.invalidate();
99+
},
100+
});
101+
86102
useEffect(() => {
87103
hookForm.reset({});
88104
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -128,6 +144,29 @@ export default function RoutingForms({
128144
},
129145
];
130146

147+
async function moveRoutingForm(index: number, increment: 1 | -1) {
148+
const types = forms?.map((type) => {
149+
return type.form;
150+
});
151+
152+
if (types?.length) {
153+
const newList = [...types];
154+
155+
const type = types[index];
156+
const tmp = types[index + increment];
157+
if (tmp) {
158+
newList[index] = tmp;
159+
newList[index + increment] = type;
160+
}
161+
162+
await utils.viewer.appRoutingForms.forms.cancel();
163+
164+
mutation.mutate({
165+
ids: newList?.map((type) => type.id),
166+
});
167+
}
168+
}
169+
131170
return (
132171
<LicenseRequired>
133172
<ShellMain
@@ -177,8 +216,8 @@ export default function RoutingForms({
177216
}
178217
SkeletonLoader={SkeletonLoaderTeamList}>
179218
<div className="bg-default mb-16 overflow-hidden">
180-
<List data-testid="routing-forms-list">
181-
{forms?.map(({ form, readOnly }) => {
219+
<List data-testid="routing-forms-list" ref={parent}>
220+
{forms?.map(({ form, readOnly }, index) => {
182221
if (!form) {
183222
return null;
184223
}
@@ -187,116 +226,129 @@ export default function RoutingForms({
187226
form.routes = form.routes || [];
188227
const fields = form.fields || [];
189228
const userRoutes = form.routes.filter((route) => !isFallbackRoute(route));
229+
const firstItem = forms[0].form;
230+
const lastItem = forms[forms.length - 1].form;
231+
190232
return (
191-
<ListLinkItem
192-
key={form.id}
193-
href={appUrl + "/form-edit/" + form.id}
194-
heading={form.name}
195-
disabled={readOnly}
196-
subHeading={description}
197-
className="space-x-2 rtl:space-x-reverse"
198-
actions={
199-
<>
200-
{form.team?.name && (
201-
<div className="border-r-2 border-neutral-300">
202-
<Badge className="ltr:mr-2 rtl:ml-2" variant="gray">
203-
{form.team.name}
204-
</Badge>
205-
</div>
206-
)}
207-
<FormAction
208-
disabled={readOnly}
209-
className="self-center"
210-
action="toggle"
211-
routingForm={form}
212-
/>
213-
<ButtonGroup combined>
214-
<Tooltip content={t("preview")}>
215-
<FormAction
216-
action="preview"
217-
routingForm={form}
218-
target="_blank"
219-
StartIcon={ExternalLink}
220-
color="secondary"
221-
variant="icon"
222-
/>
223-
</Tooltip>
224-
<FormAction
225-
routingForm={form}
226-
action="copyLink"
227-
color="secondary"
228-
variant="icon"
229-
StartIcon={LinkIcon}
230-
tooltip={t("copy_link_to_form")}
231-
/>
233+
<div
234+
className="group flex w-full max-w-full items-center justify-between overflow-hidden"
235+
key={form.id}>
236+
{!(firstItem && firstItem.id === form.id) && (
237+
<ArrowButton onClick={() => moveRoutingForm(index, -1)} arrowDirection="up" />
238+
)}
239+
240+
{!(lastItem && lastItem.id === form.id) && (
241+
<ArrowButton onClick={() => moveRoutingForm(index, 1)} arrowDirection="down" />
242+
)}
243+
<ListLinkItem
244+
href={appUrl + "/form-edit/" + form.id}
245+
heading={form.name}
246+
disabled={readOnly}
247+
subHeading={description}
248+
className="space-x-2 rtl:space-x-reverse"
249+
actions={
250+
<>
251+
{form.team?.name && (
252+
<div className="border-r-2 border-neutral-300">
253+
<Badge className="ltr:mr-2 rtl:ml-2" variant="gray">
254+
{form.team.name}
255+
</Badge>
256+
</div>
257+
)}
232258
<FormAction
259+
disabled={readOnly}
260+
className="self-center"
261+
action="toggle"
233262
routingForm={form}
234-
action="embed"
235-
color="secondary"
236-
variant="icon"
237-
StartIcon={Code}
238-
tooltip={t("embed")}
239263
/>
240-
<FormActionsDropdown disabled={readOnly}>
241-
<FormAction
242-
action="edit"
243-
routingForm={form}
244-
color="minimal"
245-
className="!flex"
246-
StartIcon={Edit}>
247-
{t("edit")}
248-
</FormAction>
264+
<ButtonGroup combined>
265+
<Tooltip content={t("preview")}>
266+
<FormAction
267+
action="preview"
268+
routingForm={form}
269+
target="_blank"
270+
StartIcon={ExternalLink}
271+
color="secondary"
272+
variant="icon"
273+
/>
274+
</Tooltip>
249275
<FormAction
250-
action="download"
251276
routingForm={form}
252-
color="minimal"
253-
StartIcon={Download}>
254-
{t("download_responses")}
255-
</FormAction>
277+
action="copyLink"
278+
color="secondary"
279+
variant="icon"
280+
StartIcon={LinkIcon}
281+
tooltip={t("copy_link_to_form")}
282+
/>
256283
<FormAction
257-
action="duplicate"
258284
routingForm={form}
259-
color="minimal"
260-
className="w-full"
261-
StartIcon={Copy}>
262-
{t("duplicate")}
263-
</FormAction>
264-
{typeformApp?.isInstalled ? (
285+
action="embed"
286+
color="secondary"
287+
variant="icon"
288+
StartIcon={Code}
289+
tooltip={t("embed")}
290+
/>
291+
<FormActionsDropdown disabled={readOnly}>
265292
<FormAction
266-
data-testid="copy-redirect-url"
293+
action="edit"
267294
routingForm={form}
268-
action="copyRedirectUrl"
269295
color="minimal"
270-
type="button"
271-
StartIcon={LinkIcon}>
272-
{t("Copy Typeform Redirect Url")}
296+
className="!flex"
297+
StartIcon={Edit}>
298+
{t("edit")}
273299
</FormAction>
274-
) : null}
275-
<FormAction
276-
action="_delete"
277-
routingForm={form}
278-
color="destructive"
279-
className="w-full"
280-
StartIcon={Trash}>
281-
{t("delete")}
282-
</FormAction>
283-
</FormActionsDropdown>
284-
</ButtonGroup>
285-
</>
286-
}>
287-
<div className="flex flex-wrap gap-1">
288-
<Badge variant="gray" startIcon={Menu}>
289-
{fields.length} {fields.length === 1 ? "field" : "fields"}
290-
</Badge>
291-
<Badge variant="gray" startIcon={GitMerge}>
292-
{userRoutes.length} {userRoutes.length === 1 ? "route" : "routes"}
293-
</Badge>
294-
<Badge variant="gray" startIcon={MessageCircle}>
295-
{form._count.responses}{" "}
296-
{form._count.responses === 1 ? "response" : "responses"}
297-
</Badge>
298-
</div>
299-
</ListLinkItem>
300+
<FormAction
301+
action="download"
302+
routingForm={form}
303+
color="minimal"
304+
StartIcon={Download}>
305+
{t("download_responses")}
306+
</FormAction>
307+
<FormAction
308+
action="duplicate"
309+
routingForm={form}
310+
color="minimal"
311+
className="w-full"
312+
StartIcon={Copy}>
313+
{t("duplicate")}
314+
</FormAction>
315+
{typeformApp?.isInstalled ? (
316+
<FormAction
317+
data-testid="copy-redirect-url"
318+
routingForm={form}
319+
action="copyRedirectUrl"
320+
color="minimal"
321+
type="button"
322+
StartIcon={LinkIcon}>
323+
{t("Copy Typeform Redirect Url")}
324+
</FormAction>
325+
) : null}
326+
<FormAction
327+
action="_delete"
328+
routingForm={form}
329+
color="destructive"
330+
className="w-full"
331+
StartIcon={Trash}>
332+
{t("delete")}
333+
</FormAction>
334+
</FormActionsDropdown>
335+
</ButtonGroup>
336+
</>
337+
}>
338+
<div className="flex flex-wrap gap-1">
339+
<Badge variant="gray" startIcon={Menu}>
340+
{fields.length} {fields.length === 1 ? "field" : "fields"}
341+
</Badge>
342+
<Badge variant="gray" startIcon={GitMerge}>
343+
{userRoutes.length} {userRoutes.length === 1 ? "route" : "routes"}
344+
</Badge>
345+
<Badge variant="gray" startIcon={MessageCircle}>
346+
{form._count.responses}{" "}
347+
{form._count.responses === 1 ? "response" : "responses"}
348+
</Badge>
349+
</div>
350+
</ListLinkItem>
351+
</div>
300352
);
301353
})}
302354
</List>

packages/app-store/routing-forms/playwright/tests/basic.e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ test.describe("Routing Forms", () => {
2121

2222
await page.waitForSelector('[data-testid="routing-forms-list"]');
2323
// Ensure that it's visible in forms list
24-
expect(await page.locator('[data-testid="routing-forms-list"] > li').count()).toBe(1);
24+
expect(await page.locator('[data-testid="routing-forms-list"] > div').count()).toBe(1);
2525

2626
await gotoRoutingLink({ page, formId });
2727
await expect(page.locator("text=Test Form Name")).toBeVisible();

packages/app-store/routing-forms/trpc/formMutation.handler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export const formMutationHandler = async ({ ctx, input }: FormMutationHandlerOpt
5959
fields: true,
6060
settings: true,
6161
teamId: true,
62+
position: true,
6263
},
6364
});
6465

packages/app-store/routing-forms/trpc/forms.handler.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,14 @@ export const formsHandler = async ({ ctx, input }: FormsHandlerOptions) => {
2626

2727
const forms = await prisma.app_RoutingForms_Form.findMany({
2828
where,
29-
orderBy: {
30-
createdAt: "desc",
31-
},
29+
orderBy: [
30+
{
31+
position: "desc",
32+
},
33+
{
34+
createdAt: "asc",
35+
},
36+
],
3237
include: {
3338
team: {
3439
include: {

packages/features/bookings/components/event-meta/Members.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { usePathname } from "next/navigation";
2+
13
import { getOrgFullDomain } from "@calcom/features/ee/organizations/lib/orgDomains";
24
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
35
import { SchedulingType } from "@calcom/prisma/enums";
@@ -26,6 +28,7 @@ type Avatar = {
2628
type AvatarWithRequiredImage = Avatar & { image: string };
2729

2830
export const EventMembers = ({ schedulingType, users, profile, entity }: EventMembersProps) => {
31+
const pathname = usePathname();
2932
const showMembers = schedulingType !== SchedulingType.ROUND_ROBIN;
3033
const shownUsers = showMembers ? users : [];
3134

@@ -57,7 +60,9 @@ export const EventMembers = ({ schedulingType, users, profile, entity }: EventMe
5760
title: `${profile.name || profile.username}`,
5861
image: "logo" in profile && profile.logo ? `${profile.logo}` : undefined,
5962
alt: profile.name || undefined,
60-
href: profile.username ? `${CAL_URL}/${profile.username}` : undefined,
63+
href: profile.username
64+
? `${CAL_URL}` + (pathname.indexOf("/team/") !== -1 ? "/team" : "") + `/${profile.username}`
65+
: undefined,
6166
});
6267

6368
const uniqueAvatars = avatars

0 commit comments

Comments
 (0)