Skip to content

Commit

Permalink
feat(disable export button): Disable export button when no records av…
Browse files Browse the repository at this point in the history
…ailable (#739)

* disable export button when no records displayed

* add tooltip only when export button disabled

* wip useOsUrl not found

* add role to button

* useOsUrl is not a function wip

* delete other unused code

* useLocation() may be used only in the context of a <Router> component.

* useOsData is not a function

* still not a function...

* Component finally rendering, changed import to use '@/'

* wip mock disable export button

* test hover disabled export button

* remove unused export and return handleExport if no records/disabled even if button is enabled

* change role to data-testid to fix e2e

---------

Co-authored-by: Tiffany Vu <[email protected]>
Co-authored-by: Tiffany Vu <[email protected]>
  • Loading branch information
3 people authored Sep 6, 2024
1 parent d2f2c68 commit bf9455f
Show file tree
Hide file tree
Showing 8 changed files with 32,264 additions and 19 deletions.
Binary file modified bun.lockb
Binary file not shown.
32,165 changes: 32,165 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-query": "^4.29.1",
"@tanstack/react-query-devtools": "^4.29.5",
"@types/file-saver": "^2.0.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { render, screen, waitFor } from "@testing-library/react";
import { describe, expect, test, vi, beforeEach } from "vitest";
import { OsExportData } from "@/components";
import userEvent from "@testing-library/user-event";

vi.mock("@/components/Opensearch/main/useOpensearch.ts", () => ({
useOsUrl: vi.fn(),
}));

describe("Tooltip component within export button", () => {
beforeEach(() => {
render(<OsExportData columns={[]} disabled={true} />);
});

test("Tooltip content hidden when not hovering", async () => {
const tooltipTrigger = screen.queryByTestId("tooltip-trigger");
expect(tooltipTrigger).toBeInTheDocument();

const tooltipContent = screen.queryByText("No records available");
expect(tooltipContent).not.toBeInTheDocument();
});

test("Tooltip content shown on hover", async () => {
const tooltipTrigger = screen.queryByTestId("tooltip-trigger");
expect(tooltipTrigger).toBeDisabled();

userEvent.hover(screen.queryByTestId("tooltip-trigger"));

await waitFor(() => screen.getByTestId("tooltip-content"));
expect(screen.queryAllByText("No records available")[0]).toBeVisible();
});
});
56 changes: 38 additions & 18 deletions react-app/src/components/Opensearch/main/Filtering/Export/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,24 @@ import {
OsTableColumn,
createSearchFilterable,
useOsUrl,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components";
import { FC } from "react";

export const OsExportData: FC<{
columns: OsTableColumn[];
}> = ({ columns }) => {
disabled?: boolean;
}> = ({ columns, disabled }) => {
const [loading, setLoading] = useState(false);
const url = useOsUrl();

const handleExport = async () => {
if (disabled) {
return;
}
setLoading(true);

const exportData: Record<any, any>[] = [];
Expand Down Expand Up @@ -54,22 +62,34 @@ export const OsExportData: FC<{
};

return (
<Button
variant="outline"
onClick={handleExport}
disabled={loading}
className="w-full xs:w-fit hover:bg-transparent self-center h-10 flex gap-2"
>
{loading && (
<motion.div
animate={{ rotate: "360deg" }}
transition={{ repeat: Infinity, duration: 0.5 }}
>
<Loader className="w-4 h-4" />
</motion.div>
)}
{!loading && <Download className="w-4 h-4" />}
<span className="prose-sm">Export</span>
</Button>
<TooltipProvider>
<Tooltip disableHoverableContent={true}>
<TooltipTrigger asChild className="disabled:pointer-events-auto">
<Button
variant="outline"
onClick={handleExport}
disabled={loading || disabled}
className="w-full xs:w-fit hover:bg-transparent self-center h-10 flex gap-2"
data-testid="tooltip-trigger"
>
{loading && (
<motion.div
animate={{ rotate: "360deg" }}
transition={{ repeat: Infinity, duration: 0.5 }}
>
<Loader className="w-4 h-4" />
</motion.div>
)}
{!loading && <Download className="w-4 h-4" />}
<span className="prose-sm">Export</span>
</Button>
</TooltipTrigger>
{disabled && (
<TooltipContent data-testid="tooltip-content">
No records available
</TooltipContent>
)}
</Tooltip>
</TooltipProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const OsFiltering: FC<{
disabled={!!props.disabled}
/>
<div className="flex justify-center flex-row gap-2">
<OsExportData columns={props.columns} />
<OsExportData columns={props.columns} disabled={context?.data?.total.value === 0}/>
<OsFilterDrawer />
</div>
</div>
Expand Down
26 changes: 26 additions & 0 deletions react-app/src/components/Tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { cn } from "@/utils";
const TooltipProvider = TooltipPrimitive.Provider

const Tooltip = TooltipPrimitive.Root

const TooltipTrigger = TooltipPrimitive.Trigger

const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName

export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
1 change: 1 addition & 0 deletions react-app/src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export * from "./ConfirmationDialog";
export * from "./SearchForm";
export * from "./TimeoutModal";
export * from "./Banner";
export * from "./Tooltip";

0 comments on commit bf9455f

Please sign in to comment.