Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ interface IUserToValue {
}

export const mapUserToValue = (
{ id, name, username, avatar, email, defaultScheduleId }: IUserToValue,
{ id, name, username, avatar, email, defaultScheduleId, isOptional }: IUserToValue & { isOptional?: boolean },
pendingString: string
) => ({
value: `${id || ""}`,
label: `${name || email || ""}${!username ? ` (${pendingString})` : ""}`,
avatar,
email,
defaultScheduleId,
isOptional: isOptional || false,
});

const sortByLabel = (a: ReturnType<typeof mapUserToValue>, b: ReturnType<typeof mapUserToValue>) => {
Expand Down
2 changes: 2 additions & 0 deletions apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -4656,5 +4656,7 @@
"paypal_step_7": "You should be all set up after this.",
"dashboard": "dashboard",
"paypal_webhook_reminder": "Our integration creates a specific webhook on your PayPal account that we use to report back transactions to our system. If you delete this webhook, we will not be able to report back and you should uninstall and install the app again for this to work properly. Uninstalling the app won't delete your current event type price/currency configuration but you will not be able to receive bookings.",
"make_optional": "Make optional",
"make_required": "Make required",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const getAggregatedAvailability = (
userAvailability: {
dateRanges: DateRange[];
oooExcludedDateRanges: DateRange[];
user?: { isFixed?: boolean; groupId?: string | null };
user?: { isFixed?: boolean; groupId?: string | null; isOptional?: boolean };
}[],
schedulingType: SchedulingType | null
): DateRange[] => {
Expand All @@ -36,14 +36,14 @@ export const getAggregatedAvailability = (
userAvailability.length > 1;

const fixedHosts = userAvailability.filter(
({ user }) => !schedulingType || schedulingType === SchedulingType.COLLECTIVE || user?.isFixed
({ user }) => (!schedulingType || schedulingType === SchedulingType.COLLECTIVE || user?.isFixed) && !user?.isOptional
);

const fixedDateRanges = mergeOverlappingDateRanges(
intersect(fixedHosts.map((s) => (!isTeamEvent ? s.dateRanges : s.oooExcludedDateRanges)))
);
const dateRangesToIntersect = fixedDateRanges.length ? [fixedDateRanges] : [];
const roundRobinHosts = userAvailability.filter(({ user }) => user?.isFixed !== true);
const roundRobinHosts = userAvailability.filter(({ user }) => user?.isFixed !== true && !user?.isOptional);
if (roundRobinHosts.length) {
// Group round robin hosts by their groupId
const hostsByGroup = roundRobinHosts.reduce(
Expand Down
18 changes: 18 additions & 0 deletions packages/features/eventtypes/components/CheckedTeamSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type CheckedSelectOption = {
priority?: number;
weight?: number;
isFixed?: boolean;
isOptional?: boolean;
disabled?: boolean;
defaultScheduleId?: number | null;
groupId: string | null;
Expand Down Expand Up @@ -136,6 +137,23 @@ export const CheckedTeamSelect = ({
<div className="ml-auto flex items-center">
{option && !option.isFixed ? (
<>
<Tooltip content={t(option.isOptional ? "make_required" : "make_optional")}>
<Button
color="minimal"
onClick={() =>
props.onChange(
value.map((item) =>
item.value === option.value ? { ...item, isOptional: !item.isOptional } : item
)
)
}
className={classNames(
"mr-6 h-2 p-0 text-sm hover:bg-transparent",
option.isOptional ? "text-orange-500" : "text-subtle"
)}>
{option.isOptional ? t("optional") : t("required")}
</Button>
</Tooltip>
<Tooltip content={t("change_priority")}>
<Button
color="minimal"
Expand Down
2 changes: 2 additions & 0 deletions packages/features/eventtypes/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type HostLocation = {

export type Host = {
isFixed: boolean;
isOptional: boolean;
userId: number;
priority: number;
weight: number;
Expand Down Expand Up @@ -269,6 +270,7 @@ export type HostInput = {
userId: number;
profileId?: number | null;
isFixed?: boolean;
isOptional?: boolean;
priority?: number | null;
weight?: number | null;
scheduleId?: number | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@ export class EventTypeRepository implements IEventTypesRepository {
},
hosts: {
select: {
isOptional: true,
user: {
select: {
email: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Host" ADD COLUMN "isOptional" BOOLEAN NOT NULL DEFAULT false;
1 change: 1 addition & 0 deletions packages/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ model Host {
isFixed Boolean @default(false)
priority Int?
weight Int?
isOptional Boolean @default(false)
// weightAdjustment is deprecated. We not calculate the calibratino value on the spot. Plan to drop this column.
weightAdjustment Int?
schedule Schedule? @relation(fields: [scheduleId], references: [id])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
const hostData: {
userId: number;
isFixed: boolean;
isOptional: boolean;
priority: number;
weight: number;
groupId: string | null | undefined;
Expand All @@ -526,6 +527,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
} = {
userId: host.userId,
isFixed: data.schedulingType === SchedulingType.COLLECTIVE || host.isFixed || false,
isOptional: host.isOptional || false,
priority: host.priority ?? 2,
weight: host.weight ?? 100,
groupId: host.groupId,
Expand All @@ -547,6 +549,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
update: existingHosts.map((host) => {
const updateData: {
isFixed: boolean | undefined;
isOptional: boolean | undefined;
priority: number;
weight: number;
scheduleId: number | null | undefined;
Expand All @@ -571,6 +574,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
};
} = {
isFixed: data.schedulingType === SchedulingType.COLLECTIVE || host.isFixed,
isOptional: host.isOptional,
priority: host.priority ?? 2,
weight: host.weight ?? 100,
scheduleId: host.scheduleId === undefined ? undefined : host.scheduleId,
Expand Down
1 change: 1 addition & 0 deletions packages/trpc/server/routers/viewer/eventTypes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const hostSchema: z.ZodType<HostInput> = z.object({
userId: z.number(),
profileId: z.number().or(z.null()).optional(),
isFixed: z.boolean().optional(),
isOptional: z.boolean().optional(),
priority: z.number().min(0).max(4).optional().nullable(),
weight: z.number().min(0).optional().nullable(),
scheduleId: z.number().optional().nullable(),
Expand Down
3 changes: 2 additions & 1 deletion packages/trpc/server/routers/viewer/slots/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,11 +741,12 @@ export class AvailableSlotsService {
}: {
hosts: {
isFixed?: boolean;
isOptional?: boolean;
groupId?: string | null;
user: GetAvailabilityUserWithDelegationCredentials;
}[];
}) {
return hosts.map(({ isFixed, groupId, user }) => ({ isFixed, groupId, ...user }));
return hosts.map(({ isFixed, isOptional, groupId, user }) => ({ isFixed, isOptional, groupId, ...user }));
}

private getUsersWithCredentials = withReporting(
Expand Down
Loading