Merge pull request 'core/page-provider' (#26) from core/page-provider into main
Reviewed-on: eigen/fe-monorepo-template#26
This commit is contained in:
+1
-3
@@ -8,9 +8,7 @@
|
|||||||
"create_page_description": "Fill out the form below to add a new record to the system.",
|
"create_page_description": "Fill out the form below to add a new record to the system.",
|
||||||
"duplicate_page_description": "Copy and modify information from an existing record to quickly create a new one.",
|
"duplicate_page_description": "Copy and modify information from an existing record to quickly create a new one.",
|
||||||
"fields": {
|
"fields": {
|
||||||
"status": "Status",
|
|
||||||
"name": "Name",
|
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
"description": "Description"
|
"name": "Name"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-3
@@ -8,9 +8,7 @@
|
|||||||
"create_page_description": "Lengkapi formulir di bawah ini untuk menambahkan data baru ke dalam sistem.",
|
"create_page_description": "Lengkapi formulir di bawah ini untuk menambahkan data baru ke dalam sistem.",
|
||||||
"duplicate_page_description": "Salin dan sesuaikan informasi dari data yang sudah ada untuk mempercepat pembuatan data baru.",
|
"duplicate_page_description": "Salin dan sesuaikan informasi dari data yang sudah ada untuk mempercepat pembuatan data baru.",
|
||||||
"fields": {
|
"fields": {
|
||||||
"status": "Status",
|
|
||||||
"name": "Nama",
|
|
||||||
"code": "Kode",
|
"code": "Kode",
|
||||||
"description": "Deskripsi"
|
"name": "Nama"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -6,10 +6,10 @@ export default function FullPagePageDetail() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<EnterpriseDetailPageProvider
|
<EnterpriseDetailPageProvider
|
||||||
|
highlightDataKey="code"
|
||||||
pageHeaderProps={{
|
pageHeaderProps={{
|
||||||
title: t('detail_page_title'),
|
title: t('detail_page_title'),
|
||||||
description: t('detail_page_description'),
|
description: t('detail_page_description'),
|
||||||
// showBadges: false,
|
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{ label: t('nav:example-module'), type: 'text' },
|
{ label: t('nav:example-module'), type: 'text' },
|
||||||
{ label: t('nav:example-full-page'), type: 'link', href: `${fullPageModuleConfig.webUrl}/index` },
|
{ label: t('nav:example-full-page'), type: 'link', href: `${fullPageModuleConfig.webUrl}/index` },
|
||||||
|
|||||||
+19
-25
@@ -1,38 +1,32 @@
|
|||||||
import { EnterpriseIndexPageProvider, useEnterpriseModuleTranslationContext } from '@repo/ui/foundations';
|
import {
|
||||||
|
EnterpriseIndexPageProvider,
|
||||||
|
useEnterpriseModuleTranslationContext,
|
||||||
|
EnterpriseDataTable,
|
||||||
|
} from '@repo/ui/foundations';
|
||||||
|
import { ColDef } from '@repo/ui/components';
|
||||||
import { Trans } from '@repo/core-i18n';
|
import { Trans } from '@repo/core-i18n';
|
||||||
import { Badge, Text } from '@repo/ui/components';
|
import { Text } from '@repo/ui/components';
|
||||||
import { Activity, LayoutDashboard } from 'lucide-react';
|
import { LayoutDashboard } from 'lucide-react';
|
||||||
import { DataTable } from '../components/data-table';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
export default function FullPagePageIndex() {
|
export default function FullPagePageIndex() {
|
||||||
const { t } = useEnterpriseModuleTranslationContext();
|
const { t } = useEnterpriseModuleTranslationContext();
|
||||||
|
|
||||||
|
const columnDefs: ColDef<any>[] = useMemo(() => {
|
||||||
|
return [
|
||||||
|
{ field: 'code', headerName: t('fields.code'), minWidth: 150 },
|
||||||
|
{ field: 'name', headerName: t('fields.name'), minWidth: 150 },
|
||||||
|
];
|
||||||
|
}, [t]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EnterpriseIndexPageProvider
|
<EnterpriseIndexPageProvider
|
||||||
pageHeaderProps={{
|
pageHeaderProps={{
|
||||||
title: t('title'),
|
title: t('title'),
|
||||||
description: (
|
description: (
|
||||||
<Trans
|
<Trans t={t} i18nKey="description" components={{ 1: <Text span fw={500} c="var(--mantine-color-text)" /> }} />
|
||||||
t={t}
|
|
||||||
i18nKey="description"
|
|
||||||
components={{
|
|
||||||
1: <Text span fw={500} c="var(--mantine-color-text)" />,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
badges: (
|
|
||||||
<Badge
|
|
||||||
variant="light"
|
|
||||||
color="teal"
|
|
||||||
size="sm"
|
|
||||||
radius="sm"
|
|
||||||
fw={600}
|
|
||||||
leftSection={<Activity size={10} strokeWidth={3} />}
|
|
||||||
style={{ textTransform: 'capitalize' }}
|
|
||||||
>
|
|
||||||
Healthy
|
|
||||||
</Badge>
|
|
||||||
),
|
),
|
||||||
|
|
||||||
icon: LayoutDashboard,
|
icon: LayoutDashboard,
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{ label: t('nav:example-module'), type: 'text' },
|
{ label: t('nav:example-module'), type: 'text' },
|
||||||
@@ -40,7 +34,7 @@ export default function FullPagePageIndex() {
|
|||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DataTable />
|
<EnterpriseDataTable columnDefs={columnDefs} />
|
||||||
</EnterpriseIndexPageProvider>
|
</EnterpriseIndexPageProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import { FullPageEntity } from '../../domain/entities';
|
|||||||
export interface FullPageStoreState extends EnterpriseModuleState<FullPageEntity> {}
|
export interface FullPageStoreState extends EnterpriseModuleState<FullPageEntity> {}
|
||||||
|
|
||||||
export const fullPageStore = create<FullPageStoreState>((set) => ({
|
export const fullPageStore = create<FullPageStoreState>((set) => ({
|
||||||
metaData: null,
|
metaData: { limit: 15 },
|
||||||
setMetaData: (data) => set({ metaData: data }),
|
setMetaData: (data) => set({ metaData: data }),
|
||||||
|
|
||||||
filterData: { page: 1, limit: 10 },
|
filterData: {},
|
||||||
setFilterData: (data) => set({ filterData: data }),
|
setFilterData: (data) => set({ filterData: data }),
|
||||||
|
|
||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
setSelectedRows: (rows) => set({ selectedRows: rows }),
|
setSelectedRows: (rows) => set({ selectedRows: rows }),
|
||||||
|
|
||||||
privileges: [],
|
privileges: [],
|
||||||
setPrivileges: (privileges) => set({ privileges }),
|
setPrivileges: (privileges) => set({ privileges }),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ export interface NestJSPaginationMeta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface StandardPaginationMeta {
|
export interface StandardPaginationMeta {
|
||||||
page: number;
|
page?: number;
|
||||||
limit: number;
|
limit?: number;
|
||||||
total: number;
|
total?: number;
|
||||||
totalPages: number;
|
totalPages?: number;
|
||||||
|
countPerPage?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PaginatedResponse<T> {
|
export interface PaginatedResponse<T> {
|
||||||
@@ -21,7 +22,7 @@ export interface PaginatedResponse<T> {
|
|||||||
meta: StandardPaginationMeta;
|
meta: StandardPaginationMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function defaultTransformPaginationMeta(meta: any): StandardPaginationMeta {
|
export function defaultTransformPaginationMeta(meta: NestJSPaginationMeta): StandardPaginationMeta {
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
return { page: 1, limit: 10, total: 0, totalPages: 0 };
|
return { page: 1, limit: 10, total: 0, totalPages: 0 };
|
||||||
}
|
}
|
||||||
@@ -30,6 +31,7 @@ export function defaultTransformPaginationMeta(meta: any): StandardPaginationMet
|
|||||||
limit: meta.itemsPerPage ?? meta.limit ?? 10,
|
limit: meta.itemsPerPage ?? meta.limit ?? 10,
|
||||||
total: meta.totalItems ?? meta.total ?? 0,
|
total: meta.totalItems ?? meta.total ?? 0,
|
||||||
totalPages: meta.totalPages ?? 0,
|
totalPages: meta.totalPages ?? 0,
|
||||||
|
countPerPage: meta?.itemCount ?? 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,41 @@
|
|||||||
"system_menu": {
|
"system_menu": {
|
||||||
"history": "History",
|
"history": "History",
|
||||||
"bookmark": "Bookmark"
|
"bookmark": "Bookmark"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"id": "ID",
|
||||||
|
"code": "Code",
|
||||||
|
"name": "Name",
|
||||||
|
"description": "Description",
|
||||||
|
"number": "Number",
|
||||||
|
"status": "Status",
|
||||||
|
"type": "Type",
|
||||||
|
"category": "Category",
|
||||||
|
"action": "Action",
|
||||||
|
"createdAt": "Created At",
|
||||||
|
"updatedAt": "Updated At",
|
||||||
|
"createdBy": "Created By",
|
||||||
|
"updatedBy": "Updated By",
|
||||||
|
"deletedAt": "Deleted At",
|
||||||
|
"date": "Date",
|
||||||
|
"amount": "Amount",
|
||||||
|
"price": "Price",
|
||||||
|
"quantity": "Quantity",
|
||||||
|
"total": "Total",
|
||||||
|
"balance": "Balance",
|
||||||
|
"address": "Address",
|
||||||
|
"phone": "Phone Number",
|
||||||
|
"email": "Email",
|
||||||
|
"user": "User",
|
||||||
|
"role": "Role",
|
||||||
|
"notes": "Notes",
|
||||||
|
"isActive": "Active",
|
||||||
|
"isDefault": "Default",
|
||||||
|
"isRequired": "Required",
|
||||||
|
"startDate": "Start Date",
|
||||||
|
"endDate": "End Date",
|
||||||
|
"attachment": "Attachment",
|
||||||
|
"reference": "Reference"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,6 +113,41 @@
|
|||||||
"system_menu": {
|
"system_menu": {
|
||||||
"history": "Riwayat",
|
"history": "Riwayat",
|
||||||
"bookmark": "Bookmark"
|
"bookmark": "Bookmark"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"id": "ID",
|
||||||
|
"code": "Kode",
|
||||||
|
"name": "Nama",
|
||||||
|
"description": "Deskripsi",
|
||||||
|
"number": "Nomor",
|
||||||
|
"status": "Status",
|
||||||
|
"type": "Tipe",
|
||||||
|
"category": "Kategori",
|
||||||
|
"action": "Aksi",
|
||||||
|
"createdAt": "Tanggal Dibuat",
|
||||||
|
"updatedAt": "Tanggal Diperbarui",
|
||||||
|
"createdBy": "Dibuat Oleh",
|
||||||
|
"updatedBy": "Diperbarui Oleh",
|
||||||
|
"deletedAt": "Tanggal Dihapus",
|
||||||
|
"date": "Tanggal",
|
||||||
|
"amount": "Nominal",
|
||||||
|
"price": "Harga",
|
||||||
|
"quantity": "Kuantitas",
|
||||||
|
"total": "Total",
|
||||||
|
"balance": "Saldo",
|
||||||
|
"address": "Alamat",
|
||||||
|
"phone": "No. Telepon",
|
||||||
|
"email": "Email",
|
||||||
|
"user": "Pengguna",
|
||||||
|
"role": "Peran",
|
||||||
|
"notes": "Catatan",
|
||||||
|
"isActive": "Aktif",
|
||||||
|
"isDefault": "Bawaan",
|
||||||
|
"isRequired": "Wajib",
|
||||||
|
"startDate": "Tanggal Mulai",
|
||||||
|
"endDate": "Tanggal Selesai",
|
||||||
|
"attachment": "Lampiran",
|
||||||
|
"reference": "Referensi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { ModuleAction, ModuleActionType } from '../../../entities/entity';
|
||||||
|
import { useEnterpriseModuleTranslationContext } from '../../../hooks/use-module.context';
|
||||||
|
import { Trash2, CheckCircle, XCircle } from 'lucide-react';
|
||||||
|
import { PageActionProps } from '../../../../../components';
|
||||||
|
|
||||||
|
export interface UseBulkActionsProps {
|
||||||
|
selectedRows: any[];
|
||||||
|
onActionClick: (action: ModuleActionType, data: any[]) => void;
|
||||||
|
statusKey?: string;
|
||||||
|
customBulkActions?: (selectedRows: any[], defaultActions: PageActionProps[]) => PageActionProps[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useBulkActions({
|
||||||
|
selectedRows,
|
||||||
|
onActionClick,
|
||||||
|
statusKey = 'status',
|
||||||
|
customBulkActions,
|
||||||
|
}: UseBulkActionsProps) {
|
||||||
|
const { t } = useEnterpriseModuleTranslationContext();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!selectedRows || selectedRows.length === 0) return [];
|
||||||
|
|
||||||
|
const hasActive = selectedRows.some((row) => row[statusKey]?.toLowerCase() === 'active');
|
||||||
|
const hasInactive = selectedRows.some((row) => row[statusKey]?.toLowerCase() === 'inactive');
|
||||||
|
|
||||||
|
const defaultActions: PageActionProps[] = [];
|
||||||
|
|
||||||
|
if (hasActive) {
|
||||||
|
defaultActions.push({
|
||||||
|
key: ModuleAction.DEACTIVATE,
|
||||||
|
label: t('common:actions.deactivate'),
|
||||||
|
icon: <XCircle size={16} />,
|
||||||
|
variant: 'default',
|
||||||
|
onClick: () => onActionClick(ModuleAction.DEACTIVATE, selectedRows),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasInactive) {
|
||||||
|
defaultActions.push({
|
||||||
|
key: ModuleAction.ACTIVATE,
|
||||||
|
label: t('common:actions.activate'),
|
||||||
|
icon: <CheckCircle size={16} />,
|
||||||
|
variant: 'default',
|
||||||
|
onClick: () => onActionClick(ModuleAction.ACTIVATE, selectedRows),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultActions.push({
|
||||||
|
key: ModuleAction.DELETE,
|
||||||
|
label: t('common:actions.delete'),
|
||||||
|
icon: <Trash2 size={16} />,
|
||||||
|
variant: 'outline',
|
||||||
|
intent: 'destructive',
|
||||||
|
onClick: () => onActionClick(ModuleAction.DELETE, selectedRows),
|
||||||
|
});
|
||||||
|
|
||||||
|
return customBulkActions ? customBulkActions(selectedRows, defaultActions) : defaultActions;
|
||||||
|
}, [selectedRows, statusKey, t, onActionClick, customBulkActions]);
|
||||||
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { Menu, ActionIcon } from '@mantine/core';
|
||||||
|
import { MoreVertical, Eye, Trash2, CheckCircle, XCircle } from 'lucide-react';
|
||||||
|
import { ModuleAction, ModuleActionType } from '../../../entities/entity';
|
||||||
|
import { useEnterpriseModuleTranslationContext } from '../../../hooks/use-module.context';
|
||||||
|
|
||||||
|
export interface RowActionMenuProps {
|
||||||
|
data: any;
|
||||||
|
rowIndex: number;
|
||||||
|
onActionClick: (action: ModuleActionType, data: any) => void;
|
||||||
|
statusKey?: string;
|
||||||
|
customActions?: (data: any, defaultActions: any[]) => any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RowActionMenu({ data, onActionClick, statusKey = 'status', customActions }: RowActionMenuProps) {
|
||||||
|
const { t } = useEnterpriseModuleTranslationContext();
|
||||||
|
const status = data?.[statusKey]?.toLowerCase();
|
||||||
|
|
||||||
|
const defaultActions = useMemo(() => {
|
||||||
|
const actions: any[] = [];
|
||||||
|
|
||||||
|
// View Details
|
||||||
|
actions.push({
|
||||||
|
key: 'VIEW',
|
||||||
|
label: t('common:actions.detail'),
|
||||||
|
icon: <Eye size={14} />,
|
||||||
|
onClick: () => onActionClick('VIEW' as any, data),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Active/Inactive toggle
|
||||||
|
if (status === 'active') {
|
||||||
|
actions.push({
|
||||||
|
key: ModuleAction.DEACTIVATE,
|
||||||
|
label: t('common:actions.deactivate'),
|
||||||
|
icon: <XCircle size={14} />,
|
||||||
|
onClick: () => onActionClick(ModuleAction.DEACTIVATE, data),
|
||||||
|
});
|
||||||
|
} else if (status === 'inactive') {
|
||||||
|
actions.push({
|
||||||
|
key: ModuleAction.ACTIVATE,
|
||||||
|
label: t('common:actions.activate'),
|
||||||
|
icon: <CheckCircle size={14} />,
|
||||||
|
onClick: () => onActionClick(ModuleAction.ACTIVATE, data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
actions.push({
|
||||||
|
key: ModuleAction.DELETE,
|
||||||
|
label: t('common:actions.delete'),
|
||||||
|
icon: <Trash2 size={14} />,
|
||||||
|
color: 'red',
|
||||||
|
onClick: () => onActionClick(ModuleAction.DELETE, data),
|
||||||
|
});
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}, [status, t, onActionClick, data]);
|
||||||
|
|
||||||
|
const finalActions = customActions ? customActions(data, defaultActions) : defaultActions;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu position="bottom-end" withinPortal>
|
||||||
|
<Menu.Target>
|
||||||
|
<ActionIcon variant="subtle" color="gray">
|
||||||
|
<MoreVertical size={16} />
|
||||||
|
</ActionIcon>
|
||||||
|
</Menu.Target>
|
||||||
|
<Menu.Dropdown>
|
||||||
|
{finalActions.map((action, idx) => (
|
||||||
|
<Menu.Item key={action.key || idx} color={action.color} leftSection={action.icon} onClick={action.onClick}>
|
||||||
|
{action.label}
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu.Dropdown>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,14 +7,13 @@ import {
|
|||||||
IServerSideDatasource,
|
IServerSideDatasource,
|
||||||
IServerSideGetRowsParams,
|
IServerSideGetRowsParams,
|
||||||
SelectionChangedEvent,
|
SelectionChangedEvent,
|
||||||
GetContextMenuItemsParams,
|
|
||||||
MenuItemDef,
|
MenuItemDef,
|
||||||
DefaultMenuItem,
|
DefaultMenuItem,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import { Box } from '@mantine/core';
|
import { Box } from '@mantine/core';
|
||||||
|
|
||||||
import { DataGrid } from '../../../../components';
|
import { DataGrid, StatusBadge } from '../../../../components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useEnterpriseModuleDataServiceContext,
|
useEnterpriseModuleDataServiceContext,
|
||||||
@@ -86,7 +85,7 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
const { t } = useEnterpriseModuleTranslationContext();
|
const { t } = useEnterpriseModuleTranslationContext();
|
||||||
const { dataServices } = useEnterpriseModuleDataServiceContext<E>();
|
const { dataServices } = useEnterpriseModuleDataServiceContext<E>();
|
||||||
const { setSelectedRows, setFilterData, metaData, setMetaData } = useEnterpriseModuleSelectionContext<E>();
|
const { setSelectedRows, metaData, setMetaData } = useEnterpriseModuleSelectionContext<E>();
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Local UI State
|
// Local UI State
|
||||||
@@ -100,6 +99,7 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Determine the number of rows per page based on metadata, defaulting to 10
|
// Determine the number of rows per page based on metadata, defaulting to 10
|
||||||
const perPage = useMemo(() => {
|
const perPage = useMemo(() => {
|
||||||
|
console.log({ metaData });
|
||||||
return metaData?.limit ?? 10;
|
return metaData?.limit ?? 10;
|
||||||
}, [metaData]);
|
}, [metaData]);
|
||||||
|
|
||||||
@@ -108,8 +108,20 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
|||||||
|
|
||||||
// Ensure column definitions are referentially stable
|
// Ensure column definitions are referentially stable
|
||||||
const finalColumnDefs = useMemo<ColDef<E>[]>(() => {
|
const finalColumnDefs = useMemo<ColDef<E>[]>(() => {
|
||||||
return columnDefs;
|
const masterDetailColumn: ColDef<E> = { maxWidth: 50, sortable: false, cellRenderer: 'agGroupCellRenderer' };
|
||||||
}, [columnDefs]);
|
const statusColumn: ColDef<E> = {
|
||||||
|
maxWidth: 130,
|
||||||
|
field: 'status' as any,
|
||||||
|
headerName: t('common:fields.status'),
|
||||||
|
cellRenderer: ({ value }: any) => <StatusBadge status={value} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
const prefixColumn: ColDef<E>[] = [props.masterDetail ? masterDetailColumn : (null as any), statusColumn].filter(
|
||||||
|
Boolean,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [...prefixColumn, ...columnDefs];
|
||||||
|
}, [columnDefs, props.masterDetail]);
|
||||||
|
|
||||||
// Default configuration applied to all columns in the grid
|
// Default configuration applied to all columns in the grid
|
||||||
const defaultColDef = useMemo<ColDef>(() => ({ flex: 1, minWidth: 100, sortable: true, resizable: true }), []);
|
const defaultColDef = useMemo<ColDef>(() => ({ flex: 1, minWidth: 100, sortable: true, resizable: true }), []);
|
||||||
@@ -186,35 +198,45 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Configures the context menu items available when right-clicking a cell
|
// Configures the context menu items available when right-clicking a cell
|
||||||
const getContextMenuItems = useCallback(
|
const getContextMenuItems = useCallback(():
|
||||||
(
|
| (DefaultMenuItem | MenuItemDef)[]
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
| Promise<(DefaultMenuItem | MenuItemDef)[]> => {
|
||||||
params: GetContextMenuItemsParams,
|
return ['copy', 'copyWithHeaders'];
|
||||||
): (DefaultMenuItem | MenuItemDef)[] | Promise<(DefaultMenuItem | MenuItemDef)[]> => {
|
}, []);
|
||||||
return ['copy', 'copyWithHeaders'];
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const statusBar = useMemo<StatusBar | undefined>(() => {
|
const statusBar = useMemo<StatusBar | undefined>(() => {
|
||||||
if (!showStatusbar) return undefined;
|
if (!showStatusbar) return undefined;
|
||||||
return { statusPanels: [{ statusPanel: 'agSelectedRowCountComponent', align: 'left' }] };
|
return { statusPanels: [{ statusPanel: 'agSelectedRowCountComponent', align: 'left' }] };
|
||||||
}, [showStatusbar]);
|
}, [showStatusbar]);
|
||||||
|
|
||||||
|
const domLayout = useMemo(() => {
|
||||||
|
const meta = { total: metaData?.total ?? 0, limit: metaData?.limit ?? 0 };
|
||||||
|
if (!isPaginated) {
|
||||||
|
return meta?.total < meta?.limit ? 'autoHeight' : 'normal';
|
||||||
|
}
|
||||||
|
return 'autoHeight';
|
||||||
|
}, [metaData, isPaginated]);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Render
|
// Render
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
{/* GRID CONTAINER */}
|
{/* GRID CONTAINER */}
|
||||||
<Box style={{ height: gridHeight, width: '100%' }} className="erp-data-grid-container">
|
<Box
|
||||||
|
className="erp-data-grid-container"
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: domLayout === 'autoHeight' || restAgGridProps.domLayout === 'autoHeight' ? '100%' : gridHeight,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DataGrid<E>
|
<DataGrid<E>
|
||||||
rowModelType="serverSide"
|
rowModelType="serverSide"
|
||||||
getRowId={(v) => v.data.id as string}
|
getRowId={(v) => v.data.id as string}
|
||||||
cacheBlockSize={perPage}
|
cacheBlockSize={perPage}
|
||||||
pagination={isPaginated}
|
pagination={isPaginated}
|
||||||
paginationPageSize={isPaginated ? perPage : undefined}
|
paginationPageSize={isPaginated ? perPage : undefined}
|
||||||
paginationPageSizeSelector={isPaginated ? [10, 20, 50] : undefined}
|
paginationPageSizeSelector={isPaginated ? [10, 15, 20, 50] : undefined}
|
||||||
columnDefs={finalColumnDefs}
|
columnDefs={finalColumnDefs}
|
||||||
defaultColDef={defaultColDef}
|
defaultColDef={defaultColDef}
|
||||||
animateRows={true}
|
animateRows={true}
|
||||||
@@ -224,6 +246,7 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
|||||||
onGridReady={onGridReady}
|
onGridReady={onGridReady}
|
||||||
getContextMenuItems={getContextMenuItems}
|
getContextMenuItems={getContextMenuItems}
|
||||||
statusBar={statusBar}
|
statusBar={statusBar}
|
||||||
|
domLayout={domLayout}
|
||||||
overlayLoadingTemplate={`<span style="padding:10px">${loadingMessage}</span>`}
|
overlayLoadingTemplate={`<span style="padding:10px">${loadingMessage}</span>`}
|
||||||
overlayNoRowsTemplate={`<span style="padding:10px;color:var(--ag-foreground-color,#868e96)">${noRowsMessage}</span>`}
|
overlayNoRowsTemplate={`<span style="padding:10px;color:var(--ag-foreground-color,#868e96)">${noRowsMessage}</span>`}
|
||||||
{...restAgGridProps}
|
{...restAgGridProps}
|
||||||
|
|||||||
Reference in New Issue
Block a user