Skip to content

Commit 3a85a26

Browse files
committed
[Reporting] Refactor types for API response data
1 parent d65743c commit 3a85a26

26 files changed

Lines changed: 3558 additions & 1251 deletions

x-pack/plugins/reporting/common/types.ts

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ export interface TaskRunResult {
5656

5757
export interface ReportSource {
5858
jobtype: string;
59-
kibana_name: string;
60-
kibana_id: string;
6159
created_by: string | false;
6260
payload: {
6361
headers: string; // encrypted headers
@@ -68,17 +66,20 @@ export interface ReportSource {
6866
isDeprecated?: boolean;
6967
};
7068
meta: { objectType: string; layout?: string };
71-
browser_type: string;
7269
migration_version: string;
73-
max_attempts: number;
74-
timeout: number;
75-
7670
status: JobStatus;
7771
attempts: number;
7872
output: TaskRunResult | null;
73+
created_at: string;
74+
75+
// fields with undefined values exist in report jobs that have not been claimed
76+
kibana_name?: string;
77+
kibana_id?: string;
78+
browser_type?: string;
79+
timeout?: number;
80+
max_attempts?: number;
7981
started_at?: string;
8082
completed_at?: string;
81-
created_at: string;
8283
process_expiration?: string | null; // must be set to null to clear the expiration
8384
}
8485

@@ -108,37 +109,20 @@ export interface JobContent {
108109
content: string;
109110
}
110111

111-
export interface ReportApiJSON {
112+
/* Info API response: report query results do not need to include the
113+
* payload.headers or output.content */
114+
type ReportSimple = Omit<ReportSource, 'payload' | 'output'> & {
115+
payload: Omit<ReportSource['payload'], 'headers'>;
116+
} & {
117+
output?: Omit<Partial<TaskRunResult>, 'content'>; // is undefined for report jobs that are not completed
118+
};
119+
120+
/*
121+
* The response format for all of the report job APIs
122+
*/
123+
export interface ReportApiJSON extends ReportSimple {
112124
id: string;
113125
index: string;
114-
kibana_name: string;
115-
kibana_id: string;
116-
browser_type: string | undefined;
117-
created_at: string;
118-
jobtype: string;
119-
created_by: string | false;
120-
timeout?: number;
121-
output?: {
122-
content_type: string;
123-
size: number;
124-
warnings?: string[];
125-
};
126-
process_expiration?: string;
127-
completed_at: string | undefined;
128-
payload: {
129-
layout?: LayoutParams;
130-
title: string;
131-
browserTimezone?: string;
132-
isDeprecated?: boolean;
133-
};
134-
meta: {
135-
layout?: string;
136-
objectType: string;
137-
};
138-
max_attempts: number;
139-
started_at: string | undefined;
140-
attempts: number;
141-
status: string;
142126
}
143127

144128
export interface LicenseCheckResults {
@@ -147,13 +131,14 @@ export interface LicenseCheckResults {
147131
message: string;
148132
}
149133

134+
/* Notifier Toasts */
150135
export interface JobSummary {
151136
id: JobId;
152137
status: JobStatus;
153-
title: string;
154-
jobtype: string;
155-
maxSizeReached?: boolean;
156-
csvContainsFormulas?: boolean;
138+
jobtype: ReportSource['jobtype'];
139+
title: ReportSource['payload']['title'];
140+
maxSizeReached: TaskRunResult['max_size_reached'];
141+
csvContainsFormulas: TaskRunResult['csv_contains_formulas'];
157142
}
158143

159144
export interface JobSummarySet {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { JobId, ReportApiJSON, ReportSource, TaskRunResult } from '../../common/types';
9+
10+
type ReportPayload = ReportSource['payload'];
11+
12+
/*
13+
* This class represents a report job for the UI
14+
* It can be instantiated with ReportApiJSON: the response data format for the report job APIs
15+
*/
16+
export class Job {
17+
public id: JobId;
18+
public index: string;
19+
20+
public objectType: ReportPayload['objectType'];
21+
public title: ReportPayload['title'];
22+
public isDeprecated: ReportPayload['isDeprecated'];
23+
public browserTimezone?: ReportPayload['browserTimezone'];
24+
public layout: ReportPayload['layout'];
25+
26+
public jobtype: ReportSource['jobtype'];
27+
public created_by: ReportSource['created_by'];
28+
public created_at: ReportSource['created_at'];
29+
public started_at: ReportSource['started_at'];
30+
public completed_at: ReportSource['completed_at'];
31+
public status: ReportSource['status'];
32+
public attempts: ReportSource['attempts'];
33+
public max_attempts: ReportSource['max_attempts'];
34+
35+
public timeout: ReportSource['timeout'];
36+
public kibana_name: ReportSource['kibana_name'];
37+
public kibana_id: ReportSource['kibana_id'];
38+
public browser_type: ReportSource['browser_type'];
39+
40+
public size?: TaskRunResult['size'];
41+
public content_type?: TaskRunResult['content_type'];
42+
public csv_contains_formulas?: TaskRunResult['csv_contains_formulas'];
43+
public max_size_reached?: TaskRunResult['max_size_reached'];
44+
public warnings?: TaskRunResult['warnings'];
45+
46+
constructor(report: ReportApiJSON) {
47+
this.id = report.id;
48+
this.index = report.index;
49+
50+
this.jobtype = report.jobtype;
51+
this.objectType = report.payload.objectType;
52+
this.title = report.payload.title;
53+
this.layout = report.payload.layout;
54+
this.created_by = report.created_by;
55+
this.created_at = report.created_at;
56+
this.started_at = report.started_at;
57+
this.completed_at = report.completed_at;
58+
this.status = report.status;
59+
this.attempts = report.attempts;
60+
this.max_attempts = report.max_attempts;
61+
62+
this.timeout = report.timeout;
63+
this.kibana_name = report.kibana_name;
64+
this.kibana_id = report.kibana_id;
65+
this.browser_type = report.browser_type;
66+
this.browserTimezone = report.payload.browserTimezone;
67+
this.size = report.output?.size;
68+
69+
this.isDeprecated = report.payload.isDeprecated || false;
70+
this.csv_contains_formulas = report.output?.csv_contains_formulas;
71+
this.max_size_reached = report.output?.max_size_reached;
72+
this.warnings = report.output?.warnings;
73+
}
74+
}

x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,45 @@ import {
1515
API_MIGRATE_ILM_POLICY_URL,
1616
REPORTING_MANAGEMENT_HOME,
1717
} from '../../../common/constants';
18-
import {
19-
DownloadReportFn,
20-
JobId,
21-
ManagementLinkFn,
22-
ReportApiJSON,
23-
ReportDocument,
24-
ReportSource,
25-
} from '../../../common/types';
18+
import { DownloadReportFn, JobId, ManagementLinkFn, ReportApiJSON } from '../../../common/types';
2619
import { add } from '../../notifier/job_completion_notifications';
27-
28-
export interface JobQueueEntry {
29-
_id: string;
30-
_source: ReportSource;
31-
}
20+
import { Job } from '../job';
3221

3322
export interface JobContent {
3423
content: string;
3524
content_type: boolean;
3625
}
3726

38-
interface JobParams {
39-
[paramName: string]: any;
40-
}
41-
4227
export interface DiagnoseResponse {
4328
help: string[];
4429
success: boolean;
4530
logs: string;
4631
}
4732

48-
export class ReportingAPIClient {
33+
interface JobParams {
34+
[paramName: string]: any;
35+
}
36+
37+
interface IReportingAPI {
38+
getReportURL(jobId: string): string;
39+
downloadReport(jobId: string): void;
40+
deleteReport(jobId: string): Promise<void>;
41+
list(page: number, jobIds: string[]): Promise<Job[]>;
42+
total(): Promise<number>;
43+
getError(jobId: string): Promise<JobContent>;
44+
getInfo(jobId: string): Promise<Job>;
45+
findForJobIds(jobIds: string[]): Promise<Job[]>;
46+
getReportingJobPath(exportType: string, jobParams: JobParams): string;
47+
createReportingJob(exportType: string, jobParams: any): Promise<Job>;
48+
getServerBasePath(): string;
49+
verifyConfig(): Promise<DiagnoseResponse>;
50+
verifyBrowser(): Promise<DiagnoseResponse>;
51+
verifyScreenCapture(): Promise<DiagnoseResponse>;
52+
getManagementLink: ManagementLinkFn;
53+
getDownloadLink: DownloadReportFn;
54+
}
55+
56+
export class ReportingAPIClient implements IReportingAPI {
4957
private http: HttpSetup;
5058

5159
constructor(http: HttpSetup) {
@@ -71,68 +79,75 @@ export class ReportingAPIClient {
7179
});
7280
}
7381

74-
public list = (page = 0, jobIds: string[] = []): Promise<JobQueueEntry[]> => {
82+
public async list(page = 0, jobIds: string[] = []) {
7583
const query = { page } as any;
7684
if (jobIds.length > 0) {
7785
// Only getting the first 10, to prevent URL overflows
7886
query.ids = jobIds.slice(0, 10).join(',');
7987
}
8088

81-
return this.http.get(`${API_LIST_URL}/list`, {
89+
const jobQueueEntries: ReportApiJSON[] = await this.http.get(`${API_LIST_URL}/list`, {
8290
query,
8391
asSystemRequest: true,
8492
});
85-
};
8693

87-
public total(): Promise<number> {
88-
return this.http.get(`${API_LIST_URL}/count`, {
94+
return jobQueueEntries.map((report) => new Job(report));
95+
}
96+
97+
public async total() {
98+
return await this.http.get(`${API_LIST_URL}/count`, {
8999
asSystemRequest: true,
90100
});
91101
}
92102

93-
public getContent(jobId: string): Promise<JobContent> {
94-
return this.http.get(`${API_LIST_URL}/output/${jobId}`, {
103+
public async getError(jobId: string) {
104+
return await this.http.get(`${API_LIST_URL}/output/${jobId}`, {
95105
asSystemRequest: true,
96106
});
97107
}
98108

99-
public getInfo(jobId: string): Promise<ReportApiJSON> {
100-
return this.http.get(`${API_LIST_URL}/info/${jobId}`, {
109+
public async getInfo(jobId: string) {
110+
const report: ReportApiJSON = await this.http.get(`${API_LIST_URL}/info/${jobId}`, {
101111
asSystemRequest: true,
102112
});
113+
return new Job(report);
103114
}
104115

105-
public findForJobIds = (jobIds: JobId[]): Promise<ReportDocument[]> => {
106-
return this.http.fetch(`${API_LIST_URL}/list`, {
116+
public async findForJobIds(jobIds: JobId[]) {
117+
const reports: ReportApiJSON[] = await this.http.fetch(`${API_LIST_URL}/list`, {
107118
query: { page: 0, ids: jobIds.join(',') },
108119
method: 'GET',
109120
});
110-
};
121+
return reports.map((report) => new Job(report));
122+
}
111123

112124
/*
113125
* Return a URL to queue a job, with the job params encoded in the query string of the URL. Used for copying POST URL
114126
*/
115-
public getReportingJobPath = (exportType: string, jobParams: JobParams) => {
127+
public getReportingJobPath(exportType: string, jobParams: JobParams) {
116128
const params = stringify({ jobParams: rison.encode(jobParams) });
117129
return `${this.http.basePath.prepend(API_BASE_GENERATE)}/${exportType}?${params}`;
118-
};
130+
}
119131

120132
/*
121133
* Sends a request to queue a job, with the job params in the POST body
122134
*/
123-
public createReportingJob = async (exportType: string, jobParams: any) => {
135+
public async createReportingJob(exportType: string, jobParams: any) {
124136
const jobParamsRison = rison.encode(jobParams);
125-
const resp = await this.http.post(`${API_BASE_GENERATE}/${exportType}`, {
126-
method: 'POST',
127-
body: JSON.stringify({
128-
jobParams: jobParamsRison,
129-
}),
130-
});
137+
const resp: { job: ReportApiJSON } = await this.http.post(
138+
`${API_BASE_GENERATE}/${exportType}`,
139+
{
140+
method: 'POST',
141+
body: JSON.stringify({
142+
jobParams: jobParamsRison,
143+
}),
144+
}
145+
);
131146

132147
add(resp.job.id);
133148

134-
return resp;
135-
};
149+
return new Job(resp.job);
150+
}
136151

137152
public getManagementLink: ManagementLinkFn = () =>
138153
this.http.basePath.prepend(REPORTING_MANAGEMENT_HOME);
@@ -148,28 +163,31 @@ export class ReportingAPIClient {
148163
/*
149164
* Diagnostic-related API calls
150165
*/
151-
public verifyConfig = (): Promise<DiagnoseResponse> =>
152-
this.http.post(`${API_BASE_URL}/diagnose/config`, {
166+
public async verifyConfig() {
167+
return await this.http.post(`${API_BASE_URL}/diagnose/config`, {
153168
asSystemRequest: true,
154169
});
170+
}
155171

156172
/*
157173
* Diagnostic-related API calls
158174
*/
159-
public verifyBrowser = (): Promise<DiagnoseResponse> =>
160-
this.http.post(`${API_BASE_URL}/diagnose/browser`, {
175+
public async verifyBrowser() {
176+
return await this.http.post(`${API_BASE_URL}/diagnose/browser`, {
161177
asSystemRequest: true,
162178
});
179+
}
163180

164181
/*
165182
* Diagnostic-related API calls
166183
*/
167-
public verifyScreenCapture = (): Promise<DiagnoseResponse> =>
168-
this.http.post(`${API_BASE_URL}/diagnose/screenshot`, {
184+
public async verifyScreenCapture() {
185+
return await this.http.post(`${API_BASE_URL}/diagnose/screenshot`, {
169186
asSystemRequest: true,
170187
});
188+
}
171189

172-
public migrateReportingIndicesIlmPolicy = (): Promise<void> => {
173-
return this.http.put(`${API_MIGRATE_ILM_POLICY_URL}`);
174-
};
190+
public async migrateReportingIndicesIlmPolicy() {
191+
return await this.http.put(`${API_MIGRATE_ILM_POLICY_URL}`);
192+
}
175193
}

0 commit comments

Comments
 (0)