gbs-add-block 1.0.12 → 1.0.13
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 +4 -4
- package/package.json +1 -1
- package/source/components/datagrid/context/GridContext.tsx +1 -1
- package/source/components/datagrid/hooks/usePagination.ts +38 -1
- package/source/components/grid/FilterPopup.tsx +0 -85
- package/source/components/grid/Grid.tsx +0 -653
- package/source/components/grid/GridHelperFunctions.ts +0 -218
- package/source/components/grid/index.tsx +0 -26
- package/source/components/grid/type.ts +0 -30
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# GBS Building Blocks 2.0 (v1.0.
|
|
1
|
+
# GBS Building Blocks 2.0 (v1.0.13)
|
|
2
2
|
|
|
3
3
|
Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@ Latest and upgraded version of GBS building blocks with headless UI and removed
|
|
|
6
6
|
|
|
7
7
|
For detailed documentation on usage and props, Please visit: [Building Block Documentation v2.0](https://blackmax-designs.gitbook.io/building-block-v2.0)
|
|
8
8
|
|
|
9
|
-
## What's New 🎉 (Ver 1.0.
|
|
9
|
+
## What's New 🎉 (Ver 1.0.13)
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
11
|
+
- Data Grid Enhancement
|
|
12
|
+
- End of Support for Grid Component
|
|
13
13
|
|
|
14
14
|
## Authors
|
|
15
15
|
|
package/package.json
CHANGED
|
@@ -70,7 +70,7 @@ export const GridProvider: React.FC<{
|
|
|
70
70
|
goToFirstPage,
|
|
71
71
|
goToPage,
|
|
72
72
|
resetPage,
|
|
73
|
-
} = usePagination(totalPages, lazy);
|
|
73
|
+
} = usePagination(totalPages, lazy, workingDataSource, pageSettings);
|
|
74
74
|
|
|
75
75
|
// Search functionality
|
|
76
76
|
const { searchParam, handleSearchInput, handleSearch } = useSearch({
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect } from "react";
|
|
2
2
|
|
|
3
|
-
export const usePagination = (
|
|
3
|
+
export const usePagination = (
|
|
4
|
+
totalPages: number,
|
|
5
|
+
lazy: boolean,
|
|
6
|
+
dataSource?: any[],
|
|
7
|
+
pageSettings?: { pageNumber: number }
|
|
8
|
+
) => {
|
|
4
9
|
const [currentPage, setCurrentPage] = useState(0);
|
|
5
10
|
const [pageStart, setPageStart] = useState(0);
|
|
6
11
|
const [pageEnd, setPageEnd] = useState(10);
|
|
12
|
+
const [prevDataLength, setPrevDataLength] = useState(0);
|
|
7
13
|
|
|
8
14
|
const updatePageRange = useCallback(
|
|
9
15
|
(page: number) => {
|
|
@@ -22,6 +28,37 @@ export const usePagination = (totalPages: number, lazy: boolean) => {
|
|
|
22
28
|
}
|
|
23
29
|
}, [totalPages, lazy, pageStart]);
|
|
24
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
|
+
|
|
25
62
|
const nextPage = useCallback(() => {
|
|
26
63
|
setCurrentPage((prevPage) => {
|
|
27
64
|
if (prevPage < totalPages - 1) {
|
|
@@ -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 border z-50 mt-48 flex items-end flex-col shadow-lg gap-2 rounded-md dark:bg-gray-700"
|
|
38
|
-
role="dialog"
|
|
39
|
-
>
|
|
40
|
-
<select
|
|
41
|
-
name={`${columnHeader}-filter`}
|
|
42
|
-
id={`${columnHeader}-filter-id`}
|
|
43
|
-
className="w-full p-2 rounded-lg 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-sm dark:bg-gray-600"
|
|
57
|
-
value={filterValue}
|
|
58
|
-
onInput={handleFilterInput}
|
|
59
|
-
/>
|
|
60
|
-
<div className="mt-2">
|
|
61
|
-
<button
|
|
62
|
-
className="text-xs bg-red-600 text-white p-1 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 p-1 rounded-lg dark:bg-white dark:text-white"
|
|
70
|
-
onClick={clearFilter}
|
|
71
|
-
>
|
|
72
|
-
Clear Filter
|
|
73
|
-
</button>
|
|
74
|
-
)}
|
|
75
|
-
<button
|
|
76
|
-
className="text-xs bg-black text-white p-1 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,653 +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
|
-
* Extended Documentation for Grid can be found at
|
|
7
|
-
* https://psychedelic-step-e70.notion.site/Data-GRID-by-GBS-R-D-20ff97c899d24bc590215a6196435fa3
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import React, {
|
|
11
|
-
forwardRef,
|
|
12
|
-
useCallback,
|
|
13
|
-
useEffect,
|
|
14
|
-
useImperativeHandle,
|
|
15
|
-
useState,
|
|
16
|
-
} from "react";
|
|
17
|
-
import FilterPopup from "./FilterPopup";
|
|
18
|
-
import {
|
|
19
|
-
clearFilterHelper,
|
|
20
|
-
exportToExcelHelper,
|
|
21
|
-
exportToPDFHelper,
|
|
22
|
-
} from "./GridHelperFunctions";
|
|
23
|
-
import { handleApplyFilterHelper } from "./GridHelperFunctions";
|
|
24
|
-
import Icon from "../icon/Icon";
|
|
25
|
-
import {
|
|
26
|
-
leftArrows,
|
|
27
|
-
leftArrow,
|
|
28
|
-
rightArrow,
|
|
29
|
-
rightArrows,
|
|
30
|
-
search,
|
|
31
|
-
listFilter,
|
|
32
|
-
} from "../icon/iconPaths";
|
|
33
|
-
import type { GridProps } from "./type";
|
|
34
|
-
import { getSourceData } from "../utils";
|
|
35
|
-
|
|
36
|
-
export const GridMemoised = forwardRef((props: GridProps, ref) => {
|
|
37
|
-
const {
|
|
38
|
-
dataSource,
|
|
39
|
-
columns = [],
|
|
40
|
-
pageSettings,
|
|
41
|
-
enableSearch = false,
|
|
42
|
-
lazy = false,
|
|
43
|
-
enableExcelExport = false,
|
|
44
|
-
excelName = "data",
|
|
45
|
-
enablePdfExport = false,
|
|
46
|
-
pdfName = "data",
|
|
47
|
-
pdfOptions = {},
|
|
48
|
-
gridButtonClass = "px-1 py-2 bg-white border rounded-lg text-xs text-black dark:bg-black dark:text-white",
|
|
49
|
-
selectAll = false,
|
|
50
|
-
onSelectRow,
|
|
51
|
-
isFetching,
|
|
52
|
-
tableHeaderStyle = "text-left border-b border-t bg-gray-50 px-2 py-4 dark:bg-gray-700 dark:text-white",
|
|
53
|
-
gridContainerClass = "flex flex-col min-w-screen border rounded-md overflow-hidden dark:bg-black",
|
|
54
|
-
gridColumnStyleSelectAll = "border-b px-4 text-sm dark:text-white",
|
|
55
|
-
gridColumnStyle = "border-b p-2 text-sm dark:text-white",
|
|
56
|
-
rowChange = () => {},
|
|
57
|
-
pageStatus = () => {},
|
|
58
|
-
} = props;
|
|
59
|
-
|
|
60
|
-
// States Handling Grid
|
|
61
|
-
const [workingDataSource, setWorkingDataSource] = useState<any>([]);
|
|
62
|
-
const [fallbackSourceData, setFallbackSourceData] = useState([]);
|
|
63
|
-
const [workingColumns, setWorkingColumns] = useState<any>([]);
|
|
64
|
-
const [currentPage, setCurrentPage] = useState(0);
|
|
65
|
-
const [pageStart, setPageStart] = useState(0);
|
|
66
|
-
const [pageEnd, setPageEnd] = useState(10);
|
|
67
|
-
const [totalPages, setTotalPages] = useState(0);
|
|
68
|
-
const [searchParam, setSearchParam] = useState("");
|
|
69
|
-
const [activeFilterArray, setActiveFilterArray] = useState<any>([]);
|
|
70
|
-
const [selectedRows, setSelectedRows] = useState<any[]>([]);
|
|
71
|
-
|
|
72
|
-
// This will returns the Page Navigation Status of Grid
|
|
73
|
-
// Such as totalPages in the grid, currentpage, etc..
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
if (pageStatus) {
|
|
76
|
-
pageStatus({ currentPage: currentPage, totalPages: totalPages });
|
|
77
|
-
}
|
|
78
|
-
}, [pageStatus, currentPage, totalPages]);
|
|
79
|
-
|
|
80
|
-
// Function to handle API datasource
|
|
81
|
-
const getGridData = useCallback(async () => {
|
|
82
|
-
try {
|
|
83
|
-
const sourceData = await getSourceData(dataSource);
|
|
84
|
-
const gridData = sourceData.sourcedata;
|
|
85
|
-
setFallbackSourceData(gridData);
|
|
86
|
-
setWorkingDataSource(gridData);
|
|
87
|
-
const totalPages = Math.ceil(gridData.length / pageSettings.pageNumber);
|
|
88
|
-
setTotalPages(totalPages);
|
|
89
|
-
setPageEnd(Math.min(10, totalPages));
|
|
90
|
-
} catch (error) {
|
|
91
|
-
console.error("Error fetching grid source data:", error);
|
|
92
|
-
}
|
|
93
|
-
}, [dataSource, pageSettings.pageNumber]);
|
|
94
|
-
|
|
95
|
-
// Calculates total pages and determine dataSource type
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
const handleDataSource = async () => {
|
|
98
|
-
if (Array.isArray(dataSource) && dataSource.length > 0) {
|
|
99
|
-
setWorkingDataSource(dataSource);
|
|
100
|
-
const totalPages = Math.ceil(
|
|
101
|
-
dataSource.length / pageSettings.pageNumber
|
|
102
|
-
);
|
|
103
|
-
setTotalPages(totalPages);
|
|
104
|
-
setPageEnd(Math.min(10, totalPages));
|
|
105
|
-
} else if (typeof dataSource === "string") {
|
|
106
|
-
await getGridData();
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
handleDataSource();
|
|
111
|
-
}, [dataSource, pageSettings]);
|
|
112
|
-
|
|
113
|
-
// Adds Filter Column
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (columns && columns.length > 0) {
|
|
116
|
-
const filteredColumns = columns.map((column) => ({
|
|
117
|
-
...column,
|
|
118
|
-
showFilterPopup: false,
|
|
119
|
-
isFilterActive: false,
|
|
120
|
-
}));
|
|
121
|
-
setWorkingColumns(filteredColumns);
|
|
122
|
-
}
|
|
123
|
-
}, [columns]);
|
|
124
|
-
|
|
125
|
-
useEffect(() => {
|
|
126
|
-
if (!columns || columns.length === 0) {
|
|
127
|
-
if (
|
|
128
|
-
workingDataSource.length > 0 &&
|
|
129
|
-
Object.keys(workingDataSource[0]).length > 0
|
|
130
|
-
) {
|
|
131
|
-
const inferredColumns = Object.keys(workingDataSource[0]).map(
|
|
132
|
-
(key) => ({
|
|
133
|
-
field: key,
|
|
134
|
-
headerText: key.charAt(0).toUpperCase() + key.slice(1),
|
|
135
|
-
width: 150,
|
|
136
|
-
})
|
|
137
|
-
);
|
|
138
|
-
setWorkingColumns((prevColumns: any) => {
|
|
139
|
-
if (JSON.stringify(prevColumns) !== JSON.stringify(inferredColumns)) {
|
|
140
|
-
return inferredColumns;
|
|
141
|
-
}
|
|
142
|
-
return prevColumns;
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}, [columns, workingDataSource]);
|
|
147
|
-
|
|
148
|
-
// *** Page Navigation Helper Methods Starts Here
|
|
149
|
-
const nextPage = () => {
|
|
150
|
-
setCurrentPage((prevPage) => {
|
|
151
|
-
if (prevPage < totalPages - 1) {
|
|
152
|
-
const newPage = prevPage + 1;
|
|
153
|
-
updatePageRange(newPage);
|
|
154
|
-
return newPage;
|
|
155
|
-
}
|
|
156
|
-
return prevPage;
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const prevPage = () => {
|
|
161
|
-
setCurrentPage((prevPage) => {
|
|
162
|
-
if (prevPage > 0) {
|
|
163
|
-
const newPage = prevPage - 1;
|
|
164
|
-
updatePageRange(newPage);
|
|
165
|
-
return newPage;
|
|
166
|
-
}
|
|
167
|
-
return prevPage;
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const goToEndPage = () => {
|
|
172
|
-
const lastPage = totalPages - 1;
|
|
173
|
-
setCurrentPage(lastPage);
|
|
174
|
-
updatePageRange(lastPage);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const goToFirstPage = () => {
|
|
178
|
-
setCurrentPage(0);
|
|
179
|
-
updatePageRange(0);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const goToPage = (page: number) => {
|
|
183
|
-
setCurrentPage(page);
|
|
184
|
-
updatePageRange(page);
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const updatePageRange = (page: number) => {
|
|
188
|
-
const start = Math.floor(page / 10) * 10;
|
|
189
|
-
setPageStart(start);
|
|
190
|
-
setPageEnd(Math.min(start + 10, totalPages));
|
|
191
|
-
};
|
|
192
|
-
// Page Navigation Helper Methods Ends Here ***
|
|
193
|
-
|
|
194
|
-
// *** Functions handling global search starts here
|
|
195
|
-
const handleSearchInput = (e: any) => {
|
|
196
|
-
if (!lazy) {
|
|
197
|
-
const searchValue = e.target.value;
|
|
198
|
-
setSearchParam(searchValue);
|
|
199
|
-
if (searchValue === "") {
|
|
200
|
-
setWorkingDataSource(
|
|
201
|
-
fallbackSourceData.length > 0 ? fallbackSourceData : dataSource
|
|
202
|
-
);
|
|
203
|
-
const fallback =
|
|
204
|
-
fallbackSourceData.length > 0 ? fallbackSourceData : dataSource;
|
|
205
|
-
const totalPages = Math.ceil(fallback.length / pageSettings.pageNumber);
|
|
206
|
-
setTotalPages(totalPages);
|
|
207
|
-
setPageEnd(Math.min(pageStart + 10, totalPages));
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
const handleSearch = (searchParam: string) => {
|
|
213
|
-
const filteredData = workingDataSource.filter((item: any) =>
|
|
214
|
-
Object.values(item).some((val: any) => {
|
|
215
|
-
const trimmedVal = val.toString().toLowerCase().trim();
|
|
216
|
-
const trimmedSearchParam = searchParam.toLowerCase().trim();
|
|
217
|
-
return trimmedVal.includes(trimmedSearchParam);
|
|
218
|
-
})
|
|
219
|
-
);
|
|
220
|
-
setWorkingDataSource(filteredData);
|
|
221
|
-
const newTotalPages = Math.ceil(
|
|
222
|
-
filteredData.length / pageSettings.pageNumber
|
|
223
|
-
);
|
|
224
|
-
setTotalPages(newTotalPages);
|
|
225
|
-
const newCurrentPage = 0;
|
|
226
|
-
setCurrentPage(newCurrentPage);
|
|
227
|
-
const newPageStart = Math.floor(newCurrentPage / 10) * 10;
|
|
228
|
-
setPageStart(newPageStart);
|
|
229
|
-
setPageEnd(Math.min(newPageStart + 10, newTotalPages));
|
|
230
|
-
};
|
|
231
|
-
// Functions handling global search ends here ***
|
|
232
|
-
|
|
233
|
-
// This will render template passed to Grid
|
|
234
|
-
const renderCell = (rowData: any, column: any, rowIndex: number) => {
|
|
235
|
-
const cellValue = rowData[column.field];
|
|
236
|
-
|
|
237
|
-
if (column.template) {
|
|
238
|
-
return (
|
|
239
|
-
<column.template
|
|
240
|
-
rowData={rowData}
|
|
241
|
-
rowIndex={rowIndex + currentPage * pageSettings.pageNumber}
|
|
242
|
-
rowChange={(changes: any) => {
|
|
243
|
-
if (rowChange) rowChange(changes);
|
|
244
|
-
}}
|
|
245
|
-
/>
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (column.tooltip) {
|
|
250
|
-
return (
|
|
251
|
-
<span title={cellValue?.toString()}>
|
|
252
|
-
{cellValue && cellValue.length > 10
|
|
253
|
-
? `${cellValue.slice(0, 10)}...`
|
|
254
|
-
: cellValue}
|
|
255
|
-
</span>
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
return cellValue;
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// *** Filter Handling Functions Starts Here
|
|
263
|
-
const toggleFilterPopup = (index: number) => {
|
|
264
|
-
setWorkingColumns((prevColumns: any) =>
|
|
265
|
-
prevColumns.map((column: any, i: any) =>
|
|
266
|
-
i === index
|
|
267
|
-
? { ...column, showFilterPopup: !column.showFilterPopup }
|
|
268
|
-
: column
|
|
269
|
-
)
|
|
270
|
-
);
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
// Resetting pagination params for updating pagination
|
|
274
|
-
function resetPage(dataSource: any) {
|
|
275
|
-
const newTotalPages = Math.ceil(
|
|
276
|
-
dataSource.length / pageSettings.pageNumber
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
setTotalPages(newTotalPages);
|
|
280
|
-
setCurrentPage(0);
|
|
281
|
-
setPageStart(0);
|
|
282
|
-
setPageEnd(Math.min(10, newTotalPages));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Applying Filter
|
|
286
|
-
function handleApplyFilter(event: any) {
|
|
287
|
-
const {
|
|
288
|
-
columns: updatedColumns,
|
|
289
|
-
workingDataSource: updatedFullDataSource,
|
|
290
|
-
activeFilterArray: updatedActiveFilterArray,
|
|
291
|
-
} = handleApplyFilterHelper(event, columns, workingDataSource);
|
|
292
|
-
|
|
293
|
-
setWorkingColumns(updatedColumns);
|
|
294
|
-
setWorkingDataSource(updatedFullDataSource);
|
|
295
|
-
setActiveFilterArray(updatedActiveFilterArray);
|
|
296
|
-
|
|
297
|
-
setActiveFilterArray(updatedActiveFilterArray);
|
|
298
|
-
resetPage(updatedFullDataSource);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Clearing Filter
|
|
302
|
-
function clearFilter(event: any) {
|
|
303
|
-
const clearDataSource = Array.isArray(dataSource)
|
|
304
|
-
? dataSource
|
|
305
|
-
: fallbackSourceData;
|
|
306
|
-
const {
|
|
307
|
-
columns: updatedColumns,
|
|
308
|
-
workingDataSource: updatedDataSource,
|
|
309
|
-
activeFilterArray: updatedActiveFilterArray,
|
|
310
|
-
} = clearFilterHelper(event, workingColumns, clearDataSource);
|
|
311
|
-
|
|
312
|
-
setWorkingColumns(updatedColumns);
|
|
313
|
-
setWorkingDataSource(updatedDataSource);
|
|
314
|
-
setActiveFilterArray(updatedActiveFilterArray);
|
|
315
|
-
resetPage(updatedDataSource);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const handleFilterAction = (action: any, colIndex: number) => {
|
|
319
|
-
switch (action.type) {
|
|
320
|
-
case "cancel":
|
|
321
|
-
toggleFilterPopup(colIndex);
|
|
322
|
-
break;
|
|
323
|
-
case "applyFilter":
|
|
324
|
-
handleApplyFilter(action);
|
|
325
|
-
break;
|
|
326
|
-
case "clearFilter":
|
|
327
|
-
clearFilter(action);
|
|
328
|
-
break;
|
|
329
|
-
default:
|
|
330
|
-
break;
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
// *** Filter Handling Functions Ends Here
|
|
334
|
-
|
|
335
|
-
// *** RowSelection Handling Logic Starts Here
|
|
336
|
-
const handleSelectAll = () => {
|
|
337
|
-
setSelectedRows(workingDataSource);
|
|
338
|
-
if (onSelectRow) onSelectRow(workingDataSource);
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
const handleSelect = (rowData: any) => {
|
|
342
|
-
setSelectedRows((prevData) => {
|
|
343
|
-
const isSelected = prevData.includes(rowData);
|
|
344
|
-
let updatedData;
|
|
345
|
-
if (isSelected) {
|
|
346
|
-
updatedData = prevData.filter((item) => item !== rowData);
|
|
347
|
-
} else {
|
|
348
|
-
updatedData = [...prevData, rowData];
|
|
349
|
-
}
|
|
350
|
-
if (onSelectRow) onSelectRow(updatedData);
|
|
351
|
-
return updatedData;
|
|
352
|
-
});
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
const isRowSelected = (rowData: any) => {
|
|
356
|
-
return selectedRows.includes(rowData);
|
|
357
|
-
};
|
|
358
|
-
// RowSelection Handling Logic Ends Here ***
|
|
359
|
-
|
|
360
|
-
// Making Grid Functions Accessible in Parent
|
|
361
|
-
useImperativeHandle(
|
|
362
|
-
ref,
|
|
363
|
-
() => {
|
|
364
|
-
return {
|
|
365
|
-
goToPage,
|
|
366
|
-
nextPage,
|
|
367
|
-
prevPage,
|
|
368
|
-
goToFirstPage,
|
|
369
|
-
goToEndPage,
|
|
370
|
-
handleSearch,
|
|
371
|
-
handleApplyFilter,
|
|
372
|
-
clearFilter,
|
|
373
|
-
};
|
|
374
|
-
},
|
|
375
|
-
[]
|
|
376
|
-
);
|
|
377
|
-
|
|
378
|
-
// JSX Rendering
|
|
379
|
-
return (
|
|
380
|
-
<div className={gridContainerClass}>
|
|
381
|
-
<React.Fragment>
|
|
382
|
-
{/* Global utility logic */}
|
|
383
|
-
<div
|
|
384
|
-
className={`min-w-full flex justify-between items-center ${
|
|
385
|
-
enableExcelExport || enableSearch || enablePdfExport
|
|
386
|
-
? "block"
|
|
387
|
-
: "hidden"
|
|
388
|
-
}`}
|
|
389
|
-
>
|
|
390
|
-
<div className="flex justify-end gap-2 px-1 py-3 flex-grow">
|
|
391
|
-
{enableExcelExport && (
|
|
392
|
-
<button
|
|
393
|
-
className={gridButtonClass}
|
|
394
|
-
onClick={() => {
|
|
395
|
-
exportToExcelHelper(workingDataSource, columns, excelName);
|
|
396
|
-
}}
|
|
397
|
-
>
|
|
398
|
-
Export as Excel
|
|
399
|
-
</button>
|
|
400
|
-
)}
|
|
401
|
-
{enablePdfExport && (
|
|
402
|
-
<button
|
|
403
|
-
className={gridButtonClass}
|
|
404
|
-
onClick={() => {
|
|
405
|
-
exportToPDFHelper(
|
|
406
|
-
workingDataSource,
|
|
407
|
-
columns,
|
|
408
|
-
pdfName,
|
|
409
|
-
pdfOptions
|
|
410
|
-
);
|
|
411
|
-
}}
|
|
412
|
-
>
|
|
413
|
-
Export as PDF
|
|
414
|
-
</button>
|
|
415
|
-
)}
|
|
416
|
-
{enableSearch && (
|
|
417
|
-
<div className="flex gap-1">
|
|
418
|
-
<input
|
|
419
|
-
type="search"
|
|
420
|
-
value={searchParam}
|
|
421
|
-
onChange={handleSearchInput}
|
|
422
|
-
placeholder="search"
|
|
423
|
-
className="outline-none p-2 text-sm font-normal bg-gray-50 rounded-lg max-sm:hidden dark:bg-black dark:border dark:text-white"
|
|
424
|
-
onKeyDown={(event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
425
|
-
if (event.key === "Enter") {
|
|
426
|
-
handleSearch(searchParam);
|
|
427
|
-
}
|
|
428
|
-
}}
|
|
429
|
-
/>
|
|
430
|
-
<button
|
|
431
|
-
className="bg-white border rounded-lg text-black w-10 flex items-center justify-center dark:bg-black dark:text-white"
|
|
432
|
-
onClick={() => handleSearch(searchParam)}
|
|
433
|
-
>
|
|
434
|
-
<Icon
|
|
435
|
-
elements={search}
|
|
436
|
-
svgClass={"stroke-gray-500 fill-none dark:stroke-white"}
|
|
437
|
-
/>
|
|
438
|
-
</button>
|
|
439
|
-
</div>
|
|
440
|
-
)}
|
|
441
|
-
</div>
|
|
442
|
-
</div>
|
|
443
|
-
|
|
444
|
-
<div className="overflow-x-auto">
|
|
445
|
-
<table className="min-w-full">
|
|
446
|
-
<thead>
|
|
447
|
-
<tr>
|
|
448
|
-
{selectAll && (
|
|
449
|
-
<th className="text-left border-b border-t bg-gray-50 px-4 py-4 dark:bg-gray-700 dark:text-white">
|
|
450
|
-
<input type="checkbox" onChange={handleSelectAll} />
|
|
451
|
-
</th>
|
|
452
|
-
)}
|
|
453
|
-
{/* Rendering column headers */}
|
|
454
|
-
{workingColumns.map((columnHeader: any, colIndex: number) => (
|
|
455
|
-
<th
|
|
456
|
-
key={colIndex}
|
|
457
|
-
className={tableHeaderStyle}
|
|
458
|
-
style={{
|
|
459
|
-
width: columnHeader.width
|
|
460
|
-
? `${columnHeader.width}px`
|
|
461
|
-
: "auto",
|
|
462
|
-
}}
|
|
463
|
-
>
|
|
464
|
-
<div className="flex items-center relative">
|
|
465
|
-
{columnHeader.headerText
|
|
466
|
-
? columnHeader.headerText
|
|
467
|
-
: columnHeader.field}
|
|
468
|
-
{columnHeader.filter && !columnHeader.template && (
|
|
469
|
-
<React.Fragment>
|
|
470
|
-
<button
|
|
471
|
-
onClick={() => {
|
|
472
|
-
toggleFilterPopup(colIndex);
|
|
473
|
-
}}
|
|
474
|
-
>
|
|
475
|
-
<Icon
|
|
476
|
-
dimensions={{ width: "12", height: "12" }}
|
|
477
|
-
elements={listFilter}
|
|
478
|
-
svgClass={`ml-2 fill-none dark:stroke-white ${
|
|
479
|
-
activeFilterArray &&
|
|
480
|
-
activeFilterArray.some(
|
|
481
|
-
(filter: any) =>
|
|
482
|
-
filter.filterColumn === columnHeader.field
|
|
483
|
-
)
|
|
484
|
-
? "stroke-red-400"
|
|
485
|
-
: "stroke-black"
|
|
486
|
-
}`}
|
|
487
|
-
/>
|
|
488
|
-
</button>
|
|
489
|
-
<FilterPopup
|
|
490
|
-
show={columnHeader.showFilterPopup}
|
|
491
|
-
columnHeader={columnHeader.field}
|
|
492
|
-
filterAction={(action: any) => {
|
|
493
|
-
handleFilterAction(action, colIndex);
|
|
494
|
-
}}
|
|
495
|
-
/>
|
|
496
|
-
</React.Fragment>
|
|
497
|
-
)}
|
|
498
|
-
</div>
|
|
499
|
-
</th>
|
|
500
|
-
))}
|
|
501
|
-
</tr>
|
|
502
|
-
</thead>
|
|
503
|
-
<tbody>
|
|
504
|
-
{/* rendering body */}
|
|
505
|
-
{workingDataSource.length > 0 && !isFetching ? (
|
|
506
|
-
workingDataSource
|
|
507
|
-
.slice(
|
|
508
|
-
currentPage * pageSettings.pageNumber,
|
|
509
|
-
(currentPage + 1) * pageSettings.pageNumber
|
|
510
|
-
)
|
|
511
|
-
.map((rowData: any, rowIndex: number) => (
|
|
512
|
-
<tr
|
|
513
|
-
key={rowIndex}
|
|
514
|
-
className="hover:bg-gray-50 dark:hover:bg-gray-900 cursor-pointer"
|
|
515
|
-
>
|
|
516
|
-
{selectAll && (
|
|
517
|
-
<td className={gridColumnStyleSelectAll}>
|
|
518
|
-
<input
|
|
519
|
-
type="checkbox"
|
|
520
|
-
checked={isRowSelected(rowData)}
|
|
521
|
-
onChange={() => handleSelect(rowData)}
|
|
522
|
-
/>
|
|
523
|
-
</td>
|
|
524
|
-
)}
|
|
525
|
-
{workingColumns.map((column: any, colIndex: number) => (
|
|
526
|
-
<td
|
|
527
|
-
key={colIndex}
|
|
528
|
-
className={gridColumnStyle}
|
|
529
|
-
style={{
|
|
530
|
-
width: column.width ? `${column.width}px` : "auto",
|
|
531
|
-
}}
|
|
532
|
-
>
|
|
533
|
-
{renderCell(rowData, column, rowIndex)}
|
|
534
|
-
</td>
|
|
535
|
-
))}
|
|
536
|
-
</tr>
|
|
537
|
-
))
|
|
538
|
-
) : (
|
|
539
|
-
<tr>
|
|
540
|
-
<td
|
|
541
|
-
colSpan={workingColumns.length}
|
|
542
|
-
className="text-center p-4 border-b text-sm"
|
|
543
|
-
>
|
|
544
|
-
{isFetching
|
|
545
|
-
? "Fetching Data Please Wait..."
|
|
546
|
-
: "No Data Found"}
|
|
547
|
-
</td>
|
|
548
|
-
</tr>
|
|
549
|
-
)}
|
|
550
|
-
</tbody>
|
|
551
|
-
</table>
|
|
552
|
-
</div>
|
|
553
|
-
{/* Pagination logic */}
|
|
554
|
-
<div className="flex p-2 justify-between dark:text-white">
|
|
555
|
-
<div className="flex gap-4">
|
|
556
|
-
<button
|
|
557
|
-
onClick={goToFirstPage}
|
|
558
|
-
className={`${
|
|
559
|
-
currentPage === 0 ? "text-gray-200 dark:text-gray-700" : ""
|
|
560
|
-
}`}
|
|
561
|
-
>
|
|
562
|
-
<Icon
|
|
563
|
-
elements={leftArrows}
|
|
564
|
-
svgClass={`${
|
|
565
|
-
currentPage === 0
|
|
566
|
-
? "stroke-gray-200 fill-none dark:stroke-gray-700"
|
|
567
|
-
: "stroke-black fill-none dark:stroke-white"
|
|
568
|
-
}`}
|
|
569
|
-
/>
|
|
570
|
-
</button>
|
|
571
|
-
<button onClick={prevPage}>
|
|
572
|
-
<Icon
|
|
573
|
-
elements={leftArrow}
|
|
574
|
-
svgClass={`${
|
|
575
|
-
currentPage === 0
|
|
576
|
-
? "stroke-gray-200 fill-none dark:stroke-gray-700"
|
|
577
|
-
: "stroke-black fill-none dark:stroke-white"
|
|
578
|
-
}`}
|
|
579
|
-
/>
|
|
580
|
-
</button>
|
|
581
|
-
<div className="flex flex-row gap-3 items-center">
|
|
582
|
-
{pageStart > 0 && (
|
|
583
|
-
<button
|
|
584
|
-
className="p-1 w-5 h-5 flex items-center justify-center rounded-full"
|
|
585
|
-
onClick={() => goToPage(pageStart - 1)}
|
|
586
|
-
>
|
|
587
|
-
...
|
|
588
|
-
</button>
|
|
589
|
-
)}
|
|
590
|
-
{workingDataSource.length > 0 &&
|
|
591
|
-
Array.from({ length: pageEnd - pageStart }).map((_, i) => (
|
|
592
|
-
<button
|
|
593
|
-
key={i}
|
|
594
|
-
onClick={() => goToPage(pageStart + i)}
|
|
595
|
-
className={`${
|
|
596
|
-
pageStart + i === currentPage
|
|
597
|
-
? "font-bold text-white p-2 h-6 bg-black flex items-center justify-center rounded-md w-auto dark:bg-white dark:text-black"
|
|
598
|
-
: ""
|
|
599
|
-
}`}
|
|
600
|
-
>
|
|
601
|
-
{pageStart + i + 1}
|
|
602
|
-
</button>
|
|
603
|
-
))}
|
|
604
|
-
{pageEnd < totalPages && (
|
|
605
|
-
<button onClick={() => goToPage(pageEnd)}>...</button>
|
|
606
|
-
)}
|
|
607
|
-
</div>
|
|
608
|
-
<button
|
|
609
|
-
onClick={nextPage}
|
|
610
|
-
className={`${
|
|
611
|
-
currentPage === totalPages - 1 || workingDataSource.length <= 0
|
|
612
|
-
? "text-gray-200 dark:text-gray-700"
|
|
613
|
-
: ""
|
|
614
|
-
}`}
|
|
615
|
-
>
|
|
616
|
-
<Icon
|
|
617
|
-
elements={rightArrow}
|
|
618
|
-
svgClass={`${
|
|
619
|
-
currentPage === totalPages - 1 ||
|
|
620
|
-
workingDataSource.length <= 0
|
|
621
|
-
? "stroke-gray-200 fill-none dark:stroke-gray-700"
|
|
622
|
-
: "stroke-black fill-none dark:stroke-white"
|
|
623
|
-
}`}
|
|
624
|
-
/>
|
|
625
|
-
</button>
|
|
626
|
-
<button
|
|
627
|
-
onClick={goToEndPage}
|
|
628
|
-
className={`${
|
|
629
|
-
currentPage === totalPages - 1 || workingDataSource.length <= 0
|
|
630
|
-
? "text-gray-200 dark:text-gray-700"
|
|
631
|
-
: ""
|
|
632
|
-
}`}
|
|
633
|
-
>
|
|
634
|
-
<Icon
|
|
635
|
-
elements={rightArrows}
|
|
636
|
-
svgClass={`${
|
|
637
|
-
currentPage === totalPages - 1 ||
|
|
638
|
-
workingDataSource.length <= 0
|
|
639
|
-
? "stroke-gray-200 fill-none dark:stroke-gray-700"
|
|
640
|
-
: "stroke-black fill-none dark:stroke-white"
|
|
641
|
-
}`}
|
|
642
|
-
/>
|
|
643
|
-
</button>
|
|
644
|
-
</div>
|
|
645
|
-
<div className="flex text-sm">
|
|
646
|
-
{currentPage + 1} of {totalPages} pages ({workingDataSource.length})
|
|
647
|
-
items
|
|
648
|
-
</div>
|
|
649
|
-
</div>
|
|
650
|
-
</React.Fragment>
|
|
651
|
-
</div>
|
|
652
|
-
);
|
|
653
|
-
});
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import * as XLSX from "xlsx";
|
|
2
|
-
import jsPDF from "jspdf";
|
|
3
|
-
import "jspdf-autotable";
|
|
4
|
-
|
|
5
|
-
let activeFilterArray: any[] = [];
|
|
6
|
-
|
|
7
|
-
interface PDFExportOptions {
|
|
8
|
-
layout: "portrait" | "landscape";
|
|
9
|
-
paperSize:
|
|
10
|
-
| "a3"
|
|
11
|
-
| "a4"
|
|
12
|
-
| "letter"
|
|
13
|
-
| "legal"
|
|
14
|
-
| "tabloid"
|
|
15
|
-
| "statement"
|
|
16
|
-
| "executive";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function handleApplyFilterHelper(
|
|
20
|
-
event: any,
|
|
21
|
-
columns: any,
|
|
22
|
-
dataSource: any
|
|
23
|
-
) {
|
|
24
|
-
let workingDataSource: any[] = [...dataSource];
|
|
25
|
-
let filterValue = event.filterValue.toLowerCase();
|
|
26
|
-
let filterCondition = event.filterType;
|
|
27
|
-
let filterColumn = event.columnHeader;
|
|
28
|
-
|
|
29
|
-
// Add the new filter to activeFilterArray
|
|
30
|
-
activeFilterArray.push({
|
|
31
|
-
filterValue: filterValue,
|
|
32
|
-
filterCondition: filterCondition,
|
|
33
|
-
filterColumn: filterColumn,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
columns = columns.map((column: any) => {
|
|
37
|
-
if (column.field === filterColumn) {
|
|
38
|
-
return { ...column, isFilterActive: true, showFilterPopup: false };
|
|
39
|
-
}
|
|
40
|
-
return column;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Apply all active filters
|
|
44
|
-
activeFilterArray.forEach((filter: any) => {
|
|
45
|
-
workingDataSource = dataSource.filter((item: any) => {
|
|
46
|
-
let columnValue = item[filter.filterColumn].toString().toLowerCase();
|
|
47
|
-
switch (filter.filterCondition) {
|
|
48
|
-
case "contains":
|
|
49
|
-
return columnValue.includes(filter.filterValue);
|
|
50
|
-
case "equals":
|
|
51
|
-
return columnValue === filter.filterValue;
|
|
52
|
-
case "starts_with":
|
|
53
|
-
return columnValue.startsWith(filter.filterValue);
|
|
54
|
-
case "ends_with":
|
|
55
|
-
return columnValue.endsWith(filter.filterValue);
|
|
56
|
-
default:
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return { columns, workingDataSource, activeFilterArray };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Function For Clearing the Filter
|
|
66
|
-
export function clearFilterHelper(
|
|
67
|
-
event: any,
|
|
68
|
-
columns: any[],
|
|
69
|
-
dataSource: any[]
|
|
70
|
-
) {
|
|
71
|
-
let workingDataSource = [...dataSource];
|
|
72
|
-
let filterColumn = event.columnHeader;
|
|
73
|
-
|
|
74
|
-
// Remove the cleared filter from activeFilterArray
|
|
75
|
-
activeFilterArray = activeFilterArray.filter(
|
|
76
|
-
(filter: any) => filter.filterColumn !== filterColumn
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
let hasActiveFilters = activeFilterArray.length > 0;
|
|
80
|
-
|
|
81
|
-
// Reset the isFilterActive and showFilterPopup flags for the cleared filter
|
|
82
|
-
columns = columns.map((column: any) => {
|
|
83
|
-
if (column.field === filterColumn) {
|
|
84
|
-
return { ...column, isFilterActive: false, showFilterPopup: false };
|
|
85
|
-
}
|
|
86
|
-
return column;
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Reapply all remaining active filters
|
|
90
|
-
if (hasActiveFilters) {
|
|
91
|
-
activeFilterArray.forEach((filter: any) => {
|
|
92
|
-
workingDataSource = workingDataSource.filter((item: any) => {
|
|
93
|
-
let columnValue = item[filter.filterColumn].toString().toLowerCase();
|
|
94
|
-
switch (filter.filterCondition) {
|
|
95
|
-
case "contains":
|
|
96
|
-
return columnValue.includes(filter.filterValue);
|
|
97
|
-
case "equals":
|
|
98
|
-
return columnValue === filter.filterValue;
|
|
99
|
-
case "starts_with":
|
|
100
|
-
return columnValue.startsWith(filter.filterValue);
|
|
101
|
-
case "ends_with":
|
|
102
|
-
return columnValue.endsWith(filter.filterValue);
|
|
103
|
-
default:
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return { columns, workingDataSource, hasActiveFilters, activeFilterArray };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function exportToExcelHelper(
|
|
114
|
-
dataSource: any[],
|
|
115
|
-
columns: any[],
|
|
116
|
-
excelName: string
|
|
117
|
-
) {
|
|
118
|
-
// This will remove the column template.
|
|
119
|
-
const templateRemovedColumn = columns.filter((column) => !column.template);
|
|
120
|
-
const dataToExport = dataSource.map((row) => {
|
|
121
|
-
const rowData: any = {};
|
|
122
|
-
templateRemovedColumn.forEach((column: any) => {
|
|
123
|
-
rowData[column.field] = row[column.field];
|
|
124
|
-
});
|
|
125
|
-
return rowData;
|
|
126
|
-
});
|
|
127
|
-
const ws = XLSX.utils.json_to_sheet(dataToExport);
|
|
128
|
-
const wb = XLSX.utils.book_new();
|
|
129
|
-
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
|
|
130
|
-
XLSX.writeFile(wb, `${excelName}.xlsx`);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function exportToPDFHelper(
|
|
134
|
-
dataSource: any[],
|
|
135
|
-
columns: any[],
|
|
136
|
-
pdfName: string,
|
|
137
|
-
pdfoptions?: PDFExportOptions
|
|
138
|
-
) {
|
|
139
|
-
const { layout = "portrait", paperSize = "a4" }: any = pdfoptions;
|
|
140
|
-
|
|
141
|
-
const doc: any = new jsPDF({
|
|
142
|
-
orientation: layout,
|
|
143
|
-
unit: "mm",
|
|
144
|
-
format: paperSize,
|
|
145
|
-
});
|
|
146
|
-
// This will remove the columns with template.
|
|
147
|
-
const printableColumns = columns.filter(
|
|
148
|
-
(column) => !column.template || column.showInPdf
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
const dataToExport = dataSource.map((row) => {
|
|
152
|
-
const rowData: any = {};
|
|
153
|
-
printableColumns.forEach((column: any) => {
|
|
154
|
-
rowData[column.field] = row[column.field];
|
|
155
|
-
});
|
|
156
|
-
return Object.values(rowData);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const columnNames = printableColumns.map((column: any) => column.field);
|
|
160
|
-
doc.autoTable({
|
|
161
|
-
head: [columnNames],
|
|
162
|
-
body: dataToExport,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
doc.save(`${pdfName}.pdf`);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function handleEditActionHelper(
|
|
169
|
-
e: any,
|
|
170
|
-
isEditModeActive: boolean,
|
|
171
|
-
actionMode: string,
|
|
172
|
-
newEntry: any,
|
|
173
|
-
workingDataSource: any[],
|
|
174
|
-
goToFirstPage: () => void
|
|
175
|
-
) {
|
|
176
|
-
const { mode } = e.detail;
|
|
177
|
-
let dataSourceUpdate = [...workingDataSource];
|
|
178
|
-
let isEditModeActiveUpdate: boolean = isEditModeActive;
|
|
179
|
-
let actionModeUpdate: string = actionMode;
|
|
180
|
-
let newEntryUpdate: any = { ...newEntry };
|
|
181
|
-
|
|
182
|
-
function resetEditMode() {
|
|
183
|
-
isEditModeActiveUpdate = false;
|
|
184
|
-
actionModeUpdate = "";
|
|
185
|
-
newEntryUpdate = {};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function addNewEntry() {
|
|
189
|
-
if (Object.keys(newEntryUpdate).length > 0) {
|
|
190
|
-
dataSourceUpdate = [newEntryUpdate, ...workingDataSource];
|
|
191
|
-
newEntryUpdate = {};
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
switch (mode) {
|
|
196
|
-
case "add":
|
|
197
|
-
isEditModeActiveUpdate = true;
|
|
198
|
-
actionModeUpdate = mode;
|
|
199
|
-
goToFirstPage();
|
|
200
|
-
break;
|
|
201
|
-
case "cancel":
|
|
202
|
-
resetEditMode();
|
|
203
|
-
break;
|
|
204
|
-
case "update":
|
|
205
|
-
addNewEntry();
|
|
206
|
-
resetEditMode();
|
|
207
|
-
break;
|
|
208
|
-
default:
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
dataSourceUpdate,
|
|
214
|
-
isEditModeActiveUpdate,
|
|
215
|
-
actionModeUpdate,
|
|
216
|
-
newEntryUpdate,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
@@ -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 "./Grid";
|
|
12
|
-
import React, { memo } from "react";
|
|
13
|
-
|
|
14
|
-
const Grid = 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 { Grid };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
interface PageSettingsProps {
|
|
2
|
-
pageNumber: number;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export type GridProps = {
|
|
6
|
-
dataSource: any[] | string;
|
|
7
|
-
columns?: any[];
|
|
8
|
-
pageSettings: PageSettingsProps;
|
|
9
|
-
enableSearch?: boolean;
|
|
10
|
-
lazy?: boolean;
|
|
11
|
-
enableExcelExport?: boolean;
|
|
12
|
-
excelName?: string;
|
|
13
|
-
enablePdfExport?: boolean;
|
|
14
|
-
pdfName?: string;
|
|
15
|
-
gridContainerClass?: string;
|
|
16
|
-
gridButtonClass?: string;
|
|
17
|
-
gridHeaderClass?: string;
|
|
18
|
-
gridGlobalSearchButtonClass?: string;
|
|
19
|
-
gridPaginationButtonClass?: string;
|
|
20
|
-
pdfOptions?: any;
|
|
21
|
-
isFetching?: boolean;
|
|
22
|
-
showPagination?: boolean;
|
|
23
|
-
selectAll?: boolean;
|
|
24
|
-
onSelectRow?: (value: any) => void;
|
|
25
|
-
tableHeaderStyle?: string;
|
|
26
|
-
gridColumnStyleSelectAll?: string;
|
|
27
|
-
gridColumnStyle?: string;
|
|
28
|
-
rowChange?: any;
|
|
29
|
-
pageStatus?: any;
|
|
30
|
-
};
|