Skip to content

Commit

Permalink
feat: Namananand/ins 1355 update metric table with new design on dash…
Browse files Browse the repository at this point in the history
…board page (#482)

Because

- we need metric table with new design on dashboard page

This commit

- metric table with new design on dashboard page
  • Loading branch information
iamnamananand996 authored Jul 24, 2023
1 parent cea2f28 commit 4894b1a
Show file tree
Hide file tree
Showing 11 changed files with 643 additions and 12 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
"@code-hike/mdx": "^0.7.3",
"@dnd-kit/core": "^6.0.8",
"@hookform/resolvers": "^3.1.1",
"@instill-ai/design-system": "^0.33.1",
"@instill-ai/design-system": "^0.33.2-rc.1",
"@instill-ai/design-tokens": "^0.3.2",
"@instill-ai/toolkit": "^0.61.3",
"@instill-ai/toolkit": "^0.61.4-rc.0",
"@radix-ui/react-checkbox": "^1.0.3",
"@radix-ui/react-collapsible": "^1.0.2",
"@radix-ui/react-dialog": "^1.0.3",
Expand All @@ -46,6 +46,7 @@
"@radix-ui/react-toast": "^1.1.4",
"@tanstack/react-query": "^4.29.19",
"@tanstack/react-query-devtools": "^4.29.19",
"@tanstack/react-table": "^8.9.3",
"axios": "^1.3.4",
"clsx": "^1.1.1",
"cookie": "^0.5.0",
Expand Down
21 changes: 12 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

195 changes: 195 additions & 0 deletions src/components/DashboardPipelinesTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import * as React from "react";
import Link from "next/link";
import {
Nullable,
PipelineTriggerCount,
chunk,
env,
PaginationListContainerProps,
} from "@instill-ai/toolkit";
import {
Button,
Checkbox,
DataTable,
Icons,
Tag,
} from "@instill-ai/design-system";
import { ColumnDef } from "@tanstack/react-table";
import { PipelineTablePlaceholder } from "./table/PipelineTablePlaceholder";
import { TableError } from "./table/TableError";

export type DashboardPipelinesTableProps = {
pipelineTriggerCounts: PipelineTriggerCount[];
isError: boolean;
isLoading: boolean;
} & Pick<PaginationListContainerProps, "marginBottom">;

type Sort = "asc" | "desc" | false;
const getIcon = (type: Sort) => {
if (type === "asc") {
return <Icons.ArrowDown className="h-4 w-4 stroke-semantic-fg-secondary" />;
}
if (type === "desc") {
return <Icons.ArrowUp className="h-4 w-4 stroke-semantic-fg-secondary" />;
}
return (
<Icons.ChevronSelectorVertical className="h-4 w-4 stroke-semantic-fg-secondary" />
);
};

export const DashboardPipelinesTable = (
props: DashboardPipelinesTableProps
) => {
const { pipelineTriggerCounts, marginBottom, isError, isLoading } = props;
const [currentPage, setCurrentPage] = React.useState(0);
const [searchTerm, setSearchTerm] = React.useState<Nullable<string>>(null);

// We will only use searched resource when user input search term

const pipelineTriggerPages = React.useMemo(() => {
return chunk(pipelineTriggerCounts, env("NEXT_PUBLIC_LIST_PAGE_SIZE"));
}, [pipelineTriggerCounts]);

const columns: ColumnDef<PipelineTriggerCount>[] = [
{
accessorKey: "pipeline_id",
header: () => <div className="min-w-[600px] text-left">Pipeline Id</div>,
cell: ({ row }) => {
return (
<div className="flex min-w-[600px] flex-row gap-x-2">
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
className="h-5 w-5"
/>

<Link
href={`/dashboard/pipeline/${row.getValue("pipeline_id")}`}
className="hover:underline"
>
{row.getValue("pipeline_id")}
</Link>
</div>
);
},
},
{
accessorKey: "watchState",
accessorFn: (row) => row.watchState,
header: () => <div className="max-w-[80px] text-center">Status</div>,
cell: ({ row }) => {
return (
<div className="text-center">
<Tag
variant={
row.getValue("watchState") === "STATE_ACTIVE"
? "lightGreen"
: "lightRed"
}
className="border-0"
size={"sm"}
>
Active
</Tag>
</div>
);
},
},
{
accessorKey: "pipeline_completed",
header: ({ column }) => {
return (
<div className="min-w-[130px] text-center">
<Button
className="gap-x-2 py-0"
variant="tertiaryGrey"
size="sm"
onClick={() =>
column.toggleSorting(column.getIsSorted() === "asc")
}
>
<span className="min-w-[130px]">Completed Triggers</span>
{getIcon(column.getIsSorted())}
</Button>
</div>
);
},

cell: ({ row }) => {
return (
<div className="text-center text-semantic-fg-secondary">
{row.getValue("pipeline_completed")}
</div>
);
},
},
{
accessorKey: "pipeline_errored",
header: ({ column }) => (
<div className="min-w-[110px] text-center">
<Button
className="gap-x-2 py-0"
variant="tertiaryGrey"
size="sm"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="min-w-[110px]">Errored Triggers</span>
{getIcon(column.getIsSorted())}
</Button>
</div>
),
cell: ({ row }) => {
return (
<div className="text-center text-semantic-fg-secondary">
{row.getValue("pipeline_errored")}
</div>
);
},
},
];

if (isError) {
return (
<DataTable
columns={columns}
data={pipelineTriggerCounts}
pageSize={6}
searchPlaceholder={null}
searchKey={null}
isLoading={isLoading}
loadingRows={6}
>
<TableError />
</DataTable>
);
}

if (pipelineTriggerCounts.length === 0 && !isLoading) {
return (
<DataTable
columns={columns}
data={pipelineTriggerCounts}
pageSize={6}
searchPlaceholder={null}
searchKey={null}
isLoading={isLoading}
loadingRows={6}
>
<PipelineTablePlaceholder enableCreateButton={false} />
</DataTable>
);
}

return (
<DataTable
columns={columns}
data={pipelineTriggerCounts}
pageSize={6}
searchPlaceholder={null}
searchKey={null}
isLoading={isLoading}
loadingRows={6}
/>
);
};
38 changes: 38 additions & 0 deletions src/components/cell/TableCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Nullable } from "@instill-ai/toolkit";
import * as React from "react";

type TableCellProps = {
iconElement: Nullable<React.ReactElement>;
primaryText: Nullable<string>;
secondaryText: Nullable<string>;
};

function TableCell({
iconElement,
primaryText,
secondaryText,
}: TableCellProps) {
return (
<div className="flex flex-row items-center gap-x-3">
{iconElement && (
<div className="h-8 w-8 rounded-lg bg-semantic-bg-secondary p-2 ">
{iconElement}
</div>
)}
<div className="flex flex-col">
{primaryText && (
<h1 className="text-semantic-fg-primary product-body-text-3-semibold">
{primaryText}
</h1>
)}
{secondaryText && (
<p className="text-semantic-fg-disabled product-body-text-3-regular">
{secondaryText}
</p>
)}
</div>
</div>
);
}

export { TableCell };
1 change: 1 addition & 0 deletions src/components/cell/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./TableCell";
25 changes: 25 additions & 0 deletions src/components/icons/IconWithBackground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { ReactElement } from "react";
import cn from "clsx";

type IconWithBackgroundProps = {
iconElement: ReactElement;
className: string;
};

function IconWithBackground({
iconElement,
className,
}: IconWithBackgroundProps) {
return (
<div
className={cn(
"flex h-8 w-8 items-center justify-center rounded-lg p-2",
className
)}
>
{iconElement}
</div>
);
}

export { IconWithBackground };
1 change: 1 addition & 0 deletions src/components/icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./IconWithBackground";
Loading

0 comments on commit 4894b1a

Please sign in to comment.