perbaikan storybook dataTable Component
This commit is contained in:
@@ -7,6 +7,7 @@ const config: StorybookConfig = {
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-onboarding",
|
||||
"@storybook/addon-interactions",
|
||||
"@storybook/addon-styling-webpack"
|
||||
],
|
||||
framework: {
|
||||
name: "@storybook/react-vite",
|
||||
|
||||
14560
front_end_portserver/package-lock.json
generated
14560
front_end_portserver/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@
|
||||
"@storybook/addon-interactions": "7.5.3",
|
||||
"@storybook/addon-links": "7.5.3",
|
||||
"@storybook/addon-onboarding": "1.0.8",
|
||||
"@storybook/addon-styling-webpack": "0.0.5",
|
||||
"@storybook/blocks": "7.5.3",
|
||||
"@storybook/react": "7.5.3",
|
||||
"@storybook/react-vite": "7.5.3",
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
export type OptionStatusType = {
|
||||
InfoValue: string,
|
||||
};
|
||||
|
||||
export type OptionResultType = {
|
||||
RawDataValue: string,
|
||||
ResultValue: string,
|
||||
ExportValue: string,
|
||||
};
|
||||
|
||||
export type OptionQueryType = {
|
||||
RawDataValue: string,
|
||||
QueryResponseValue: string,
|
||||
ExportValue: string,
|
||||
};
|
||||
|
||||
export type OptionType = {
|
||||
type : string,
|
||||
data : OptionStatusType | OptionResultType | OptionQueryType
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
export type InfoType = {
|
||||
status ?: string,
|
||||
result ?: string,
|
||||
query ?: string,
|
||||
type ?: string,
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Meta, StoryObj} from "@storybook/react";
|
||||
import { DataTableDemo, columns, data } from "../tableComponent/DataTable";
|
||||
|
||||
const meta = {
|
||||
title: 'Component/Table',
|
||||
component: DataTableDemo,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
args: {
|
||||
data: data,
|
||||
columns: columns,
|
||||
},
|
||||
argTypes: {
|
||||
},
|
||||
} satisfies Meta<typeof DataTableDemo>
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Datable = (args:Story) => {
|
||||
return(
|
||||
<DataTableDemo data={data} columns={columns} {...args} />
|
||||
)
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
import { columns } from "../tableComponent/columns"
|
||||
import { Tables } from "../tableComponent/Table"
|
||||
|
||||
const meta = {
|
||||
title: 'Component/Table',
|
||||
component : Tables,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
|
||||
args:{
|
||||
data: [
|
||||
{ date: new Date("2023-10-30 15:26:04"), info: '800 Cobas Status', type: 'status', onClick: () => console.log('Clicked') },
|
||||
{ date: new Date("2020-01-10 05:00:04"), info: 'Incoming Cobas 800 result', type: 'result', onClick: () => console.log('Clicked') },
|
||||
// Data lainnya...
|
||||
], // Tentukan header di sini
|
||||
columns: columns
|
||||
},
|
||||
argTypes:{
|
||||
columns: {
|
||||
accessorKey: { type: "string" }, // Ganti "string" dengan tipe data yang benar
|
||||
header: { type: "string" }
|
||||
}
|
||||
},
|
||||
|
||||
}satisfies Meta<typeof Tables>
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
|
||||
const getData = [
|
||||
{
|
||||
id: "2023-10-30T15:26:04Z",
|
||||
info: "Cobas 800",
|
||||
date: "2023-10-30T15:26:04",
|
||||
type: "status"
|
||||
},
|
||||
{
|
||||
id: "2023-10-28T15:26:04",
|
||||
info: "Incoming Cobas 800 Result",
|
||||
date: "2020-01-10 05:00:04",
|
||||
type: "result"
|
||||
}
|
||||
];
|
||||
|
||||
export const PortServerTable = (args:Story) => {
|
||||
|
||||
return (
|
||||
<div className="container mx-auto py-10">
|
||||
<Tables columns={columns} data={getData} {...args} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table"
|
||||
import { DateDisplay } from "./DateDisplay"
|
||||
import { CogIcon, DotIcon } from "../stories/Icon.stories"
|
||||
import "../../../../app/global.css"
|
||||
|
||||
export const data: PortServer[] = [
|
||||
{
|
||||
id: "m5gr84i9",
|
||||
info: "800 Cobas Status",
|
||||
date: new Date("2023-10-30 15:26:04"),
|
||||
type: "status",
|
||||
},
|
||||
{
|
||||
id: "3u1reuv4",
|
||||
info: "Incoming 800 Cobas Result",
|
||||
date: new Date("2023-10-30 15:26:04"),
|
||||
type: "result",
|
||||
},
|
||||
{
|
||||
id: "derv1ws0",
|
||||
info: "Incoming 800 Cobas Query",
|
||||
date: new Date("2023-10-30 15:26:04"),
|
||||
type: "query",
|
||||
}
|
||||
]
|
||||
|
||||
export type PortServer = {
|
||||
id: string
|
||||
info: string
|
||||
date: Date
|
||||
type : 'status' | 'result' | 'query'
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<PortServer>[] = [
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: "Date",
|
||||
cell: ({ row }) => {
|
||||
const date = new Date(row.getValue("date"))
|
||||
return(
|
||||
<div className="text-[#637381] bg-[#919EAB29] rounded-md border-4 border-[#919EAB29]">
|
||||
<DateDisplay date={date}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorKey: "info",
|
||||
header: "Info",
|
||||
cell: ({ row }) => (
|
||||
<div className="capitalize">{row.getValue("info")}</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header:() => {
|
||||
return(
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<CogIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem
|
||||
onClick={() => {}}
|
||||
>
|
||||
<span>Change Password</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
},
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const type = row.original
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<DotIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
{
|
||||
type.type?.toLowerCase() == 'status' ? (
|
||||
<DropdownMenuItem
|
||||
onClick={() => {}}
|
||||
>
|
||||
Info
|
||||
</DropdownMenuItem>
|
||||
) : ''
|
||||
}
|
||||
{
|
||||
type.type?.toLowerCase() == 'result' ? (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => {}} >
|
||||
Raw Data
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Result
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Export
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
) : ''
|
||||
}
|
||||
{
|
||||
type.type?.toLowerCase() == 'query' ? (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Raw Data
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Query Response
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Export
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
) : ''
|
||||
}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
},
|
||||
]
|
||||
|
||||
export interface DataTableProps {
|
||||
data: PortServer[]; // Properti untuk data tabel
|
||||
columns: ColumnDef<PortServer>[];
|
||||
}
|
||||
|
||||
export const DataTableDemo = ({
|
||||
data,
|
||||
columns,
|
||||
}: DataTableProps) => {
|
||||
const [sorting, setSorting] = React.useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
)
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({})
|
||||
const [rowSelection, setRowSelection] = React.useState({})
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
)
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={columns.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
ColumnDef,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table"
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table"
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[]
|
||||
data: TData[]
|
||||
}
|
||||
|
||||
export const Tables = <TData, TValue>({
|
||||
columns,
|
||||
data,
|
||||
}: DataTableProps<TData, TValue>) => {
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-[#919EAB52]">
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
)
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@radix-ui/react-dropdown-menu"
|
||||
import { ColumnDef } from "@tanstack/react-table"
|
||||
import { CogIcon, DotIcon } from "../stories/Icon.stories"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { DateDisplay } from "./DateDisplay"
|
||||
|
||||
// This type is used to define the shape of our data.
|
||||
// You can use a Zod schema here if you want.
|
||||
export type PortServer = {
|
||||
id: string
|
||||
date: string
|
||||
info: string
|
||||
type: string
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<PortServer>[] = [
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: "Date",
|
||||
cell: ({ row }) => {
|
||||
const date = new Date(row.getValue("date"))
|
||||
return(
|
||||
<div className="text-[#637381] bg-[#919EAB29] rounded-md border-4 border-[#919EAB29]">
|
||||
<DateDisplay date={date}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorKey: "info",
|
||||
header: "Info",
|
||||
},
|
||||
{
|
||||
accessorKey: "option",
|
||||
header:() => {
|
||||
return(
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<CogIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem
|
||||
onClick={() => {}}
|
||||
>
|
||||
Change Password
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const type = row.original
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<DotIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
{
|
||||
type.type?.toLowerCase() == 'status' ? (
|
||||
<DropdownMenuItem
|
||||
onClick={() => {}}
|
||||
>
|
||||
Info
|
||||
</DropdownMenuItem>
|
||||
) : ''
|
||||
}
|
||||
{
|
||||
type.type?.toLowerCase() == 'result' ? (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => {}} >
|
||||
Raw Data
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Result
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Export
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
) : ''
|
||||
}
|
||||
{
|
||||
type.type?.toLowerCase() == 'query' ? (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Raw Data
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Query Response
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => {}}>
|
||||
Export
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
) : ''
|
||||
}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
},
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user