mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-30 15:24:22 +00:00
feat(ui): migrate from HeroUI to shadcn/ui (#11532)
This commit is contained in:
1 parent
c665005790
commit
52875b5c7c
519 files changed
+4798
-6997
No files matched your search
@@ -2,7 +2,7 @@
|
||||
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
import { DataTableColumnHeader } from "@/components/ui/table";
|
||||
import { DataTableColumnHeader } from "@/components/shadcn/table";
|
||||
|
||||
import { DataTableRowActions } from "./data-table-row-actions";
|
||||
import {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { DateCell, NameCell } from "./table-cells";
|
||||
import type { EnrichedApiKey } from "./types";
|
||||
|
||||
const apiKey: EnrichedApiKey = {
|
||||
type: "api-keys",
|
||||
id: "api-key-1",
|
||||
attributes: {
|
||||
name: "Production access key with a very long human readable name",
|
||||
prefix: "pk_12345678",
|
||||
expires_at: "2099-01-01T00:00:00Z",
|
||||
revoked: false,
|
||||
inserted_at: "2026-01-01T00:00:00Z",
|
||||
last_used_at: null,
|
||||
},
|
||||
relationships: {
|
||||
entity: {
|
||||
data: {
|
||||
type: "users",
|
||||
id: "user-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
userEmail: "user@example.com",
|
||||
};
|
||||
|
||||
describe("NameCell", () => {
|
||||
it("keeps long API key names on one line with a tooltip", async () => {
|
||||
// Given - A long API key name
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(<NameCell apiKey={apiKey} />);
|
||||
|
||||
// When - Reading and hovering the displayed name
|
||||
const name = screen.getByText(apiKey.attributes.name!);
|
||||
await user.hover(name);
|
||||
|
||||
// Then - The cell has a fixed width, truncates, and exposes the full name
|
||||
expect(name).toHaveClass("w-64", "truncate", "whitespace-nowrap");
|
||||
expect(await screen.findByRole("tooltip")).toHaveTextContent(
|
||||
apiKey.attributes.name!,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("DateCell", () => {
|
||||
it("keeps API key dates on one line", () => {
|
||||
// Given - A rendered API key date
|
||||
render(<DateCell date={null} />);
|
||||
|
||||
// When - Reading the date cell
|
||||
const date = screen.getByText("Never");
|
||||
|
||||
// Then - The table date cannot wrap to a second line
|
||||
expect(date).toHaveClass("whitespace-nowrap");
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,35 @@
|
||||
import { Chip } from "@heroui/chip";
|
||||
import {
|
||||
Badge,
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/shadcn";
|
||||
|
||||
import { FALLBACK_VALUES } from "./constants";
|
||||
import { EnrichedApiKey, getApiKeyStatus } from "./types";
|
||||
import { formatRelativeTime, getStatusColor, getStatusLabel } from "./utils";
|
||||
|
||||
export const NameCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => (
|
||||
<p className="text-sm font-medium">
|
||||
{apiKey.attributes.name || FALLBACK_VALUES.UNNAMED}
|
||||
</p>
|
||||
);
|
||||
// Maps HeroUI status colors to shadcn Badge variants
|
||||
const STATUS_BADGE_VARIANT = {
|
||||
success: "success",
|
||||
danger: "error",
|
||||
warning: "warning",
|
||||
} as const;
|
||||
|
||||
export const NameCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => {
|
||||
const name = apiKey.attributes.name || FALLBACK_VALUES.UNNAMED;
|
||||
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<p className="w-64 truncate text-sm font-medium whitespace-nowrap">
|
||||
{name}
|
||||
</p>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{name}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export const PrefixCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => (
|
||||
<code className="rounded px-2 py-1 font-mono text-xs">
|
||||
@@ -17,7 +38,7 @@ export const PrefixCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => (
|
||||
);
|
||||
|
||||
export const DateCell = ({ date }: { date: string | null }) => (
|
||||
<p className="text-sm">{formatRelativeTime(date)}</p>
|
||||
<p className="text-sm whitespace-nowrap">{formatRelativeTime(date)}</p>
|
||||
);
|
||||
|
||||
export const LastUsedCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => (
|
||||
@@ -27,9 +48,9 @@ export const LastUsedCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => (
|
||||
export const StatusCell = ({ apiKey }: { apiKey: EnrichedApiKey }) => {
|
||||
const status = getApiKeyStatus(apiKey);
|
||||
return (
|
||||
<Chip color={getStatusColor(status)} size="sm" variant="flat">
|
||||
<Badge variant={STATUS_BADGE_VARIANT[getStatusColor(status)]}>
|
||||
{getStatusLabel(status)}
|
||||
</Chip>
|
||||
</Badge>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user