From 2a5361472363006cdfbf038ccd7a35922f081d39 Mon Sep 17 00:00:00 2001 From: Arthur Cruz <42497300+arthur1041@users.noreply.github.com> Date: Sat, 14 May 2022 15:47:23 -0300 Subject: [PATCH] Fix/avoid multiple schedule deletions (#2602) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Prevents users from deleting the same schedule multiple times due to delay before the schedule disappears. It also applies the same fix to team disband. Schedule deletion: ![schedule_deletion_new_behaving](https://user-images.githubusercontent.com/42497300/165126805-b3090268-c1a6-418a-b06e-06bd8446da03.gif) Team disband: ![team_disband_new_behaving](https://user-images.githubusercontent.com/42497300/165127043-7e083e94-e4c9-4e88-90a2-47d31bdd92e6.gif) Fixes issue [#2569](https://github.com/calcom/cal.com/issues/2569) Bug fix (non-breaking change which fixes an issue) **apps/web/components/LightLoader.tsx** → this file was created in order to make a light color loading spinner available. It's necessary when we need to display a loading spinner above dark backgrounds. **apps/web/components/availability/ScheduleListItem.tsx** → this component was created in order to give a schedule list item its own state. * Removing a "setTimeout" that was only used for testing purposes * Adding a code review suggestion to my modifications * Changing loading style * Cleanup * Avoids using unnecessary state * Revert "Adding a code review suggestion to my modifications" This reverts commit b5e40062d71157ca1d9384fb1f5c30d50625809d. * Reverts some changes * Renames isLoading Co-authored-by: Alex van Andel Co-authored-by: Omar López --- .../availability/ScheduleListItem.tsx | 75 +++++++++++++++++++ .../dialog/ConfirmationDialogContent.tsx | 15 ++-- apps/web/components/team/TeamList.tsx | 6 +- apps/web/components/team/TeamListItem.tsx | 16 ++-- apps/web/pages/availability/index.tsx | 62 ++------------- apps/web/public/static/locales/en/common.json | 1 + .../public/static/locales/pt-BR/common.json | 1 + apps/web/public/static/locales/pt/common.json | 1 + 8 files changed, 110 insertions(+), 67 deletions(-) create mode 100644 apps/web/components/availability/ScheduleListItem.tsx diff --git a/apps/web/components/availability/ScheduleListItem.tsx b/apps/web/components/availability/ScheduleListItem.tsx new file mode 100644 index 00000000..f085c0de --- /dev/null +++ b/apps/web/components/availability/ScheduleListItem.tsx @@ -0,0 +1,75 @@ +import { DotsHorizontalIcon, TrashIcon } from "@heroicons/react/solid"; +import Link from "next/link"; +import { Fragment } from "react"; + +import { availabilityAsString } from "@calcom/lib/availability"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { Availability } from "@calcom/prisma/client"; +import { Button } from "@calcom/ui"; +import Dropdown, { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@calcom/ui/Dropdown"; + +import { inferQueryOutput } from "@lib/trpc"; + +export function ScheduleListItem({ + schedule, + deleteFunction, + isDeleting = false, +}: { + schedule: inferQueryOutput<"viewer.availability.list">["schedules"][number]; + deleteFunction: Function; + isDeleting: boolean; +}) { + const { t, i18n } = useLocale(); + + return ( +
  • +
    +
    + + +
    + {schedule.name} + {schedule.isDefault && ( + + {t("default")} + + )} +
    +

    + {schedule.availability.map((availability: Availability) => ( + + {availabilityAsString(availability, i18n.language)} +
    +
    + ))} +

    +
    + +
    + + + + + + + + + + +
    +
  • + ); +} diff --git a/apps/web/components/dialog/ConfirmationDialogContent.tsx b/apps/web/components/dialog/ConfirmationDialogContent.tsx index 9487bf88..6337b41d 100644 --- a/apps/web/components/dialog/ConfirmationDialogContent.tsx +++ b/apps/web/components/dialog/ConfirmationDialogContent.tsx @@ -3,15 +3,15 @@ import { CheckIcon } from "@heroicons/react/solid"; import * as DialogPrimitive from "@radix-ui/react-dialog"; import React, { PropsWithChildren, ReactNode } from "react"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button } from "@calcom/ui/Button"; import { DialogClose, DialogContent } from "@calcom/ui/Dialog"; -import { useLocale } from "@lib/hooks/useLocale"; - export type ConfirmationDialogContentProps = { confirmBtn?: ReactNode; confirmBtnText?: string; cancelBtnText?: string; + isLoading?: boolean; onConfirm?: (event: React.MouseEvent) => void; title: string; variety?: "danger" | "warning" | "success"; @@ -25,6 +25,7 @@ export default function ConfirmationDialogContent(props: PropsWithChildren
    - - {confirmBtn || } + + {confirmBtn || ( + + )} - +
    diff --git a/apps/web/components/team/TeamList.tsx b/apps/web/components/team/TeamList.tsx index 8c7bc027..f8177700 100644 --- a/apps/web/components/team/TeamList.tsx +++ b/apps/web/components/team/TeamList.tsx @@ -1,6 +1,6 @@ import showToast from "@calcom/lib/notification"; -import { trpc, inferQueryOutput } from "@lib/trpc"; +import { inferQueryOutput, trpc } from "@lib/trpc"; import TeamListItem from "./TeamListItem"; @@ -39,7 +39,9 @@ export default function TeamList(props: Props) { selectAction(action, team?.id as number)}> + onActionSelect={(action: string) => selectAction(action, team?.id as number)} + isLoading={deleteTeamMutation.isLoading} + /> ))} diff --git a/apps/web/components/team/TeamListItem.tsx b/apps/web/components/team/TeamListItem.tsx index 776a9139..ce05aeb6 100644 --- a/apps/web/components/team/TeamListItem.tsx +++ b/apps/web/components/team/TeamListItem.tsx @@ -1,10 +1,10 @@ import { LogoutIcon } from "@heroicons/react/outline"; import { - ExternalLinkIcon, - TrashIcon, - LinkIcon, DotsHorizontalIcon, + ExternalLinkIcon, + LinkIcon, PencilIcon, + TrashIcon, } from "@heroicons/react/solid"; import { MembershipRole } from "@prisma/client"; import Link from "next/link"; @@ -16,14 +16,14 @@ import { Dialog, DialogTrigger } from "@calcom/ui/Dialog"; import Dropdown, { DropdownMenuContent, DropdownMenuItem, - DropdownMenuTrigger, DropdownMenuSeparator, + DropdownMenuTrigger, } from "@calcom/ui/Dropdown"; import { Tooltip } from "@calcom/ui/Tooltip"; import classNames from "@lib/classNames"; import { getPlaceholderAvatar } from "@lib/getPlaceholderAvatar"; -import { trpc, inferQueryOutput } from "@lib/trpc"; +import { inferQueryOutput, trpc } from "@lib/trpc"; import ConfirmationDialogContent from "@components/dialog/ConfirmationDialogContent"; import Avatar from "@components/ui/Avatar"; @@ -34,6 +34,7 @@ interface Props { team: inferQueryOutput<"viewer.teams.list">[number]; key: number; onActionSelect: (text: string) => void; + isLoading?: boolean; } export default function TeamListItem(props: Props) { @@ -175,7 +176,10 @@ export default function TeamListItem(props: Props) { variety="danger" title={t("disband_team")} confirmBtnText={t("confirm_disband_team")} - onConfirm={() => props.onActionSelect("disband")}> + isLoading={props.isLoading} + onConfirm={() => { + props.onActionSelect("disband"); + }}> {t("disband_team_confirmation_message")} diff --git a/apps/web/pages/availability/index.tsx b/apps/web/pages/availability/index.tsx index 6de76507..ef216396 100644 --- a/apps/web/pages/availability/index.tsx +++ b/apps/web/pages/availability/index.tsx @@ -1,13 +1,7 @@ import { ClockIcon } from "@heroicons/react/outline"; -import { DotsHorizontalIcon, TrashIcon } from "@heroicons/react/solid"; -import { Availability } from "@prisma/client"; -import Link from "next/link"; -import { availabilityAsString } from "@calcom/lib/availability"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import showToast from "@calcom/lib/notification"; -import { Button } from "@calcom/ui"; -import Dropdown, { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@calcom/ui/Dropdown"; import { withQuery } from "@lib/QueryCell"; import { HttpError } from "@lib/core/http/error"; @@ -16,10 +10,11 @@ import { inferQueryOutput, trpc } from "@lib/trpc"; import EmptyScreen from "@components/EmptyScreen"; import Shell from "@components/Shell"; import { NewScheduleButton } from "@components/availability/NewScheduleButton"; +import { ScheduleListItem } from "@components/availability/ScheduleListItem"; import SkeletonLoader from "@components/availability/SkeletonLoader"; export function AvailabilityList({ schedules }: inferQueryOutput<"viewer.availability.list">) { - const { t, i18n } = useLocale(); + const { t } = useLocale(); const utils = trpc.useContext(); const deleteMutation = trpc.useMutation("viewer.availability.schedule.delete", { onSuccess: async () => { @@ -45,53 +40,12 @@ export function AvailabilityList({ schedules }: inferQueryOutput<"viewer.availab
    diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index db1a3ded..97556067 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -348,6 +348,7 @@ "receive_cal_event_meeting_data": "Receive Cal meeting data at a specified URL, in real-time, when this event is scheduled or cancelled.", "responsive_fullscreen_iframe": "Responsive full screen iframe", "loading": "Loading...", + "deleting": "Deleting...", "standard_iframe": "Standard iframe", "iframe_embed": "iframe Embed", "embed_calcom": "The easiest way to embed Cal.com on your website.", diff --git a/apps/web/public/static/locales/pt-BR/common.json b/apps/web/public/static/locales/pt-BR/common.json index 539276ac..3ff9230c 100644 --- a/apps/web/public/static/locales/pt-BR/common.json +++ b/apps/web/public/static/locales/pt-BR/common.json @@ -292,6 +292,7 @@ "receive_cal_meeting_data": "Receba dados da reunião Cal em uma, URL especificada, em tempo real, quando um evento for agendado ou cancelado.", "responsive_fullscreen_iframe": "Iframe responsivo de tela inteira", "loading": "Carregando...", + "deleting": "Apagando...", "standard_iframe": "Iframe padrão", "iframe_embed": "Incorporar iframe", "embed_calcom": "A maneira mais fácil de incorporar o Cal.com no seu site.", diff --git a/apps/web/public/static/locales/pt/common.json b/apps/web/public/static/locales/pt/common.json index 076789f8..1978b9b0 100644 --- a/apps/web/public/static/locales/pt/common.json +++ b/apps/web/public/static/locales/pt/common.json @@ -329,6 +329,7 @@ "receive_cal_event_meeting_data": "Receba dados da reunião Cal num URL especificado, em tempo real, assim que o evento for agendado ou cancelado.", "responsive_fullscreen_iframe": "Iframe responsivo de ecrã inteiro", "loading": "A carregar...", + "deleting": "A remover...", "standard_iframe": "Iframe padrão", "iframe_embed": "Incorporar iframe", "embed_calcom": "A maneira mais fácil de incorporar o Cal.com no seu site.",