@pagamio/frontend-commons-lib 0.8.356 → 0.8.357
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.
|
@@ -51,7 +51,7 @@ type ExportDropdownProps<T extends Record<string, any>> = {
|
|
|
51
51
|
xlsxOptions?: XlsxExportOptions;
|
|
52
52
|
csvOptions?: CsvExportOptions;
|
|
53
53
|
exportAll?: boolean;
|
|
54
|
-
fetchData?: (params?: Record<string, string
|
|
54
|
+
fetchData?: (params?: Record<string, string>, onProgress?: (fetched: number, total: number) => void) => Promise<T[]>;
|
|
55
55
|
enableEmailExport?: boolean;
|
|
56
56
|
emailExportApiUrl?: string;
|
|
57
57
|
onEmailExportSuccess?: (message: string) => void;
|
|
@@ -9,6 +9,7 @@ const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, ex
|
|
|
9
9
|
const [exportType, setExportType] = useState(null);
|
|
10
10
|
const [excludedColumns, setExcludedColumns] = useState(['action']);
|
|
11
11
|
const [isExporting, setIsExporting] = useState(false);
|
|
12
|
+
const [exportProgress, setExportProgress] = useState(null);
|
|
12
13
|
const [exportAllData, setExportAllData] = useState(false);
|
|
13
14
|
const [selectOpen, setSelectOpen] = useState(false);
|
|
14
15
|
const [emailAddress, setEmailAddress] = useState('');
|
|
@@ -116,8 +117,11 @@ const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, ex
|
|
|
116
117
|
const handleContinue = async () => {
|
|
117
118
|
const includedColumns = getIncludedColumns();
|
|
118
119
|
setIsExporting(true);
|
|
120
|
+
setExportProgress(null);
|
|
119
121
|
try {
|
|
120
|
-
const exportData = exportAllData && fetchData
|
|
122
|
+
const exportData = exportAllData && fetchData
|
|
123
|
+
? await fetchData({ exportAll: 'true' }, (fetched, total) => setExportProgress({ fetched, total }))
|
|
124
|
+
: data;
|
|
121
125
|
if (isEmailExport) {
|
|
122
126
|
// Store data, format and show email modal
|
|
123
127
|
setPendingExportData({ data: exportData, columns: includedColumns });
|
|
@@ -138,6 +142,7 @@ const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, ex
|
|
|
138
142
|
}
|
|
139
143
|
finally {
|
|
140
144
|
setIsExporting(false);
|
|
145
|
+
setExportProgress(null);
|
|
141
146
|
}
|
|
142
147
|
};
|
|
143
148
|
const handleExportChange = (type) => {
|
|
@@ -164,7 +169,11 @@ const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, ex
|
|
|
164
169
|
}) }), _jsx(Button, { variant: "primary", className: `w-full mt-4 px-4 py-2 rounded-md text-white flex items-center justify-center
|
|
165
170
|
${getIncludedColumns().length === 0 || isExporting
|
|
166
171
|
? 'bg-gray-300 cursor-not-allowed'
|
|
167
|
-
: 'bg-primary hover:bg-primary/90'}`, onClick: handleContinue, disabled: getIncludedColumns().length === 0 || isExporting, children: isExporting ? (_jsxs(_Fragment, { children: [_jsxs("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }),
|
|
172
|
+
: 'bg-primary hover:bg-primary/90'}`, onClick: handleContinue, disabled: getIncludedColumns().length === 0 || isExporting, children: isExporting ? (_jsxs(_Fragment, { children: [_jsxs("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), exportProgress && exportProgress.total > exportProgress.fetched
|
|
173
|
+
? `Fetching ${exportProgress.fetched}/${exportProgress.total}...`
|
|
174
|
+
: isEmailExport
|
|
175
|
+
? 'Preparing...'
|
|
176
|
+
: 'Exporting...'] })) : ('Continue') })] })), _jsx(Modal, { isOpen: showEmailModal, onClose: handleEmailModalClose, title: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(HiMail, { className: "w-5 h-5 text-primary" }), _jsx("span", { children: "Send Export via Email" })] }), size: "md", primaryButton: {
|
|
168
177
|
label: 'Send Email',
|
|
169
178
|
onClick: () => {
|
|
170
179
|
handleEmailModalSubmit().catch((error) => {
|
|
@@ -82,7 +82,14 @@ export interface ExportConfig<T extends Record<string, any>> {
|
|
|
82
82
|
xlsx?: XlsxExportOptions;
|
|
83
83
|
csv?: CsvExportOptions;
|
|
84
84
|
extraOptions?: ExtraOption[];
|
|
85
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Fetch the full dataset for "Export all data" (not just the current page).
|
|
87
|
+
* `onProgress(fetched, total)` is invoked after each page so the UI can show
|
|
88
|
+
* progress on long, multi-request exports. `usePagamioTable` auto-wires this
|
|
89
|
+
* for server-paginated tables; a consumer may override (e.g. a dedicated
|
|
90
|
+
* export endpoint).
|
|
91
|
+
*/
|
|
92
|
+
fetchAllData?: (params?: Record<string, string>, onProgress?: (fetched: number, total: number) => void) => Promise<T[]>;
|
|
86
93
|
email?: {
|
|
87
94
|
apiUrl: string;
|
|
88
95
|
onSuccess?: (message: string) => void;
|
|
@@ -274,9 +274,10 @@ export const usePagamioTable = ({ queryKey, queryFn, enabled: queryEnabled = tru
|
|
|
274
274
|
// Pages through the same `queryFn` at the backend's max `limit`, preserving
|
|
275
275
|
// the user's current sort/filters/search so the export matches what they see.
|
|
276
276
|
// Returns the full flattened dataset for the client-side export utils.
|
|
277
|
-
const fetchAllPages = useCallback(async () => {
|
|
277
|
+
const fetchAllPages = useCallback(async (_params, onProgress) => {
|
|
278
278
|
if (!isServerMode || !queryFn) {
|
|
279
279
|
// Client-mode tables already hold the whole filtered/sorted set.
|
|
280
|
+
onProgress?.(processedData.length, processedData.length);
|
|
280
281
|
return processedData;
|
|
281
282
|
}
|
|
282
283
|
const buildPageParams = (page) => buildQueryParams(queryParamConfig, { mode: paginationConfig.mode, page, size: MAX_EXPORT_PAGE_SIZE }, { mode: sortingConfig.mode, sortConfig }, { mode: filteringConfig.mode, searchMode, filters: appliedFilters });
|
|
@@ -288,6 +289,7 @@ export const usePagamioTable = ({ queryKey, queryFn, enabled: queryEnabled = tru
|
|
|
288
289
|
const all = [...first.data];
|
|
289
290
|
const total = first.total || serverTotal;
|
|
290
291
|
const totalPages = Math.max(1, Math.ceil(total / MAX_EXPORT_PAGE_SIZE));
|
|
292
|
+
onProgress?.(all.length, total);
|
|
291
293
|
// Pages are zero/one-based per the consumer's `queryParamConfig.transform`;
|
|
292
294
|
// `buildQueryParams` already applies that transform, so we just feed it the
|
|
293
295
|
// hook's internal zero-based index and let the config bump it.
|
|
@@ -297,6 +299,7 @@ export const usePagamioTable = ({ queryKey, queryFn, enabled: queryEnabled = tru
|
|
|
297
299
|
if (pageData.length === 0)
|
|
298
300
|
break; // defensive: stop if a page comes back empty
|
|
299
301
|
all.push(...pageData);
|
|
302
|
+
onProgress?.(all.length, total);
|
|
300
303
|
}
|
|
301
304
|
return all;
|
|
302
305
|
}, [
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagamio/frontend-commons-lib",
|
|
3
3
|
"description": "Pagamio library for Frontend reusable components like the form engine and table container",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.357",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"provenance": false
|