diff --git a/dashboard/src/components/entity-table/entity-table-provider.ts b/dashboard/src/components/entity-table/entity-table-provider.ts index 2204475..3b93904 100644 --- a/dashboard/src/components/entity-table/entity-table-provider.ts +++ b/dashboard/src/components/entity-table/entity-table-provider.ts @@ -6,6 +6,7 @@ interface EntityTableContextProps { table: Table data: TData[] filtering: UseFilteringReturn + isLoading: boolean } export const EntityTableContext = createContext | null>(null); diff --git a/dashboard/src/components/entity-table/hooks/use-entity-query.ts b/dashboard/src/components/entity-table/hooks/use-entity-query.ts index 04ddca5..76167c0 100644 --- a/dashboard/src/components/entity-table/hooks/use-entity-query.ts +++ b/dashboard/src/components/entity-table/hooks/use-entity-query.ts @@ -2,12 +2,13 @@ import { z } from "zod"; const UseEntityQueryPropsSchema = z.object({ page: z.number().gte(1), - size: z.number().gte(1).lte(100) + size: z.number().gte(1).lte(100), + search: z.string().optional() }) export type UseEntityQueryProps = z.infer -export type EntityQueryKeyType = { queryKey: [string, number, number] } +export type EntityQueryKeyType = { queryKey: [string, number, number, string] } interface FetchEntityResult { pageCount: number diff --git a/dashboard/src/components/entity-table/hooks/use-entity-table.ts b/dashboard/src/components/entity-table/hooks/use-entity-table.ts index 7c9a7f2..74692c2 100644 --- a/dashboard/src/components/entity-table/hooks/use-entity-table.ts +++ b/dashboard/src/components/entity-table/hooks/use-entity-table.ts @@ -1,5 +1,17 @@ -import { ColumnDef, OnChangeFn, PaginationState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table"; -import { UseFilteringReturn, UseRowSelectionReturn, UseSortingReturn, UseVisibilityReturn } from "."; +import { + ColumnDef, + OnChangeFn, + PaginationState, + getCoreRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable +} from "@tanstack/react-table"; +import { + UseRowSelectionReturn, + UseSortingReturn, + UseVisibilityReturn +} from "."; interface UseEntityTableProps { columns: ColumnDef[] @@ -7,7 +19,6 @@ interface UseEntityTableProps { entity: TData[] pageCount: number } - filtering: UseFilteringReturn sorting: UseSortingReturn visibility: UseVisibilityReturn rowSelection?: UseRowSelectionReturn @@ -20,7 +31,6 @@ export const useEntityTable = ( { columns, data, - filtering, sorting, visibility, rowSelection, @@ -36,16 +46,13 @@ export const useEntityTable = ( autoResetPageIndex: false, onPaginationChange, onSortingChange: sorting.setSorting, - onColumnFiltersChange: filtering.setColumnFilters, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), - getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: visibility.setColumnVisibility, onRowSelectionChange: rowSelection && rowSelection.setSelectedRow, state: { sorting: sorting.sorting, - columnFilters: filtering.columnFilters, columnVisibility: visibility.columnVisibility, pagination: { pageIndex: pageIndex - 1, pageSize }, rowSelection: rowSelection ? rowSelection.selectedRow : {}, diff --git a/dashboard/src/components/entity-table/hooks/use-filtering.ts b/dashboard/src/components/entity-table/hooks/use-filtering.ts index 8a09960..15041e8 100644 --- a/dashboard/src/components/entity-table/hooks/use-filtering.ts +++ b/dashboard/src/components/entity-table/hooks/use-filtering.ts @@ -1,4 +1,4 @@ -import { ColumnFiltersState, OnChangeFn } from "@tanstack/react-table" +import { OnChangeFn } from "@tanstack/react-table" import { useState } from "react" export interface UseFilteringType { @@ -6,11 +6,11 @@ export interface UseFilteringType { } export interface UseFilteringReturn extends UseFilteringType { - columnFilters: ColumnFiltersState - setColumnFilters: OnChangeFn + columnFilters: string + setColumnFilters: OnChangeFn } export const useFiltering = ({ column }: UseFilteringType): UseFilteringReturn => { - const [columnFilters, setColumnFilters] = useState([]) + const [columnFilters, setColumnFilters] = useState("") return { setColumnFilters, columnFilters, column } } diff --git a/dashboard/src/components/entity-table/index.tsx b/dashboard/src/components/entity-table/index.tsx index 8fc5d8a..05575b3 100644 --- a/dashboard/src/components/entity-table/index.tsx +++ b/dashboard/src/components/entity-table/index.tsx @@ -1,4 +1,4 @@ -import { FC, useState } from "react"; +import { FC, useEffect, useState } from "react"; import { Button, DataTableViewOptions } from "@marzneshin/components"; import { useTranslation } from "react-i18next"; import { useQuery } from "@tanstack/react-query"; @@ -71,16 +71,15 @@ export function EntityTable({ const visibility = useVisibility() const { onPaginationChange, pageIndex, pageSize } = usePagination(); - const { data } = useQuery({ + const { data, isLoading } = useQuery({ queryFn: fetchEntity, - queryKey: [entityKey, pageIndex, pageSize], + queryKey: [entityKey, pageIndex, pageSize, filtering.columnFilters], initialData: { entity: [], pageCount: 1 } }); const columns = columnsFn({ onEdit, onDelete, onOpen }) const table = useEntityTable({ data, - filtering, columns, pageSize, pageIndex, @@ -90,9 +89,11 @@ export function EntityTable({ onPaginationChange }) + useEffect(() => table.setPageIndex(1), [filtering.columnFilters, table]) + // TODO: Move the selectedEntity to context return ( - + = () => { - const { table, filtering } = useEntityTableContext() + const { filtering } = useEntityTableContext() const { t } = useTranslation() return ( - table.getColumn(filtering.column)?.setFilterValue(event.target.value) - } + value={filtering.columnFilters} + onChange={(e) => filtering.setColumnFilters(e.target.value)} className="max-w-sm" /> ); diff --git a/dashboard/src/components/entity-table/table.tsx b/dashboard/src/components/entity-table/table.tsx index 2d222ca..bf9d550 100644 --- a/dashboard/src/components/entity-table/table.tsx +++ b/dashboard/src/components/entity-table/table.tsx @@ -14,6 +14,7 @@ import { import { useTranslation } from "react-i18next" import { useEntityTableContext } from "./entity-table-provider" +import { LoaderCircle } from "lucide-react" interface DataTableProps { columns: ColumnDef[] @@ -25,7 +26,7 @@ export function EntityDataTable({ onRowClick, }: DataTableProps) { const { t } = useTranslation(); - const { table } = useEntityTableContext() + const { table, isLoading } = useEntityTableContext() return ( @@ -47,27 +48,35 @@ export function EntityDataTable({ ))} - {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - onRowClick && onRowClick(row.original)} - > - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - )) - ) : ( - + {isLoading ? ( + - {t('table.no-result')} + + ) : ( + table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + onRowClick && onRowClick(row.original)} + > + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + {t('table.no-result')} + + + ) )}
diff --git a/dashboard/src/features/nodes/services/nodes.query.ts b/dashboard/src/features/nodes/services/nodes.query.ts index 37d9185..6101556 100644 --- a/dashboard/src/features/nodes/services/nodes.query.ts +++ b/dashboard/src/features/nodes/services/nodes.query.ts @@ -7,7 +7,7 @@ import { } from "@marzneshin/components"; export async function fetchNodes({ queryKey }: EntityQueryKeyType): Promise<{ entity: NodeType[], pageCount: number }> { - return fetch(`/nodes?page=${queryKey[1]}&size=${queryKey[2]}`).then((result) => { + return fetch(`/nodes?page=${queryKey[1]}&size=${queryKey[2]}&name=${queryKey[3]}`).then((result) => { return { entity: result.items, pageCount: result.pages, @@ -18,9 +18,9 @@ export async function fetchNodes({ queryKey }: EntityQueryKeyType): Promise<{ en export const NodesQueryFetchKey = "nodes"; -export const useNodesQuery = ({ page, size }: UseEntityQueryProps) => { +export const useNodesQuery = ({ page, size, search }: UseEntityQueryProps) => { return useQuery({ - queryKey: [NodesQueryFetchKey, page, size], + queryKey: [NodesQueryFetchKey, page, size, search ? search : ""], queryFn: fetchNodes, initialData: { entity: [], pageCount: 0 }, }) diff --git a/dashboard/src/features/services/services/services.query.ts b/dashboard/src/features/services/services/services.query.ts index 2e99511..aa0cfc2 100644 --- a/dashboard/src/features/services/services/services.query.ts +++ b/dashboard/src/features/services/services/services.query.ts @@ -17,7 +17,7 @@ interface ServiceResponse { } export async function fetchServices({ queryKey }: EntityQueryKeyType): FetchEntityReturn { - return fetch(`/services?page=${queryKey[1]}&size=${queryKey[2]}`).then((result) => { + return fetch(`/services?page=${queryKey[1]}&size=${queryKey[2]}&name=${queryKey[3]}`).then((result) => { const services: ServiceType[] = result.items.map((fetchedService: ServiceResponse) => { const service: ServiceType = fetchedService; service.users = fetchedService.user_ids @@ -33,9 +33,9 @@ export async function fetchServices({ queryKey }: EntityQueryKeyType): FetchEnti export const ServicesQueryFetchKey = "services"; -export const useServicesQuery = ({ page, size }: UseEntityQueryProps) => { +export const useServicesQuery = ({ page, size, search }: UseEntityQueryProps) => { return useQuery({ - queryKey: [ServicesQueryFetchKey, page, size], + queryKey: [ServicesQueryFetchKey, page, size, search ? search : ""], queryFn: fetchServices, initialData: { entity: [], pageCount: 0 } }) diff --git a/dashboard/src/features/users/services/users.query.ts b/dashboard/src/features/users/services/users.query.ts index 1a3809d..7220aa4 100644 --- a/dashboard/src/features/users/services/users.query.ts +++ b/dashboard/src/features/users/services/users.query.ts @@ -9,7 +9,7 @@ interface UserResponse extends UserType { } export async function fetchUsers({ queryKey }: EntityQueryKeyType): FetchEntityReturn { - return fetch(`/users?page=${queryKey[1]}&size=${queryKey[2]}`).then((result) => { + return fetch(`/users?page=${queryKey[1]}&size=${queryKey[2]}&username=${queryKey[3]}`).then((result) => { const users: UserType[] = result.items.map((fetchedUser: UserResponse) => { const user: UserType = fetchedUser; user.services = fetchedUser.service_ids @@ -24,9 +24,9 @@ export async function fetchUsers({ queryKey }: EntityQueryKeyType): FetchEntityR export const UsersQueryFetchKey = "users"; -export const useUsersQuery = ({ page, size }: UseEntityQueryProps) => { +export const useUsersQuery = ({ page, size, search }: UseEntityQueryProps) => { return useQuery({ - queryKey: [UsersQueryFetchKey, page, size], + queryKey: [UsersQueryFetchKey, page, size, search ? search : ""], queryFn: fetchUsers, initialData: { entity: [], pageCount: 0 } })