fix: extract trpc and react-awesome-query-builder from atoms (#17801)

* wip

* fix: externalize react-awesome-query-builder

* fix: move useSession to webWrapper

* fixup! Merge branch 'main' into fix-platform-event-types-segment

* fixup! fixup! Merge branch 'main' into fix-platform-event-types-segment

* fixup! fixup! fixup! Merge branch 'main' into fix-platform-event-types-segment

* fixup! fixup! fixup! fixup! Merge branch 'main' into fix-platform-event-types-segment
This commit is contained in:
Morgan
2024-11-23 12:29:16 +00:00
committed by GitHub
parent 9bb66035c8
commit c2a3d8b8df
16 changed files with 97 additions and 37 deletions
+2 -1
View File
@@ -30,7 +30,8 @@
"**/*.tsx",
".next/types/**/*.ts",
"../../packages/features/bookings/lib/getBookingInfo.ts",
"../../packages/features/bookings/lib/getUserBooking.ts"
"../../packages/features/bookings/lib/getUserBooking.ts",
"../../packages/features/Segment.tsx"
],
"exclude": ["node_modules"]
}
@@ -2,12 +2,11 @@ import { render, screen, waitFor } from "@testing-library/react";
import { describe, expect, it, vi, beforeEach } from "vitest";
import type { Mock } from "vitest";
import { Segment } from "@calcom/features/Segment";
import type { AttributesQueryValue } from "@calcom/lib/raqb/types";
import { AttributeType } from "@calcom/prisma/enums";
import { trpc, type RouterOutputs } from "@calcom/trpc";
import { Segment } from "../Segment";
type Attributes = RouterOutputs["viewer"]["appRoutingForms"]["getAttributesForTeam"];
type MatchingTeamMembersData = RouterOutputs["viewer"]["attributes"]["findTeamMembersMatchingAttributeLogic"];
const mockGetAttributesForTeam = (
@@ -1,3 +1,5 @@
"use client";
import { useCallback, useState } from "react";
import { Query, Builder, Utils as QbUtils } from "react-awesome-query-builder";
import type { ImmutableTree, BuilderProps } from "react-awesome-query-builder";
@@ -1,15 +1,19 @@
import type { ComponentProps, Dispatch, SetStateAction } from "react";
import { useMemo, type ComponentProps, type Dispatch, type SetStateAction } from "react";
import { useFormContext } from "react-hook-form";
import { Controller } from "react-hook-form";
import type { Options } from "react-select";
import {
useIsPlatform,
AddMembersWithSwitchWebWrapper,
AddMembersWithSwitchPlatformWrapper,
} from "@calcom/atoms/monorepo";
import { Segment } from "@calcom/features/Segment";
import type { FormValues, Host, TeamMember } from "@calcom/features/eventtypes/lib/types";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { AttributesQueryValue } from "@calcom/lib/raqb/types";
import { trpc } from "@calcom/trpc";
import { Label, SettingsToggle } from "@calcom/ui";
import { Segment } from "../../../../apps/web/components/Segment";
import AssignAllTeamMembers from "./AssignAllTeamMembers";
import CheckedTeamSelect from "./CheckedTeamSelect";
import type { CheckedSelectOption } from "./CheckedTeamSelect";
@@ -122,7 +126,7 @@ function MembersSegmentWithToggle({
const onQueryValueChange = ({ queryValue }: { queryValue: AttributesQueryValue }) => {
setRrSegmentQueryValue(queryValue);
};
const isPlatform = useIsPlatform();
return (
<Controller<FormValues>
name="assignRRMembersUsingSegment"
@@ -136,19 +140,21 @@ function MembersSegmentWithToggle({
onCheckedChange={(active) => {
setAssignRRMembersUsingSegment(active);
}}>
<Segment
teamId={teamId}
queryValue={rrSegmentQueryValue}
onQueryValueChange={onQueryValueChange}
className={className}
/>
{!isPlatform && (
<Segment
teamId={teamId}
queryValue={rrSegmentQueryValue}
onQueryValueChange={onQueryValueChange}
className={className}
/>
)}
</SettingsToggle>
)}
/>
);
}
type AddMembersWithSwitchProps = {
export type AddMembersWithSwitchProps = {
teamMembers: TeamMember[];
value: Host[];
onChange: (hosts: Host[]) => void;
@@ -213,7 +219,7 @@ function useSegmentState() {
};
}
function AddMembersWithSwitch({
export function AddMembersWithSwitch({
teamMembers,
value,
onChange,
@@ -243,11 +249,6 @@ function AddMembersWithSwitch({
isAssigningAllTeamMembersApplicable: automaticAddAllEnabled,
isSegmentApplicable,
});
const utils = trpc.useUtils();
utils.viewer.appRoutingForms.getAttributesForTeam.prefetch({
teamId,
});
const onAssignAllTeamMembersInactive = () => {
setAssignRRMembersUsingSegment(false);
@@ -318,10 +319,15 @@ const AddMembersWithSwitchWrapper = ({
}: AddMembersWithSwitchProps & {
containerClassName?: string;
}) => {
const isPlatform = useIsPlatform();
const AddMembersWithSwitchWrapped = useMemo(
() => (isPlatform ? AddMembersWithSwitchPlatformWrapper : AddMembersWithSwitchWebWrapper),
[isPlatform]
);
return (
<div className="rounded-md ">
<div className={`flex flex-col rounded-md pb-2 pt-6 ${containerClassName}`}>
<AddMembersWithSwitch {...props} />
<AddMembersWithSwitchWrapped {...props} />
</div>
</div>
);
@@ -1,3 +1,5 @@
"use client";
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { useState } from "react";
import type { Props } from "react-select";
@@ -4,7 +4,8 @@ import { FormProvider, useForm } from "react-hook-form";
import { describe, expect, it, vi } from "vitest";
import type { Host, TeamMember } from "../../lib/types";
import AddMembersWithSwitch from "../AddMembersWithSwitch";
import type { AddMembersWithSwitchProps } from "../AddMembersWithSwitch";
import { AddMembersWithSwitch } from "../AddMembersWithSwitch";
// Mock matchMedia
vi.mock("@formkit/auto-animate/react", () => ({
@@ -12,7 +13,7 @@ vi.mock("@formkit/auto-animate/react", () => ({
}));
// Mock Segment component
vi.mock("@calcom/web/components/Segment", () => ({
vi.mock("@calcom/features/Segment", () => ({
Segment: vi.fn().mockImplementation(({ onQueryValueChange }) => (
<div data-testid="mock-segment">
<button onClick={() => onQueryValueChange({ queryValue: { id: "test" } })}>Update Query</button>
@@ -60,7 +61,7 @@ const renderComponent = ({
hosts: [],
},
}: {
componentProps: Parameters<typeof AddMembersWithSwitch>[0];
componentProps: AddMembersWithSwitchProps;
formDefaultValues?: Record<string, unknown>;
}) => {
const Wrapper = ({ children }: { children: React.ReactNode }) => {
@@ -26,6 +26,7 @@ export type EventTeamAssignmentTabBaseProps = Pick<
"teamMembers" | "team" | "eventType"
> & {
orgId: number | null;
isSegmentApplicable: boolean;
};
export const mapMemberToChildrenOption = (
@@ -227,6 +228,7 @@ const RoundRobinHosts = ({
assignAllTeamMembers,
setAssignAllTeamMembers,
teamId,
isSegmentApplicable,
}: {
orgId: number | null;
value: Host[];
@@ -235,6 +237,7 @@ const RoundRobinHosts = ({
assignAllTeamMembers: boolean;
setAssignAllTeamMembers: Dispatch<SetStateAction<boolean>>;
teamId: number;
isSegmentApplicable: boolean;
}) => {
const { t } = useLocale();
@@ -278,7 +281,7 @@ const RoundRobinHosts = ({
onChange={onChange}
assignAllTeamMembers={assignAllTeamMembers}
setAssignAllTeamMembers={setAssignAllTeamMembers}
isSegmentApplicable={!!orgId}
isSegmentApplicable={isSegmentApplicable}
automaticAddAllEnabled={true}
isRRWeightsEnabled={isRRWeightsEnabled}
isFixed={false}
@@ -347,12 +350,14 @@ const Hosts = ({
teamMembers,
assignAllTeamMembers,
setAssignAllTeamMembers,
isSegmentApplicable,
}: {
orgId: number | null;
teamId: number;
teamMembers: TeamMember[];
assignAllTeamMembers: boolean;
setAssignAllTeamMembers: Dispatch<SetStateAction<boolean>>;
isSegmentApplicable: boolean;
}) => {
const {
control,
@@ -439,6 +444,7 @@ const Hosts = ({
}}
assignAllTeamMembers={assignAllTeamMembers}
setAssignAllTeamMembers={setAssignAllTeamMembers}
isSegmentApplicable={isSegmentApplicable}
/>
</>
),
@@ -455,6 +461,7 @@ export const EventTeamAssignmentTab = ({
teamMembers,
eventType,
orgId,
isSegmentApplicable,
}: EventTeamAssignmentTabBaseProps) => {
const { t } = useLocale();
@@ -572,6 +579,7 @@ export const EventTeamAssignmentTab = ({
</div>
<Hosts
orgId={orgId}
isSegmentApplicable={isSegmentApplicable}
teamId={team.id}
assignAllTeamMembers={assignAllTeamMembers}
setAssignAllTeamMembers={setAssignAllTeamMembers}
@@ -1,4 +1,3 @@
import { useSession } from "next-auth/react";
import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form";
import type { UseFormGetValues, UseFormSetValue, Control, FormState } from "react-hook-form";
@@ -19,12 +18,13 @@ export type EventSetupTabProps = Pick<
EventTypeSetupProps,
"eventType" | "locationOptions" | "team" | "teamMembers" | "destinationCalendar"
>;
export const EventSetupTab = (props: EventSetupTabProps & { urlPrefix: string; hasOrgBranding: boolean }) => {
export const EventSetupTab = (
props: EventSetupTabProps & { urlPrefix: string; hasOrgBranding: boolean; orgId?: number }
) => {
const { t } = useLocale();
const session = useSession();
const isPlatform = useIsPlatform();
const formMethods = useFormContext<FormValues>();
const { eventType, team, urlPrefix, hasOrgBranding } = props;
const { eventType, team, urlPrefix, hasOrgBranding, orgId } = props;
const [multipleDuration, setMultipleDuration] = useState(
formMethods.getValues("metadata")?.multipleDuration
);
@@ -105,8 +105,8 @@ export const EventSetupTab = (props: EventSetupTabProps & { urlPrefix: string; h
onCheckedChange={(value) => {
formMethods.setValue("autoTranslateDescriptionEnabled", value, { shouldDirty: true });
}}
disabled={!session.data?.user.org?.id}
tooltip={!session.data?.user.org?.id ? t("orgs_upgrade_to_enable_feature") : undefined}
disabled={!orgId}
tooltip={!orgId ? t("orgs_upgrade_to_enable_feature") : undefined}
/>
</div>
<TextField
@@ -0,0 +1,6 @@
import type { AddMembersWithSwitchProps } from "@calcom/features/eventtypes/components/AddMembersWithSwitch";
import { AddMembersWithSwitch } from "@calcom/features/eventtypes/components/AddMembersWithSwitch";
export const AddMembersWithSwitchPlatformWrapper = ({ ...props }: AddMembersWithSwitchProps) => {
return <AddMembersWithSwitch {...props} />;
};
@@ -0,0 +1,12 @@
import type { AddMembersWithSwitchProps } from "@calcom/features/eventtypes/components/AddMembersWithSwitch";
import { AddMembersWithSwitch } from "@calcom/features/eventtypes/components/AddMembersWithSwitch";
import { trpc } from "@calcom/trpc";
export const AddMembersWithSwitchWebWrapper = ({ ...props }: AddMembersWithSwitchProps) => {
const utils = trpc.useUtils();
utils.viewer.appRoutingForms.getAttributesForTeam.prefetch({
teamId: props.teamId,
});
return <AddMembersWithSwitch {...props} />;
};
@@ -1,3 +1,5 @@
import { useSession } from "next-auth/react";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import type { EventSetupTabProps } from "@calcom/features/eventtypes/components/tabs/setup/EventSetupTab";
import { EventSetupTab } from "@calcom/features/eventtypes/components/tabs/setup/EventSetupTab";
@@ -5,10 +7,18 @@ import { WEBSITE_URL } from "@calcom/lib/constants";
const EventSetupTabWebWrapper = (props: EventSetupTabProps) => {
const orgBranding = useOrgBranding();
const session = useSession();
const urlPrefix = orgBranding
? orgBranding?.fullDomain.replace(/^(https?:|)\/\//, "")
: `${WEBSITE_URL?.replace(/^(https?:|)\/\//, "")}`;
return <EventSetupTab urlPrefix={urlPrefix} hasOrgBranding={!!orgBranding} {...props} />;
return (
<EventSetupTab
urlPrefix={urlPrefix}
hasOrgBranding={!!orgBranding}
orgId={session.data?.user.org?.id}
{...props}
/>
);
};
export default EventSetupTabWebWrapper;
@@ -3,8 +3,11 @@ import {
type EventTeamAssignmentTabBaseProps,
} from "@calcom/features/eventtypes/components/tabs/assignment/EventTeamAssignmentTab";
const EventTeamAssignmentTabPlatformWrapper = (props: EventTeamAssignmentTabBaseProps) => {
return <EventTeamAssignmentTab {...props} />;
const EventTeamAssignmentTabPlatformWrapper = (
props: Omit<EventTeamAssignmentTabBaseProps, "isSegmentApplicable">
) => {
// todo: implement attributes for platform orgs for segment
return <EventTeamAssignmentTab {...props} isSegmentApplicable={false} />;
};
export default EventTeamAssignmentTabPlatformWrapper;
@@ -3,8 +3,11 @@ import {
type EventTeamAssignmentTabBaseProps,
} from "@calcom/features/eventtypes/components/tabs/assignment/EventTeamAssignmentTab";
const EventTeamAssignmentTabWebWrapper = (props: EventTeamAssignmentTabBaseProps) => {
return <EventTeamAssignmentTab {...props} />;
const EventTeamAssignmentTabWebWrapper = (
props: Omit<EventTeamAssignmentTabBaseProps, "isSegmentApplicable">
) => {
const isSegmentApplicable = !!props.orgId;
return <EventTeamAssignmentTab {...props} isSegmentApplicable={isSegmentApplicable} />;
};
export default EventTeamAssignmentTabWebWrapper;
+2
View File
@@ -12,3 +12,5 @@ export * from "./availability";
export { EventTypeWebWrapper as EventType } from "./event-types/wrappers/EventTypeWebWrapper";
export type { UpdateScheduleInput_2024_06_11 as UpdateScheduleBody } from "@calcom/platform-types";
export { Shell } from "./src/components/ui/shell";
export { AddMembersWithSwitchWebWrapper } from "./add-members-switch/AddMembersWithSwitchWebWrapper";
export { AddMembersWithSwitchPlatformWrapper } from "./add-members-switch/AddMembersWithSwitchPlatformWrapper";
+5
View File
@@ -67,5 +67,10 @@
"tailwind-merge": "^1.13.2",
"tailwindcss": "^3.3.3",
"tailwindcss-animate": "^1.0.6"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-awesome-query-builder": "^5.1.2",
"react-dom": "^18.0.0 || ^19.0.0"
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ export default defineConfig(({ mode }) => {
fileName: "cal-atoms",
},
rollupOptions: {
external: ["react", "fs", "path", "os", "react-dom"],
external: ["react", "fs", "path", "os", "react-dom", "react-awesome-query-builder"],
output: {
globals: {
react: "React",