gbs-add-block 1.0.30 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/package.json +1 -1
- package/source/components/datagrid/context/GridContext.tsx +7 -5
- package/source/components/datagrid/createTemplate.tsx +82 -0
- package/source/components/datagrid/hooks/usePagination.ts +11 -1
- package/source/components/datagrid/type.ts +1 -1
- package/source/components/datagrid/hooks/usePageStatus.ts +0 -13
- package/source/components/datagridbeta/context/GridContext.tsx +0 -187
- package/source/components/datagridbeta/hooks/index.ts +0 -7
- package/source/components/datagridbeta/hooks/useColumns.ts +0 -33
- package/source/components/datagridbeta/hooks/useDataSource.ts +0 -54
- package/source/components/datagridbeta/hooks/useFiltering.ts +0 -135
- package/source/components/datagridbeta/hooks/usePageStatus.ts +0 -13
- package/source/components/datagridbeta/hooks/usePagination.ts +0 -125
- package/source/components/datagridbeta/hooks/useRowSelection.ts +0 -48
- package/source/components/datagridbeta/hooks/useSearch.ts +0 -86
- package/source/components/datagridbeta/index.tsx +0 -26
- package/source/components/datagridbeta/layout/EditableRow.tsx +0 -85
- package/source/components/datagridbeta/layout/FilterPopup.tsx +0 -85
- package/source/components/datagridbeta/layout/GridBody.tsx +0 -221
- package/source/components/datagridbeta/layout/GridPagination.tsx +0 -118
- package/source/components/datagridbeta/layout/GridToolbar.tsx +0 -108
- package/source/components/datagridbeta/layout/index.tsx +0 -68
- package/source/components/datagridbeta/type.ts +0 -183
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback, useEffect } from "react";
|
|
2
|
-
|
|
3
|
-
export const usePagination = (
|
|
4
|
-
totalPages: number,
|
|
5
|
-
lazy: boolean,
|
|
6
|
-
dataSource?: any[],
|
|
7
|
-
pageSettings?: { pageNumber: number }
|
|
8
|
-
) => {
|
|
9
|
-
const [currentPage, setCurrentPage] = useState(0);
|
|
10
|
-
const [pageStart, setPageStart] = useState(0);
|
|
11
|
-
const [pageEnd, setPageEnd] = useState(10);
|
|
12
|
-
const [prevDataLength, setPrevDataLength] = useState(0);
|
|
13
|
-
|
|
14
|
-
const updatePageRange = useCallback(
|
|
15
|
-
(page: number) => {
|
|
16
|
-
const start = Math.floor(page / 10) * 10;
|
|
17
|
-
setPageStart(start);
|
|
18
|
-
setPageEnd(Math.min(start + 10, totalPages));
|
|
19
|
-
},
|
|
20
|
-
[totalPages]
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (!lazy) {
|
|
25
|
-
setPageEnd(Math.min(10, totalPages));
|
|
26
|
-
} else {
|
|
27
|
-
setPageEnd(Math.min(pageStart + 10, totalPages));
|
|
28
|
-
}
|
|
29
|
-
}, [totalPages, lazy, pageStart]);
|
|
30
|
-
|
|
31
|
-
// This will handle the case when dataSource changes
|
|
32
|
-
// and adjust the current page accordingly
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
if (dataSource && prevDataLength > 0) {
|
|
35
|
-
const currentDataLength = dataSource.length;
|
|
36
|
-
|
|
37
|
-
if (currentDataLength > prevDataLength) {
|
|
38
|
-
const lastPage = totalPages - 1;
|
|
39
|
-
setCurrentPage(lastPage);
|
|
40
|
-
updatePageRange(lastPage);
|
|
41
|
-
} else if (currentDataLength < prevDataLength) {
|
|
42
|
-
const rowsPerPage = lazy ? 1 : pageSettings?.pageNumber || 10;
|
|
43
|
-
const startIndex = currentPage * rowsPerPage;
|
|
44
|
-
|
|
45
|
-
if (startIndex >= currentDataLength && currentPage > 0) {
|
|
46
|
-
const newPage = currentPage - 1;
|
|
47
|
-
setCurrentPage(newPage);
|
|
48
|
-
updatePageRange(newPage);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
setPrevDataLength(dataSource?.length || 0);
|
|
53
|
-
}, [
|
|
54
|
-
dataSource?.length,
|
|
55
|
-
totalPages,
|
|
56
|
-
updatePageRange,
|
|
57
|
-
prevDataLength,
|
|
58
|
-
currentPage,
|
|
59
|
-
lazy,
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
const nextPage = useCallback(() => {
|
|
63
|
-
setCurrentPage((prevPage) => {
|
|
64
|
-
if (prevPage < totalPages - 1) {
|
|
65
|
-
const newPage = prevPage + 1;
|
|
66
|
-
updatePageRange(newPage);
|
|
67
|
-
return newPage;
|
|
68
|
-
}
|
|
69
|
-
return prevPage;
|
|
70
|
-
});
|
|
71
|
-
}, [totalPages, updatePageRange]);
|
|
72
|
-
|
|
73
|
-
const prevPage = useCallback(() => {
|
|
74
|
-
setCurrentPage((prevPage) => {
|
|
75
|
-
if (prevPage > 0) {
|
|
76
|
-
const newPage = prevPage - 1;
|
|
77
|
-
updatePageRange(newPage);
|
|
78
|
-
return newPage;
|
|
79
|
-
}
|
|
80
|
-
return prevPage;
|
|
81
|
-
});
|
|
82
|
-
}, [updatePageRange]);
|
|
83
|
-
|
|
84
|
-
const goToEndPage = useCallback(() => {
|
|
85
|
-
const lastPage = totalPages - 1;
|
|
86
|
-
setCurrentPage(lastPage);
|
|
87
|
-
updatePageRange(lastPage);
|
|
88
|
-
}, [totalPages, updatePageRange]);
|
|
89
|
-
|
|
90
|
-
const goToFirstPage = useCallback(() => {
|
|
91
|
-
setCurrentPage(0);
|
|
92
|
-
updatePageRange(0);
|
|
93
|
-
}, [updatePageRange]);
|
|
94
|
-
|
|
95
|
-
const goToPage = useCallback(
|
|
96
|
-
(page: number) => {
|
|
97
|
-
setCurrentPage(page);
|
|
98
|
-
updatePageRange(page);
|
|
99
|
-
},
|
|
100
|
-
[updatePageRange]
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const resetPage = useCallback((dataSource: any, pageSettings: any) => {
|
|
104
|
-
const newTotalPages = Math.ceil(
|
|
105
|
-
dataSource.length / pageSettings.pageNumber
|
|
106
|
-
);
|
|
107
|
-
setCurrentPage(0);
|
|
108
|
-
setPageStart(0);
|
|
109
|
-
setPageEnd(Math.min(10, newTotalPages));
|
|
110
|
-
return newTotalPages;
|
|
111
|
-
}, []);
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
currentPage,
|
|
115
|
-
pageStart,
|
|
116
|
-
pageEnd,
|
|
117
|
-
nextPage,
|
|
118
|
-
prevPage,
|
|
119
|
-
goToEndPage,
|
|
120
|
-
goToFirstPage,
|
|
121
|
-
goToPage,
|
|
122
|
-
resetPage,
|
|
123
|
-
updatePageRange,
|
|
124
|
-
};
|
|
125
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback } from "react";
|
|
2
|
-
|
|
3
|
-
export const useRowSelection = (
|
|
4
|
-
workingDataSource: any[],
|
|
5
|
-
onSelectRow?: (rows: any[]) => void
|
|
6
|
-
) => {
|
|
7
|
-
const [selectedRows, setSelectedRows] = useState<any[]>([]);
|
|
8
|
-
|
|
9
|
-
const handleSelectAll = useCallback(
|
|
10
|
-
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
11
|
-
const selected = event.target.checked ? workingDataSource : [];
|
|
12
|
-
setSelectedRows(selected);
|
|
13
|
-
onSelectRow?.(selected);
|
|
14
|
-
},
|
|
15
|
-
[workingDataSource, onSelectRow]
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
const handleSelect = useCallback(
|
|
19
|
-
(rowData: any) => {
|
|
20
|
-
setSelectedRows((prevData) => {
|
|
21
|
-
const isSelected = prevData.includes(rowData);
|
|
22
|
-
let updatedData;
|
|
23
|
-
if (isSelected) {
|
|
24
|
-
updatedData = prevData.filter((item) => item !== rowData);
|
|
25
|
-
} else {
|
|
26
|
-
updatedData = [...prevData, rowData];
|
|
27
|
-
}
|
|
28
|
-
if (onSelectRow) onSelectRow(updatedData);
|
|
29
|
-
return updatedData;
|
|
30
|
-
});
|
|
31
|
-
},
|
|
32
|
-
[onSelectRow]
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
const isRowSelected = useCallback(
|
|
36
|
-
(rowData: any) => {
|
|
37
|
-
return selectedRows.includes(rowData);
|
|
38
|
-
},
|
|
39
|
-
[selectedRows]
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
selectedRows,
|
|
44
|
-
handleSelectAll,
|
|
45
|
-
handleSelect,
|
|
46
|
-
isRowSelected,
|
|
47
|
-
};
|
|
48
|
-
};
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback } from "react";
|
|
2
|
-
|
|
3
|
-
interface UseSearchProps {
|
|
4
|
-
workingDataSource: any[];
|
|
5
|
-
setWorkingDataSource: (data: any[]) => void;
|
|
6
|
-
fallbackSourceData: any[];
|
|
7
|
-
dataSource: any;
|
|
8
|
-
lazy: boolean;
|
|
9
|
-
pageSettings: any;
|
|
10
|
-
resetPage: (data: any[], settings: any) => number;
|
|
11
|
-
setTotalPages: (pages: number) => void;
|
|
12
|
-
searchParamValue?: (value: string) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const useSearch = ({
|
|
16
|
-
workingDataSource,
|
|
17
|
-
setWorkingDataSource,
|
|
18
|
-
fallbackSourceData,
|
|
19
|
-
dataSource,
|
|
20
|
-
lazy,
|
|
21
|
-
pageSettings,
|
|
22
|
-
resetPage,
|
|
23
|
-
setTotalPages,
|
|
24
|
-
searchParamValue,
|
|
25
|
-
}: UseSearchProps) => {
|
|
26
|
-
const [searchParam, setSearchParam] = useState("");
|
|
27
|
-
|
|
28
|
-
const handleSearchInput = useCallback(
|
|
29
|
-
(e: any) => {
|
|
30
|
-
const searchValue = e.target.value;
|
|
31
|
-
if (searchParamValue) searchParamValue(searchValue);
|
|
32
|
-
setSearchParam(searchValue);
|
|
33
|
-
|
|
34
|
-
if (searchValue === "") {
|
|
35
|
-
if (!lazy) {
|
|
36
|
-
const fallback =
|
|
37
|
-
fallbackSourceData.length > 0 ? fallbackSourceData : dataSource;
|
|
38
|
-
setWorkingDataSource(fallback);
|
|
39
|
-
const totalPages = resetPage(fallback, pageSettings);
|
|
40
|
-
setTotalPages(totalPages);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
[
|
|
45
|
-
searchParamValue,
|
|
46
|
-
lazy,
|
|
47
|
-
fallbackSourceData,
|
|
48
|
-
dataSource,
|
|
49
|
-
setWorkingDataSource,
|
|
50
|
-
resetPage,
|
|
51
|
-
pageSettings,
|
|
52
|
-
setTotalPages,
|
|
53
|
-
]
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const handleSearch = useCallback(
|
|
57
|
-
(searchParam: string) => {
|
|
58
|
-
if (!lazy) {
|
|
59
|
-
const filteredData = workingDataSource.filter((item: any) =>
|
|
60
|
-
Object.values(item).some((val: any) => {
|
|
61
|
-
const trimmedVal = val.toString().toLowerCase().trim();
|
|
62
|
-
const trimmedSearchParam = searchParam.toLowerCase().trim();
|
|
63
|
-
return trimmedVal.includes(trimmedSearchParam);
|
|
64
|
-
})
|
|
65
|
-
);
|
|
66
|
-
setWorkingDataSource(filteredData);
|
|
67
|
-
const totalPages = resetPage(filteredData, pageSettings);
|
|
68
|
-
setTotalPages(totalPages);
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
[
|
|
72
|
-
lazy,
|
|
73
|
-
workingDataSource,
|
|
74
|
-
setWorkingDataSource,
|
|
75
|
-
resetPage,
|
|
76
|
-
pageSettings,
|
|
77
|
-
setTotalPages,
|
|
78
|
-
]
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
searchParam,
|
|
83
|
-
handleSearchInput,
|
|
84
|
-
handleSearch,
|
|
85
|
-
};
|
|
86
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Grampro Business Services and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
* Here We Will Re-Render Grid as a Memoized Component For Better Performance.
|
|
7
|
-
* Extended Documentation for Grid can be found at
|
|
8
|
-
* https://psychedelic-step-e70.notion.site/Data-GRID-by-GBS-R-D-20ff97c899d24bc590215a6196435fa3
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { GridMemoised as GridComponent } from "./layout";
|
|
12
|
-
import { memo } from "react";
|
|
13
|
-
|
|
14
|
-
const DataGrid = memo(GridComponent, (prevProps, nextProps) => {
|
|
15
|
-
// Custom comparison function
|
|
16
|
-
return (
|
|
17
|
-
prevProps.dataSource === nextProps.dataSource &&
|
|
18
|
-
prevProps.columns === nextProps.columns &&
|
|
19
|
-
prevProps.pageSettings.pageNumber === nextProps.pageSettings.pageNumber &&
|
|
20
|
-
prevProps.enableSearch === nextProps.enableSearch &&
|
|
21
|
-
prevProps.enablePdfExport === nextProps.enablePdfExport &&
|
|
22
|
-
prevProps.enableExcelExport === nextProps.enableExcelExport
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
export { DataGrid };
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
interface EditableRowProps {
|
|
4
|
-
columnType: string | undefined;
|
|
5
|
-
cellValue: any;
|
|
6
|
-
rowIndex: number;
|
|
7
|
-
field: string;
|
|
8
|
-
style?: React.CSSProperties;
|
|
9
|
-
rowData: any;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default function EditableRow({
|
|
13
|
-
columnType,
|
|
14
|
-
cellValue,
|
|
15
|
-
rowIndex,
|
|
16
|
-
field,
|
|
17
|
-
style,
|
|
18
|
-
rowData,
|
|
19
|
-
}: EditableRowProps) {
|
|
20
|
-
// Function to handle cell value change
|
|
21
|
-
const handleCellChange = (newValue: any, field: string) => {
|
|
22
|
-
if (rowData) {
|
|
23
|
-
rowData[field] = newValue;
|
|
24
|
-
rowData(rowData);
|
|
25
|
-
console.log(rowData);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
switch (columnType) {
|
|
30
|
-
case "text":
|
|
31
|
-
return (
|
|
32
|
-
<input
|
|
33
|
-
key={`${field}-${rowIndex}`}
|
|
34
|
-
id={`${field}-${rowIndex}`}
|
|
35
|
-
type="text"
|
|
36
|
-
defaultValue={cellValue || ""}
|
|
37
|
-
onBlur={(e) => handleCellChange(e.target.value, field)}
|
|
38
|
-
onKeyDown={(e) => {
|
|
39
|
-
if (e.key === "Enter") {
|
|
40
|
-
e.currentTarget.blur();
|
|
41
|
-
}
|
|
42
|
-
}}
|
|
43
|
-
className="px-2 py-1 outline-none focus:ring-1 focus:ring-black rounded"
|
|
44
|
-
style={style}
|
|
45
|
-
/>
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
case "number":
|
|
49
|
-
return (
|
|
50
|
-
<input
|
|
51
|
-
key={`${field}-${rowIndex}`}
|
|
52
|
-
id={`${field}-${rowIndex}`}
|
|
53
|
-
type="number"
|
|
54
|
-
defaultValue={cellValue || ""}
|
|
55
|
-
onBlur={(e) => handleCellChange(e.target.value, field)}
|
|
56
|
-
onKeyDown={(e) => {
|
|
57
|
-
if (e.key === "Enter") {
|
|
58
|
-
e.currentTarget.blur();
|
|
59
|
-
}
|
|
60
|
-
}}
|
|
61
|
-
className="px-2 py-1 outline-none focus:ring-1 focus:ring-black rounded"
|
|
62
|
-
style={style}
|
|
63
|
-
/>
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
default:
|
|
67
|
-
return (
|
|
68
|
-
<input
|
|
69
|
-
type="text"
|
|
70
|
-
defaultValue={cellValue || ""}
|
|
71
|
-
onBlur={(e) => handleCellChange(e.target.value, field)}
|
|
72
|
-
onKeyDown={(e) => {
|
|
73
|
-
if (e.key === "Enter") {
|
|
74
|
-
e.currentTarget.blur();
|
|
75
|
-
}
|
|
76
|
-
}}
|
|
77
|
-
style={{
|
|
78
|
-
width: "100%",
|
|
79
|
-
border: "none",
|
|
80
|
-
background: "transparent",
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
|
|
4
|
-
export default function FilterPopup({ show, columnHeader, filterAction }: any) {
|
|
5
|
-
const [filterValue, setFilterValue] = useState("");
|
|
6
|
-
const [filterType, setFilterType] = useState("contains");
|
|
7
|
-
const [isFilterActive, setIsFilterActive] = useState(false);
|
|
8
|
-
|
|
9
|
-
const handleFilterInput = (e: any) => {
|
|
10
|
-
const filterKeyword = e.target.value;
|
|
11
|
-
setFilterValue(filterKeyword);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const onCancel = () => {
|
|
15
|
-
filterAction({ type: "cancel" });
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const applyFilter = () => {
|
|
19
|
-
filterAction({
|
|
20
|
-
type: "applyFilter",
|
|
21
|
-
filterValue,
|
|
22
|
-
filterType,
|
|
23
|
-
columnHeader,
|
|
24
|
-
});
|
|
25
|
-
show = false;
|
|
26
|
-
setIsFilterActive(true);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const clearFilter = () => {
|
|
30
|
-
setIsFilterActive(false);
|
|
31
|
-
filterAction({ type: "clearFilter", columnHeader });
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
show && (
|
|
36
|
-
<div
|
|
37
|
-
className="absolute bg-gray-100 p-2 text-xs z-50 mt-48 flex flex-col shadow-lg gap-2 rounded-md dark:bg-zinc-700"
|
|
38
|
-
role="dialog"
|
|
39
|
-
>
|
|
40
|
-
<select
|
|
41
|
-
name={`${columnHeader}-filter`}
|
|
42
|
-
id={`${columnHeader}-filter-id`}
|
|
43
|
-
className="w-full p-2 rounded-lg bg-gray-200 outline-none dark:bg-gray-600"
|
|
44
|
-
value={filterType}
|
|
45
|
-
onChange={(e: any) => {
|
|
46
|
-
setFilterType(e.target.value);
|
|
47
|
-
}}
|
|
48
|
-
>
|
|
49
|
-
<option value="contains">Contains</option>
|
|
50
|
-
<option value="starts_with">Starts With</option>
|
|
51
|
-
<option value="ends_with">Ends With</option>
|
|
52
|
-
</select>
|
|
53
|
-
<input
|
|
54
|
-
type="text"
|
|
55
|
-
placeholder="Enter filter value"
|
|
56
|
-
className="rounded-lg p-2 text-xs bg-gray-200 outline-none dark:bg-gray-600"
|
|
57
|
-
value={filterValue}
|
|
58
|
-
onInput={handleFilterInput}
|
|
59
|
-
/>
|
|
60
|
-
<div className="mt-2 flex space-x-1">
|
|
61
|
-
<button
|
|
62
|
-
className="text-xs bg-red-600 text-white px-2 py-0.5 rounded-lg hover:bg-red-600"
|
|
63
|
-
onClick={onCancel}
|
|
64
|
-
>
|
|
65
|
-
Cancel
|
|
66
|
-
</button>
|
|
67
|
-
{isFilterActive && (
|
|
68
|
-
<button
|
|
69
|
-
className="text-xs bg-black text-white px-2 py-0.5 rounded-lg dark:bg-white dark:text-black"
|
|
70
|
-
onClick={clearFilter}
|
|
71
|
-
>
|
|
72
|
-
Clear Filter
|
|
73
|
-
</button>
|
|
74
|
-
)}
|
|
75
|
-
<button
|
|
76
|
-
className="text-xs bg-black text-white px-2 py-0.5 rounded-lg dark:bg-white dark:text-black"
|
|
77
|
-
onClick={applyFilter}
|
|
78
|
-
>
|
|
79
|
-
Apply Filter
|
|
80
|
-
</button>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
)
|
|
84
|
-
);
|
|
85
|
-
}
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useGridContext } from "../context/GridContext";
|
|
3
|
-
import FilterPopup from "./FilterPopup";
|
|
4
|
-
import Icon from "../../icon/Icon";
|
|
5
|
-
import { listFilter, squarePen, trash } from "../../icon/iconPaths";
|
|
6
|
-
import { Column } from "../type";
|
|
7
|
-
import EditableRow from "./EditableRow";
|
|
8
|
-
|
|
9
|
-
const GridBody = () => {
|
|
10
|
-
const {
|
|
11
|
-
workingDataSource,
|
|
12
|
-
workingColumns,
|
|
13
|
-
isFetching,
|
|
14
|
-
currentPage,
|
|
15
|
-
pageSettings,
|
|
16
|
-
tableHeaderStyle,
|
|
17
|
-
gridColumnStyle,
|
|
18
|
-
gridColumnStyleSelectAll,
|
|
19
|
-
rowChange,
|
|
20
|
-
lazy,
|
|
21
|
-
activeFilterArray,
|
|
22
|
-
toggleFilterPopup,
|
|
23
|
-
handleFilterAction,
|
|
24
|
-
selectAll,
|
|
25
|
-
handleSelectAll,
|
|
26
|
-
handleSelect,
|
|
27
|
-
isRowSelected,
|
|
28
|
-
} = useGridContext();
|
|
29
|
-
|
|
30
|
-
const renderCell = (rowData: any, column: Column, rowIndex: number) => {
|
|
31
|
-
const cellValue = rowData[column.field];
|
|
32
|
-
const globalRowIndex = rowIndex + currentPage * pageSettings.pageNumber;
|
|
33
|
-
|
|
34
|
-
if (column.template && !column.editable) {
|
|
35
|
-
const TemplateComponent = column.template;
|
|
36
|
-
return (
|
|
37
|
-
<TemplateComponent
|
|
38
|
-
rowData={rowData}
|
|
39
|
-
rowIndex={globalRowIndex}
|
|
40
|
-
rowChange={(changes) => rowChange?.(changes)}
|
|
41
|
-
/>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (column.tooltip && !column.editable) {
|
|
46
|
-
return (
|
|
47
|
-
<span title={cellValue?.toString()}>
|
|
48
|
-
{cellValue && cellValue.length > 10
|
|
49
|
-
? `${cellValue.slice(0, 10)}...`
|
|
50
|
-
: cellValue}
|
|
51
|
-
</span>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (column.editable && !column.template) {
|
|
56
|
-
return (
|
|
57
|
-
<EditableRow
|
|
58
|
-
columnType={column.type ? column.type : undefined}
|
|
59
|
-
cellValue={cellValue}
|
|
60
|
-
rowIndex={globalRowIndex}
|
|
61
|
-
field={column.field}
|
|
62
|
-
style={{ width: column.width ? `${column.width}px` : "auto" }}
|
|
63
|
-
rowData={rowData}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return cellValue;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const displayStart = currentPage * pageSettings.pageNumber;
|
|
72
|
-
const displayEnd = displayStart + pageSettings.pageNumber;
|
|
73
|
-
const displayData = lazy
|
|
74
|
-
? workingDataSource
|
|
75
|
-
: workingDataSource.slice(displayStart, displayEnd);
|
|
76
|
-
|
|
77
|
-
const isEditablePresent = workingColumns.some(
|
|
78
|
-
(column) => column.editable || column.template
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<div className="overflow-x-auto">
|
|
83
|
-
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
84
|
-
<thead>
|
|
85
|
-
<tr>
|
|
86
|
-
{selectAll && (
|
|
87
|
-
<th
|
|
88
|
-
className={tableHeaderStyle}
|
|
89
|
-
style={{ width: "2px", paddingLeft: "16px" }}
|
|
90
|
-
>
|
|
91
|
-
<input
|
|
92
|
-
type="checkbox"
|
|
93
|
-
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
94
|
-
handleSelectAll(event);
|
|
95
|
-
}}
|
|
96
|
-
className="form-checkbox h-5 w-5"
|
|
97
|
-
/>
|
|
98
|
-
</th>
|
|
99
|
-
)}
|
|
100
|
-
{workingColumns.map((column, colIndex) => (
|
|
101
|
-
<th
|
|
102
|
-
key={colIndex}
|
|
103
|
-
className={tableHeaderStyle}
|
|
104
|
-
style={{ width: column.width ? `${column.width}px` : "auto" }}
|
|
105
|
-
>
|
|
106
|
-
<div className="flex items-center relative">
|
|
107
|
-
{column.headerText || column.field}
|
|
108
|
-
{column.filter && !column.template && (
|
|
109
|
-
<>
|
|
110
|
-
<button onClick={() => toggleFilterPopup(colIndex)}>
|
|
111
|
-
<Icon
|
|
112
|
-
dimensions={{ width: "12", height: "12" }}
|
|
113
|
-
elements={listFilter}
|
|
114
|
-
svgClass={`ml-2 fill-none ${
|
|
115
|
-
activeFilterArray.some(
|
|
116
|
-
(filter) => filter.filterColumn === column.field
|
|
117
|
-
)
|
|
118
|
-
? "stroke-red-400 dark:stroke-red-400"
|
|
119
|
-
: "stroke-black dark:stroke-white"
|
|
120
|
-
}`}
|
|
121
|
-
/>
|
|
122
|
-
</button>
|
|
123
|
-
<FilterPopup
|
|
124
|
-
show={column.showFilterPopup ?? false}
|
|
125
|
-
columnHeader={column.field}
|
|
126
|
-
filterAction={(action: any) =>
|
|
127
|
-
handleFilterAction(action, colIndex)
|
|
128
|
-
}
|
|
129
|
-
/>
|
|
130
|
-
</>
|
|
131
|
-
)}
|
|
132
|
-
</div>
|
|
133
|
-
</th>
|
|
134
|
-
))}
|
|
135
|
-
{isEditablePresent && <th className={tableHeaderStyle}>Action</th>}
|
|
136
|
-
</tr>
|
|
137
|
-
</thead>
|
|
138
|
-
<tbody>
|
|
139
|
-
{isFetching ? (
|
|
140
|
-
<tr>
|
|
141
|
-
<td colSpan={workingColumns.length + (selectAll ? 1 : 0)}>
|
|
142
|
-
Loading...
|
|
143
|
-
</td>
|
|
144
|
-
</tr>
|
|
145
|
-
) : displayData.length === 0 ? (
|
|
146
|
-
<tr>
|
|
147
|
-
<td
|
|
148
|
-
colSpan={workingColumns.length + (selectAll ? 1 : 0)}
|
|
149
|
-
className="text-center py-3"
|
|
150
|
-
>
|
|
151
|
-
No data found
|
|
152
|
-
</td>
|
|
153
|
-
</tr>
|
|
154
|
-
) : (
|
|
155
|
-
displayData.map((rowData, rowIndex) => (
|
|
156
|
-
<tr
|
|
157
|
-
key={rowIndex}
|
|
158
|
-
className={
|
|
159
|
-
isRowSelected(rowData)
|
|
160
|
-
? "bg-blue-100 dark:bg-blue-900"
|
|
161
|
-
: rowIndex % 2 === 0
|
|
162
|
-
? "bg-gray-50 dark:bg-zinc-800 cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-700"
|
|
163
|
-
: "bg-white dark:bg-zinc-900 cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-700"
|
|
164
|
-
}
|
|
165
|
-
onClick={() => rowChange(rowData)}
|
|
166
|
-
>
|
|
167
|
-
{selectAll && (
|
|
168
|
-
<td className={gridColumnStyleSelectAll}>
|
|
169
|
-
<input
|
|
170
|
-
type="checkbox"
|
|
171
|
-
checked={isRowSelected(rowData)}
|
|
172
|
-
onChange={() => handleSelect(rowData)}
|
|
173
|
-
className="form-checkbox h-5 w-5"
|
|
174
|
-
/>
|
|
175
|
-
</td>
|
|
176
|
-
)}
|
|
177
|
-
{workingColumns.map((column, colIndex) => (
|
|
178
|
-
<td
|
|
179
|
-
key={colIndex}
|
|
180
|
-
className={gridColumnStyle}
|
|
181
|
-
style={{
|
|
182
|
-
width: column.width ? `${column.width}px` : "auto",
|
|
183
|
-
maxWidth: column.width ? `${column.width}px` : "auto",
|
|
184
|
-
}}
|
|
185
|
-
>
|
|
186
|
-
{renderCell(rowData, column, rowIndex)}
|
|
187
|
-
</td>
|
|
188
|
-
))}
|
|
189
|
-
{isEditablePresent && (
|
|
190
|
-
<td style={{ width: "16px", padding: "4px" }}>
|
|
191
|
-
<div className="flex justify-start items-start px-2 gap-3">
|
|
192
|
-
<button
|
|
193
|
-
className="cursor-pointer"
|
|
194
|
-
onClick={() => console.log(rowData)}
|
|
195
|
-
>
|
|
196
|
-
<Icon
|
|
197
|
-
dimensions={{ width: "16", height: "16" }}
|
|
198
|
-
elements={squarePen}
|
|
199
|
-
svgClass="fill-none stroke-black dark:stroke-white"
|
|
200
|
-
/>
|
|
201
|
-
</button>
|
|
202
|
-
<button className="cursor-pointer">
|
|
203
|
-
<Icon
|
|
204
|
-
dimensions={{ width: "16", height: "16" }}
|
|
205
|
-
elements={trash}
|
|
206
|
-
svgClass="fill-none stroke-red-500 dark:stroke-red-500"
|
|
207
|
-
/>
|
|
208
|
-
</button>
|
|
209
|
-
</div>
|
|
210
|
-
</td>
|
|
211
|
-
)}
|
|
212
|
-
</tr>
|
|
213
|
-
))
|
|
214
|
-
)}
|
|
215
|
-
</tbody>
|
|
216
|
-
</table>
|
|
217
|
-
</div>
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export default GridBody;
|