/
report.ts
117 lines (106 loc) · 4.05 KB
/
report.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// (C) 2007-2019 GoodData Corporation
import { AFM, ExecuteAFM } from "@gooddata/typings";
import compact from "lodash/compact";
import isArray from "lodash/isArray";
import { ERROR_RESTRICTED_CODE, ERROR_RESTRICTED_MESSAGE } from "../constants/errors";
import {
convertAbsoluteDateFilter,
convertRelativeDateFilter,
} from "../DataLayer/converters/FilterConverter";
import { convertFilter as convertAttributeFilter } from "../execution/execute-afm.convert";
import { IBaseExportConfig, IExportConfig, IExportResponse } from "../interfaces";
import { ApiResponseError, XhrModule, ApiResponse } from "../xhr";
import { handleHeadPolling, IPollingOptions } from "../util";
import { isExportFinished } from "../utils/export";
interface IExtendedExportConfig extends IBaseExportConfig {
showFilters?: ExecuteAFM.CompatibilityFilter[];
}
interface IResultExport {
executionResult: string;
exportConfig: IExtendedExportConfig;
}
interface IExportResultPayload {
resultExport: IResultExport;
}
/**
* Functions for working with reports
*
* @Class report
* @module report
*/
export class ReportModule {
constructor(private xhr: XhrModule) {}
/**
* exportResult
* request new result export
* request new export of existing AFM execution
*
* @experimental
* @method exportResult
* @param {String} projectId GoodData projectId
* @param {String} executionResult report which should be exported
* @param {IExportConfig} exportConfig requested export options
* @param {Object} pollingOptions for polling (maxAttempts, pollStep)
* @return {Promise} Resolves if export successfully,
* Reject if export has error (network error, api error)
*/
public exportResult(
projectId: string,
executionResult: string,
exportConfig: IExportConfig = {},
pollingOptions: IPollingOptions = {},
): Promise<IExportResponse> {
const { showFilters } = exportConfig;
const sanitizedFilters = this.sanitizeFilters(showFilters);
const requestPayload: IExportResultPayload = {
resultExport: {
executionResult,
exportConfig: {
...exportConfig,
showFilters: sanitizedFilters,
},
},
};
return this.xhr
.post(`/gdc/internal/projects/${projectId}/exportResult`, { body: requestPayload })
.then((response: ApiResponse) => response.getData())
.then((data: IExportResponse) =>
handleHeadPolling(this.xhr.get.bind(this.xhr), data.uri, isExportFinished, pollingOptions),
)
.catch(this.handleExportResultError);
}
private handleExportResultError = (error: ApiResponseError | Error): Promise<Error> => {
if (
this.isApiResponseError(error) &&
error.response.status === 400 &&
error.responseBody.indexOf(ERROR_RESTRICTED_CODE) !== -1
) {
return Promise.reject({
...error,
message: ERROR_RESTRICTED_MESSAGE,
});
}
return Promise.reject(error);
};
private isApiResponseError(error: ApiResponseError | Error): error is ApiResponseError {
return (error as ApiResponseError).response !== undefined;
}
private sanitizeFilters(
showFilters?: AFM.CompatibilityFilter[],
): ExecuteAFM.CompatibilityFilter[] | undefined {
if (isArray(showFilters) && showFilters.length > 0) {
return compact(showFilters.map(this.sanitizeFilter));
}
return undefined;
}
private sanitizeFilter(filter: AFM.CompatibilityFilter): ExecuteAFM.CompatibilityFilter | null {
if (AFM.isAttributeFilter(filter)) {
return convertAttributeFilter(filter);
} else if (AFM.isAbsoluteDateFilter(filter)) {
return convertAbsoluteDateFilter(filter);
} else if (AFM.isRelativeDateFilter(filter)) {
return convertRelativeDateFilter(filter);
}
return filter;
}
}