@pushwoosh/smart-components-kit 1.0.24 → 1.0.26
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/ExportCSV/ExportCsvBanner/ExportCsvBanner.d.ts +18 -0
- package/ExportCSV/ExportCsvBanner/ExportCsvBanner.js +121 -0
- package/ExportCSV/ExportCsvBanner/hooks/useExportVisibility.d.ts +5 -0
- package/ExportCSV/ExportCsvBanner/hooks/useExportVisibility.js +17 -0
- package/ExportCSV/ExportCsvBanner/index.d.ts +2 -0
- package/ExportCSV/ExportCsvBanner/index.js +1 -0
- package/ExportCSV/index.d.ts +2 -0
- package/ExportCSV/index.js +2 -0
- package/ExportCSV/useExportService/constants.d.ts +2 -0
- package/ExportCSV/useExportService/constants.js +2 -0
- package/ExportCSV/useExportService/index.d.ts +1 -0
- package/ExportCSV/useExportService/index.js +1 -0
- package/ExportCSV/useExportService/useExportService.d.ts +12 -0
- package/ExportCSV/useExportService/useExportService.js +119 -0
- package/context/types.d.ts +4 -2
- package/index.d.ts +1 -0
- package/index.js +2 -1
- package/package.json +2 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type TaskInfo_args, type GetLastTasksRequest, type Status } from '@pushwoosh/rpc-v2-http-api-data/pushwoosh_export_messages_v2';
|
|
3
|
+
export type ExportTask = {
|
|
4
|
+
id: number;
|
|
5
|
+
status: Status;
|
|
6
|
+
filename?: string;
|
|
7
|
+
args?: TaskInfo_args;
|
|
8
|
+
progressTitle: string;
|
|
9
|
+
resultSubTitle: string;
|
|
10
|
+
};
|
|
11
|
+
type ExportCsvBannerProps = {
|
|
12
|
+
exportTask: ExportTask | undefined;
|
|
13
|
+
updateExportTask: (exportTask: Partial<ExportTask>) => void;
|
|
14
|
+
showLastExportLocalStorageKey: string;
|
|
15
|
+
lastTasksParams?: GetLastTasksRequest;
|
|
16
|
+
};
|
|
17
|
+
export declare const ExportCsvBanner: ({ exportTask, updateExportTask, showLastExportLocalStorageKey, lastTasksParams, }: ExportCsvBannerProps) => React.JSX.Element | null;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { ExportResult, ProgressBar, Button } from '@pushwoosh/dumb-components';
|
|
3
|
+
import { Color, ShapeRadius } from '@pushwoosh/kit-constants';
|
|
4
|
+
import { Horizontal } from '@pushwoosh/kit-helpers';
|
|
5
|
+
import { DangerTriangleIcon, DownloadIcon } from '@pushwoosh/kit-icons';
|
|
6
|
+
import { useExportService } from '../useExportService';
|
|
7
|
+
import { useExportVisibility } from './hooks/useExportVisibility';
|
|
8
|
+
export const ExportCsvBanner = ({
|
|
9
|
+
exportTask,
|
|
10
|
+
updateExportTask,
|
|
11
|
+
showLastExportLocalStorageKey,
|
|
12
|
+
lastTasksParams
|
|
13
|
+
}) => {
|
|
14
|
+
const {
|
|
15
|
+
getLastTasks,
|
|
16
|
+
getStatus,
|
|
17
|
+
clearExport,
|
|
18
|
+
taskResult,
|
|
19
|
+
progress,
|
|
20
|
+
error
|
|
21
|
+
} = useExportService();
|
|
22
|
+
const {
|
|
23
|
+
isHidden,
|
|
24
|
+
hide,
|
|
25
|
+
show
|
|
26
|
+
} = useExportVisibility(showLastExportLocalStorageKey);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!exportTask) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (exportTask.id && (exportTask.status === 'STATUS_PENDING' || exportTask.status === 'STATUS_UNSPECIFIED')) {
|
|
32
|
+
clearExport();
|
|
33
|
+
getStatus({
|
|
34
|
+
uid: exportTask.id
|
|
35
|
+
});
|
|
36
|
+
show();
|
|
37
|
+
}
|
|
38
|
+
}, [clearExport, exportTask, getStatus, show]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (taskResult) {
|
|
41
|
+
updateExportTask({
|
|
42
|
+
status: 'STATUS_SUCCESS',
|
|
43
|
+
filename: taskResult.data.file
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}, [taskResult, updateExportTask]);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (error) {
|
|
49
|
+
updateExportTask({
|
|
50
|
+
status: 'STATUS_FAILED'
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}, [error, updateExportTask]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (lastTasksParams && !isHidden) {
|
|
56
|
+
getLastTasks(lastTasksParams).then(res => {
|
|
57
|
+
if (res.length > 0) {
|
|
58
|
+
const {
|
|
59
|
+
id,
|
|
60
|
+
result,
|
|
61
|
+
status,
|
|
62
|
+
args
|
|
63
|
+
} = res[0];
|
|
64
|
+
const {
|
|
65
|
+
data
|
|
66
|
+
} = result;
|
|
67
|
+
updateExportTask({
|
|
68
|
+
id,
|
|
69
|
+
status,
|
|
70
|
+
filename: data.file,
|
|
71
|
+
args,
|
|
72
|
+
progressTitle: 'Exporting list:',
|
|
73
|
+
resultSubTitle: 'Result:'
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}, [getLastTasks, isHidden, lastTasksParams, updateExportTask]);
|
|
79
|
+
if (!exportTask || isHidden) return null;
|
|
80
|
+
const {
|
|
81
|
+
filename,
|
|
82
|
+
status,
|
|
83
|
+
resultSubTitle,
|
|
84
|
+
progressTitle
|
|
85
|
+
} = exportTask;
|
|
86
|
+
return React.createElement(Horizontal, {
|
|
87
|
+
"$padding": 8,
|
|
88
|
+
"$alignItems": "center",
|
|
89
|
+
"$border": `1px solid ${Color.DIVIDER}`,
|
|
90
|
+
"$borderRadius": ShapeRadius.SECTION,
|
|
91
|
+
"$bgColor": Color.CLEAR
|
|
92
|
+
}, status === 'STATUS_SUCCESS' && React.createElement(ExportResult, {
|
|
93
|
+
type: "success",
|
|
94
|
+
title: "Exporting complete",
|
|
95
|
+
subtitle: `${resultSubTitle} ${filename}`,
|
|
96
|
+
handleClose: hide,
|
|
97
|
+
rightSlot: React.createElement("a", {
|
|
98
|
+
href: `/api/v2/statistics/exportMessagesStatistics/download/${filename}`,
|
|
99
|
+
download: filename
|
|
100
|
+
}, React.createElement(Button, {
|
|
101
|
+
color: "secondary",
|
|
102
|
+
size: "compact",
|
|
103
|
+
icon: React.createElement(DownloadIcon, {
|
|
104
|
+
size: "small",
|
|
105
|
+
view: "filled"
|
|
106
|
+
})
|
|
107
|
+
}, "Download CSV"))
|
|
108
|
+
}), status === 'STATUS_PENDING' && React.createElement(ProgressBar, {
|
|
109
|
+
title: progressTitle,
|
|
110
|
+
percentValue: progress
|
|
111
|
+
}), status === 'STATUS_FAILED' && React.createElement(ExportResult, {
|
|
112
|
+
type: "error",
|
|
113
|
+
title: "Export failed",
|
|
114
|
+
subtitle: "Please try again",
|
|
115
|
+
leftSlotIcon: React.createElement(DangerTriangleIcon, {
|
|
116
|
+
size: "medium",
|
|
117
|
+
view: "filled"
|
|
118
|
+
}),
|
|
119
|
+
handleClose: hide
|
|
120
|
+
}));
|
|
121
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
export const useExportVisibility = key => {
|
|
3
|
+
const [isHidden, setIsHidden] = useState(() => Boolean(+(localStorage.getItem(key) ?? 0)));
|
|
4
|
+
const hide = useCallback(() => {
|
|
5
|
+
localStorage.setItem(key, '1');
|
|
6
|
+
setIsHidden(true);
|
|
7
|
+
}, [key]);
|
|
8
|
+
const show = useCallback(() => {
|
|
9
|
+
localStorage.setItem(key, '0');
|
|
10
|
+
setIsHidden(false);
|
|
11
|
+
}, [key]);
|
|
12
|
+
return {
|
|
13
|
+
isHidden,
|
|
14
|
+
hide,
|
|
15
|
+
show
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ExportCsvBanner } from './ExportCsvBanner';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useExportService';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useExportService';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StatusRequest, StatusResponse, ResultRequest, ResultResponse, ExportRequest, GetLastTasksRequest, TaskInfo, ResultResponse_result } from '@pushwoosh/rpc-v2-http-api-data/pushwoosh_export_messages_v2';
|
|
2
|
+
export declare const useExportService: () => {
|
|
3
|
+
getLastTasks: (params: GetLastTasksRequest) => Promise<TaskInfo[]>;
|
|
4
|
+
startExport: (params: ExportRequest) => Promise<number>;
|
|
5
|
+
getStatus: (params: StatusRequest) => Promise<StatusResponse>;
|
|
6
|
+
getResult: (params: ResultRequest) => Promise<ResultResponse>;
|
|
7
|
+
clearExport: () => void;
|
|
8
|
+
error: string;
|
|
9
|
+
progress: number;
|
|
10
|
+
isTaskInProgress: boolean;
|
|
11
|
+
taskResult: ResultResponse_result | undefined;
|
|
12
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { API_CHECK_INTERVAL, MAX_RETRIES } from './constants';
|
|
3
|
+
import { useSPAContext } from '../../context';
|
|
4
|
+
export const useExportService = () => {
|
|
5
|
+
const [error, setError] = useState('');
|
|
6
|
+
const [progress, setProgress] = useState(0);
|
|
7
|
+
const [isTaskInProgress, setIsTaskInProgress] = useState(false);
|
|
8
|
+
const [taskResult, setTaskResult] = useState();
|
|
9
|
+
const timeoutStatusRef = useRef(null);
|
|
10
|
+
const retriesRef = useRef(0);
|
|
11
|
+
const {
|
|
12
|
+
rpcGateway
|
|
13
|
+
} = useSPAContext();
|
|
14
|
+
const clearExport = useCallback(() => {
|
|
15
|
+
setError('');
|
|
16
|
+
setIsTaskInProgress(false);
|
|
17
|
+
setTaskResult(undefined);
|
|
18
|
+
setProgress(0);
|
|
19
|
+
}, []);
|
|
20
|
+
const clearStatusTimeout = useCallback(() => {
|
|
21
|
+
if (timeoutStatusRef.current) {
|
|
22
|
+
clearTimeout(timeoutStatusRef.current);
|
|
23
|
+
timeoutStatusRef.current = null;
|
|
24
|
+
}
|
|
25
|
+
}, []);
|
|
26
|
+
const startExport = useCallback(async params => {
|
|
27
|
+
try {
|
|
28
|
+
clearExport();
|
|
29
|
+
setIsTaskInProgress(true);
|
|
30
|
+
const {
|
|
31
|
+
uid
|
|
32
|
+
} = await rpcGateway.exportStatistics.Export(params);
|
|
33
|
+
return uid;
|
|
34
|
+
} catch (err) {
|
|
35
|
+
setError(err === null || err === void 0 ? void 0 : err.message);
|
|
36
|
+
setIsTaskInProgress(false);
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
}, [clearExport, rpcGateway.exportStatistics]);
|
|
40
|
+
const getResult = useCallback(async params => {
|
|
41
|
+
try {
|
|
42
|
+
const result = await rpcGateway.exportStatistics.Result(params);
|
|
43
|
+
setTaskResult(result.result);
|
|
44
|
+
return result;
|
|
45
|
+
} catch (err) {
|
|
46
|
+
setError(err === null || err === void 0 ? void 0 : err.message);
|
|
47
|
+
return err;
|
|
48
|
+
} finally {
|
|
49
|
+
setIsTaskInProgress(false);
|
|
50
|
+
}
|
|
51
|
+
}, [rpcGateway]);
|
|
52
|
+
const getStatus = useCallback(async params => {
|
|
53
|
+
try {
|
|
54
|
+
const result = await rpcGateway.exportStatistics.Status(params);
|
|
55
|
+
switch (result.status) {
|
|
56
|
+
case 'STATUS_PENDING':
|
|
57
|
+
if (result.progress > progress) {
|
|
58
|
+
setProgress(Math.round(result.progress));
|
|
59
|
+
}
|
|
60
|
+
clearStatusTimeout();
|
|
61
|
+
if (retriesRef.current < MAX_RETRIES) {
|
|
62
|
+
retriesRef.current += 1;
|
|
63
|
+
timeoutStatusRef.current = setTimeout(() => {
|
|
64
|
+
getStatus(params);
|
|
65
|
+
clearStatusTimeout();
|
|
66
|
+
}, API_CHECK_INTERVAL);
|
|
67
|
+
} else {
|
|
68
|
+
setError('Max retries reached. Please try again later.');
|
|
69
|
+
setIsTaskInProgress(false);
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'STATUS_SUCCESS':
|
|
73
|
+
getResult(params);
|
|
74
|
+
retriesRef.current = 0;
|
|
75
|
+
setIsTaskInProgress(false);
|
|
76
|
+
break;
|
|
77
|
+
case 'STATUS_FAILED':
|
|
78
|
+
setError('Error. File has not been generated. Please contact with our support team');
|
|
79
|
+
setIsTaskInProgress(false);
|
|
80
|
+
retriesRef.current = 0;
|
|
81
|
+
throw new Error('Export failed');
|
|
82
|
+
default:
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
setError('Export failed. File not found');
|
|
88
|
+
setIsTaskInProgress(false);
|
|
89
|
+
retriesRef.current = 0;
|
|
90
|
+
return err;
|
|
91
|
+
}
|
|
92
|
+
}, [clearStatusTimeout, getResult, progress, rpcGateway]);
|
|
93
|
+
const getLastTasks = useCallback(async params => {
|
|
94
|
+
try {
|
|
95
|
+
const {
|
|
96
|
+
tasks
|
|
97
|
+
} = await rpcGateway.exportStatistics.GetLastTasks(params);
|
|
98
|
+
return tasks;
|
|
99
|
+
} catch (err) {
|
|
100
|
+
setError(err === null || err === void 0 ? void 0 : err.message);
|
|
101
|
+
return err;
|
|
102
|
+
}
|
|
103
|
+
}, [rpcGateway]);
|
|
104
|
+
useEffect(() => () => {
|
|
105
|
+
clearStatusTimeout();
|
|
106
|
+
setIsTaskInProgress(false);
|
|
107
|
+
}, [clearStatusTimeout]);
|
|
108
|
+
return {
|
|
109
|
+
getLastTasks,
|
|
110
|
+
startExport,
|
|
111
|
+
getStatus,
|
|
112
|
+
getResult,
|
|
113
|
+
clearExport,
|
|
114
|
+
error,
|
|
115
|
+
progress,
|
|
116
|
+
isTaskInProgress,
|
|
117
|
+
taskResult
|
|
118
|
+
};
|
|
119
|
+
};
|
package/context/types.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type History } from 'history';
|
|
2
2
|
import type { GrpcBridge } from '@pushwoosh/grpc-bridge';
|
|
3
3
|
import type { GrpcClient, HttpClient, RpcClient } from '@pushwoosh/http-client';
|
|
4
|
-
import type { API } from '@pushwoosh/rpc-
|
|
4
|
+
import type { API as RpcGatewayJourneyAPI } from '@pushwoosh/rpc-gateway-journey-data';
|
|
5
|
+
import type { API as RpcGatewayAPI } from '@pushwoosh/rpc-v2-http-api-data';
|
|
5
6
|
import type { SessionStore } from '@pushwoosh/session-store';
|
|
6
7
|
export type SPAContextType = {
|
|
7
8
|
readonly history: History;
|
|
@@ -10,7 +11,8 @@ export type SPAContextType = {
|
|
|
10
11
|
readonly grpcClient: GrpcClient;
|
|
11
12
|
readonly grpcBridge: GrpcBridge;
|
|
12
13
|
readonly sessionStore: SessionStore;
|
|
13
|
-
readonly rpcGateway:
|
|
14
|
+
readonly rpcGateway: RpcGatewayAPI;
|
|
15
|
+
readonly rpcGatewayJourney: RpcGatewayJourneyAPI;
|
|
14
16
|
readonly language: string;
|
|
15
17
|
readonly helpers: {
|
|
16
18
|
getApiOrigin: (name: string) => string;
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -4,4 +4,5 @@ export * from './DynamicContentPickerForm';
|
|
|
4
4
|
export * from './PlatformsConfigurationDrawer';
|
|
5
5
|
export * from './LanguagesSelector';
|
|
6
6
|
export * from './RichMessageEditorSmart';
|
|
7
|
-
export * from './CampaignsConfigurationDrawer';
|
|
7
|
+
export * from './CampaignsConfigurationDrawer';
|
|
8
|
+
export * from './ExportCSV';
|
package/package.json
CHANGED
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@pushwoosh/grpc-bridge": "^1.5.36",
|
|
44
44
|
"@pushwoosh/http-client": "^2.5.0",
|
|
45
45
|
"@pushwoosh/rpc-v2-http-api-data": "^0.1.501",
|
|
46
|
+
"@pushwoosh/rpc-gateway-journey-data": "^0.26.206",
|
|
46
47
|
"@pushwoosh/session-store": "^2.5.0",
|
|
47
48
|
"react": "^16.14.0 || ^18.0.0",
|
|
48
49
|
"react-dom": "^16.14.0 || ^18.0.0"
|
|
@@ -50,5 +51,5 @@
|
|
|
50
51
|
"engines": {
|
|
51
52
|
"node": ">= 18"
|
|
52
53
|
},
|
|
53
|
-
"version": "1.0.
|
|
54
|
+
"version": "1.0.26"
|
|
54
55
|
}
|