Adds skeleton loader to workflows (#4402)
* fix event types skeleton loader * fix margin in event types * fix skeleton loader in bookings * add skeleton loader for workflow list * add skeleton loader for editing page * fix border radius of skeleton loader * fix mobile view workflow list * add mobile view for skeleton list * make multi select full with in mobile view * mobile view for edit skeleton loader Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
CarinaWolli
kodiakhq[bot]
parent
1deca816bd
commit
50f63ef000
@@ -4,7 +4,7 @@ import { SkeletonText } from "@calcom/ui";
|
||||
|
||||
function SkeletonLoader() {
|
||||
return (
|
||||
<ul className="animate-pulse divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
|
||||
<ul className="animate-pulse divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
|
||||
@@ -4,7 +4,7 @@ import { SkeletonText } from "@calcom/ui";
|
||||
|
||||
function SkeletonLoader() {
|
||||
return (
|
||||
<ul className="mx-6 mt-6 animate-pulse divide-y divide-neutral-200 border border-gray-200 bg-white sm:overflow-hidden">
|
||||
<ul className="animate-pulse divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:overflow-hidden">
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
@@ -16,7 +16,7 @@ export default SkeletonLoader;
|
||||
|
||||
function SkeletonItem() {
|
||||
return (
|
||||
<li className="group flex w-full items-center justify-between px-2 py-4 sm:px-6">
|
||||
<li className="group flex w-full items-center justify-between px-4 py-4 sm:px-6">
|
||||
<div className="flex-grow truncate text-sm">
|
||||
<div className="flex">
|
||||
<div className="flex flex-col space-y-2">
|
||||
|
||||
@@ -5,13 +5,13 @@ function SkeletonLoader() {
|
||||
return (
|
||||
<SkeletonContainer>
|
||||
<div className="mb-4 flex items-center">
|
||||
<SkeletonAvatar className="h-8 w-8" />
|
||||
<SkeletonAvatar width="8" height="8" />
|
||||
<div className="space-y-1">
|
||||
<SkeletonText className="h-4 w-16" />
|
||||
<SkeletonText className="h-4 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<ul className="divide-y divide-neutral-200 border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
|
||||
<ul className="divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
@@ -42,19 +42,6 @@ function SkeletonItem() {
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 hidden flex-shrink-0 sm:mt-0 sm:ml-5 sm:flex">
|
||||
<div className="flex justify-between rtl:space-x-reverse">
|
||||
<div className="cursor-pointer appearance-none rounded-sm border border-transparent p-2 text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
|
||||
<Icon.FiExternalLink className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="cursor-pointer appearance-none rounded-sm border border-transparent p-2 text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
|
||||
<Icon.FiLink className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="cursor-pointer appearance-none rounded-sm border border-transparent p-2 text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
|
||||
<Icon.FiMoreHorizontal className="h-5 w-5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { SkeletonAvatar, SkeletonContainer, SkeletonText } from "@calcom/ui";
|
||||
import { Icon } from "@calcom/ui/Icon";
|
||||
|
||||
function SkeletonLoader() {
|
||||
return (
|
||||
<SkeletonContainer>
|
||||
<div className="mt-20 ml-2 md:flex">
|
||||
<div className="mr-6 md:flex-none">
|
||||
<SkeletonText className="h-4 w-28" />
|
||||
<SkeletonText className="mt-2 mb-6 h-8 w-full md:w-64" />
|
||||
<SkeletonText className="h-4 w-28" />
|
||||
<SkeletonText className="mt-2 h-8 w-full md:w-64" />
|
||||
<SkeletonText className="mt-8 hidden h-0.5 w-full md:block" />
|
||||
<SkeletonText className="mt-8 mb-6 h-8 w-40" />
|
||||
</div>
|
||||
<div className="hidden flex-grow md:flex">
|
||||
<SkeletonText className="h-64 w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</SkeletonContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default SkeletonLoader;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { SkeletonText } from "@calcom/ui/v2";
|
||||
|
||||
function SkeletonLoader() {
|
||||
return (
|
||||
<ul className="mt-5 animate-pulse divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:mt-20 sm:overflow-hidden">
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
export default SkeletonLoader;
|
||||
|
||||
function SkeletonItem() {
|
||||
return (
|
||||
<li className="group flex w-full items-center justify-between px-4 py-4 sm:px-6">
|
||||
<div className="flex-grow truncate text-sm">
|
||||
<div className="flex">
|
||||
<div className="flex flex-col space-y-2">
|
||||
<SkeletonText className="h-4 w-16 sm:w-24" />
|
||||
<div className="flex">
|
||||
<Icon.FiBell className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200" />
|
||||
<SkeletonText className="mr-2 h-4 w-16 sm:w-28" />
|
||||
<Icon.FiLink className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200" />
|
||||
<SkeletonText className="h-4 w-28 sm:w-36" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-0 flex flex-shrink-0 sm:ml-5">
|
||||
<div className="flex justify-between space-x-2 rtl:space-x-reverse">
|
||||
<SkeletonText className="h-8 w-8 sm:w-16" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
@@ -93,6 +93,7 @@ export default function WorkflowDetailsPage(props: Props) {
|
||||
<MultiSelectCheckboxes
|
||||
options={eventTypeOptions}
|
||||
isLoading={isLoading}
|
||||
className="w-full md:w-64"
|
||||
setSelected={setSelectedEventTypes}
|
||||
selected={selectedEventTypes}
|
||||
setValue={(s: Option[]) => {
|
||||
|
||||
@@ -6,12 +6,18 @@ import { useState } from "react";
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import showToast from "@calcom/lib/notification";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Tooltip } from "@calcom/ui";
|
||||
import Dropdown, { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@calcom/ui/Dropdown";
|
||||
import { Icon } from "@calcom/ui/Icon";
|
||||
import { Button, ButtonGroup } from "@calcom/ui/v2";
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Dropdown,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
showToast,
|
||||
Tooltip,
|
||||
} from "@calcom/ui/v2";
|
||||
|
||||
import { getActionIcon } from "../../lib/getActionIcon";
|
||||
import { DeleteDialog } from "./DeleteDialog";
|
||||
@@ -111,17 +117,15 @@ export default function WorkflowListPage({ workflows }: Props) {
|
||||
</li>
|
||||
<li className="mb-1 flex items-center whitespace-nowrap rounded-sm bg-gray-100 px-1 py-px text-xs text-gray-800 dark:bg-gray-900 dark:text-white">
|
||||
{workflow.activeOn && workflow.activeOn.length > 0 ? (
|
||||
<div>
|
||||
<Tooltip
|
||||
content={workflow.activeOn.map((activeOn, key) => (
|
||||
<p key={key}>{activeOn.eventType.title}</p>
|
||||
))}>
|
||||
<>
|
||||
<Icon.FiLink className="mr-1.5 inline h-3 w-3" aria-hidden="true" />
|
||||
{t("active_on_event_types", { count: workflow.activeOn.length })}
|
||||
</>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Tooltip
|
||||
content={workflow.activeOn.map((activeOn, key) => (
|
||||
<p key={key}>{activeOn.eventType.title}</p>
|
||||
))}>
|
||||
<div>
|
||||
<Icon.FiLink className="mr-1.5 inline h-3 w-3" aria-hidden="true" />
|
||||
{t("active_on_event_types", { count: workflow.activeOn.length })}
|
||||
</div>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<div>
|
||||
<Icon.FiLink className="mr-1.5 inline h-3 w-3" aria-hidden="true" />
|
||||
@@ -134,26 +138,67 @@ export default function WorkflowListPage({ workflows }: Props) {
|
||||
</a>
|
||||
</Link>
|
||||
<div className="flex flex-shrink-0">
|
||||
<ButtonGroup combined>
|
||||
<Button
|
||||
type="button"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
combined
|
||||
StartIcon={Icon.FiEdit2}
|
||||
onClick={async () => await router.replace("/workflows/" + workflow.id)}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setDeleteDialogOpen(true);
|
||||
setwWorkflowToDeleteId(workflow.id);
|
||||
}}
|
||||
color="secondary"
|
||||
combined
|
||||
size="icon"
|
||||
StartIcon={Icon.FiTrash2}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
<div className="hidden sm:block">
|
||||
<ButtonGroup combined>
|
||||
<Tooltip content={t("edit") as string}>
|
||||
<Button
|
||||
type="button"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
combined
|
||||
StartIcon={Icon.FiEdit2}
|
||||
onClick={async () => await router.replace("/workflows/" + workflow.id)}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip content={t("delete") as string}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setDeleteDialogOpen(true);
|
||||
setwWorkflowToDeleteId(workflow.id);
|
||||
}}
|
||||
color="secondary"
|
||||
combined
|
||||
size="icon"
|
||||
StartIcon={Icon.FiTrash2}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<div className="block sm:hidden">
|
||||
<Dropdown>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
color="minimal"
|
||||
size="icon"
|
||||
StartIcon={Icon.FiMoreHorizontal}
|
||||
/>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
type="button"
|
||||
color="minimal"
|
||||
combined
|
||||
StartIcon={Icon.FiEdit2}
|
||||
onClick={async () => await router.replace("/workflows/" + workflow.id)}>
|
||||
{t("edit")}
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setDeleteDialogOpen(true);
|
||||
setwWorkflowToDeleteId(workflow.id);
|
||||
}}
|
||||
color="minimal"
|
||||
StartIcon={Icon.FiTrash2}>
|
||||
{t("delete")}
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -6,11 +6,11 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
|
||||
import { Icon } from "@calcom/ui";
|
||||
import Loader from "@calcom/ui/Loader";
|
||||
import { Alert, Button, showToast } from "@calcom/ui/v2";
|
||||
import Shell from "@calcom/ui/v2/core/Shell";
|
||||
|
||||
import LicenseRequired from "../../../common/components/v2/LicenseRequired";
|
||||
import SkeletonLoader from "../../components/v2/SkeletonLoaderList";
|
||||
import WorkflowList from "../../components/v2/WorkflowListPage";
|
||||
|
||||
function WorkflowsPage() {
|
||||
@@ -60,7 +60,7 @@ function WorkflowsPage() {
|
||||
}>
|
||||
<LicenseRequired>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
<SkeletonLoader />
|
||||
) : (
|
||||
<>
|
||||
{isFreeUser ? (
|
||||
@@ -73,7 +73,7 @@ function WorkflowsPage() {
|
||||
</LicenseRequired>
|
||||
</Shell>
|
||||
) : (
|
||||
<Loader />
|
||||
<></>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,12 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
import { stringOrNumber } from "@calcom/prisma/zod-utils";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
|
||||
import Loader from "@calcom/ui/Loader";
|
||||
import { Option } from "@calcom/ui/form/MultiSelectCheckboxes";
|
||||
import { Alert, Button, Form, showToast } from "@calcom/ui/v2";
|
||||
import Shell from "@calcom/ui/v2/core/Shell";
|
||||
|
||||
import LicenseRequired from "../../../common/components/v2/LicenseRequired";
|
||||
import SkeletonLoader from "../../components/v2/SkeletonLoaderEdit";
|
||||
import WorkflowDetailsPage from "../../components/v2/WorkflowDetailsPage";
|
||||
import { getTranslatedText } from "../../lib/variableTranslations";
|
||||
import { translateVariablesToEnglish } from "../../lib/variableTranslations";
|
||||
@@ -221,7 +221,7 @@ function WorkflowPage() {
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Loader />
|
||||
<SkeletonLoader />
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
@@ -233,7 +233,7 @@ function WorkflowPage() {
|
||||
</Shell>
|
||||
</Form>
|
||||
) : (
|
||||
<Loader />
|
||||
<></>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import { ShellSubHeading } from "../Shell";
|
||||
function SkeletonLoader({ className }: { className?: string }) {
|
||||
return (
|
||||
<>
|
||||
<ShellSubHeading title={<div className="h-6 w-32 rounded-sm bg-gray-100" />} {...{ className }} />
|
||||
<ul className="-mx-4 animate-pulse divide-y divide-neutral-200 rounded-sm border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
|
||||
<ShellSubHeading title={<div className="h-6 w-32 bg-gray-100" />} {...{ className }} />
|
||||
<ul className="-mx-4 animate-pulse divide-y divide-neutral-200 rounded-md border border-gray-200 bg-white sm:mx-0 sm:overflow-hidden">
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
<SkeletonItem />
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { Dispatch, SetStateAction } from "react";
|
||||
import { components, GroupBase, OptionProps } from "react-select";
|
||||
import { Props } from "react-select";
|
||||
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
import Select from "./Select";
|
||||
@@ -68,6 +69,7 @@ export default function MultiSelectCheckboxes({
|
||||
selected,
|
||||
setSelected,
|
||||
setValue,
|
||||
className,
|
||||
}: Omit<Props, "options"> & MultiSelectionCheckboxesProps) {
|
||||
const additonalComponents = { MultiValue };
|
||||
|
||||
@@ -91,7 +93,7 @@ export default function MultiSelectCheckboxes({
|
||||
}}
|
||||
options={options}
|
||||
isMulti
|
||||
className="w-64 text-sm"
|
||||
className={classNames(className ? className : "w-64 text-sm")}
|
||||
isSearchable={false}
|
||||
closeMenuOnSelect={false}
|
||||
hideSelectedOptions={false}
|
||||
|
||||
Reference in New Issue
Block a user