Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { connect } from 'react-redux';
import { compose, withProps } from 'recompose';
import { jobCompletionNotifications } from '../../../../../reporting/public/lib/job_completion_notifications';
import * as jobCompletionNotifications from '../../../../../reporting/public/lib/job_completion_notifications';
// @ts-ignore Untyped local
import { getWorkpad, getPages } from '../../../state/selectors/workpad';
// @ts-ignore Untyped local
Expand Down
3 changes: 3 additions & 0 deletions x-pack/legacy/plugins/reporting/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY =
export const API_BASE_URL = '/api/reporting'; // "Generation URL" from share menu
export const API_BASE_URL_V1 = '/api/reporting/v1'; //
export const API_BASE_GENERATE_V1 = `${API_BASE_URL_V1}/generate`;
export const API_LIST_URL = '/api/reporting/jobs';
export const API_GENERATE_IMMEDIATE = `${API_BASE_URL_V1}/generate/immediate/csv/saved-object`;

export const CONTENT_TYPE_CSV = 'text/csv';
export const CSV_REPORTING_ACTION = 'downloadCsvReport';

export const WHITELISTED_JOB_CONTENT_TYPES = [
'application/json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
import { EuiButton, EuiCopy, EuiForm, EuiFormRow, EuiSpacer, EuiText } from '@elastic/eui';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import React, { Component, ReactElement } from 'react';
import { KFetchError } from 'ui/kfetch/kfetch_error';
import { toastNotifications } from 'ui/notify';
import url from 'url';
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
import { reportingClient } from '../lib/reporting_client';
import * as reportingClient from '../lib/reporting_client';

interface Props {
reportType: string;
Expand Down Expand Up @@ -217,8 +216,8 @@ class ReportingPanelContentUi extends Component<Props, State> {
});
this.props.onClose();
})
.catch((kfetchError: KFetchError) => {
if (kfetchError.message === 'not exportable') {
.catch((error: any) => {
if (error.message === 'not exportable') {
return toastNotifications.addWarning({
title: intl.formatMessage(
{
Expand All @@ -237,7 +236,7 @@ class ReportingPanelContentUi extends Component<Props, State> {
}

const defaultMessage =
kfetchError.res.status === 403 ? (
error?.res?.status === 403 ? (
<FormattedMessage
id="xpack.reporting.panelContent.noPermissionToGenerateReportDescription"
defaultMessage="You don't have permission to generate this report."
Expand All @@ -254,7 +253,7 @@ class ReportingPanelContentUi extends Component<Props, State> {
id: 'xpack.reporting.panelContent.notification.reportingErrorTitle',
defaultMessage: 'Reporting error',
}),
text: toMountPoint(kfetchError.message || defaultMessage),
text: toMountPoint(error.message || defaultMessage),
'data-test-subj': 'queueReportError',
});
});
Expand Down
6 changes: 4 additions & 2 deletions x-pack/legacy/plugins/reporting/public/lib/download_report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import chrome from 'ui/chrome';
import { npStart } from 'ui/new_platform';
import { API_BASE_URL } from '../../common/constants';

const { core } = npStart;

export function getReportURL(jobId: string) {
const apiBaseUrl = chrome.addBasePath(API_BASE_URL);
const apiBaseUrl = core.http.basePath.prepend(API_BASE_URL);
const downloadLink = `${apiBaseUrl}/jobs/download/${jobId}`;

return downloadLink;
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY } from '../../common/constants';

type jobId = string;

const set = (jobs: any) => {
sessionStorage.setItem(JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, JSON.stringify(jobs));
};

const getAll = () => {
const sessionValue = sessionStorage.getItem(JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY);
return sessionValue ? JSON.parse(sessionValue) : [];
};

export const add = (jobId: jobId) => {
const jobs = getAll();
jobs.push(jobId);
set(jobs);
};

export const remove = (jobId: jobId) => {
const jobs = getAll();
const index = jobs.indexOf(jobId);

if (!index) {
throw new Error('Unable to find job to remove it');
}

jobs.splice(index, 1);
set(jobs);
};
26 changes: 10 additions & 16 deletions x-pack/legacy/plugins/reporting/public/lib/job_queue_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { kfetch } from 'ui/kfetch';
import { npStart } from 'ui/new_platform';
import { API_LIST_URL } from '../../common/constants';

const API_BASE_URL = '/api/reporting/jobs';
const { core } = npStart;

export interface JobQueueEntry {
_id: string;
Expand Down Expand Up @@ -52,40 +53,33 @@ export interface JobInfo {
}

class JobQueueClient {
public list = (page = 0, jobIds?: string[]): Promise<JobQueueEntry[]> => {
public list = (page = 0, jobIds: string[] = []): Promise<JobQueueEntry[]> => {
const query = { page } as any;
if (jobIds && jobIds.length > 0) {
if (jobIds.length > 0) {
// Only getting the first 10, to prevent URL overflows
query.ids = jobIds.slice(0, 10).join(',');
}
return kfetch({
method: 'GET',
pathname: `${API_BASE_URL}/list`,

return core.http.get(`${API_LIST_URL}/list`, {
query,
asSystemRequest: true,
});
};

public total(): Promise<number> {
return kfetch({
method: 'GET',
pathname: `${API_BASE_URL}/count`,
return core.http.get(`${API_LIST_URL}/count`, {
asSystemRequest: true,
});
}

public getContent(jobId: string): Promise<JobContent> {
return kfetch({
method: 'GET',
pathname: `${API_BASE_URL}/output/${jobId}`,
return core.http.get(`${API_LIST_URL}/output/${jobId}`, {
asSystemRequest: true,
});
}

public getInfo(jobId: string): Promise<JobInfo> {
return kfetch({
method: 'GET',
pathname: `${API_BASE_URL}/info/${jobId}`,
return core.http.get(`${API_LIST_URL}/info/${jobId}`, {
asSystemRequest: true,
});
}
Expand Down
49 changes: 23 additions & 26 deletions x-pack/legacy/plugins/reporting/public/lib/reporting_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,37 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { kfetch } from 'ui/kfetch';
import { npStart } from 'ui/new_platform';
import querystring from 'querystring';

const { core } = npStart;

// @ts-ignore
import rison from 'rison-node';
import chrome from 'ui/chrome';
import { QueryString } from 'ui/utils/query_string';
import { jobCompletionNotifications } from './job_completion_notifications';
import { add } from './job_completion_notifications';

const API_BASE_URL = '/api/reporting/generate';

interface JobParams {
[paramName: string]: any;
}

class ReportingClient {
public getReportingJobPath = (exportType: string, jobParams: JobParams) => {
return `${chrome.addBasePath(API_BASE_URL)}/${exportType}?${QueryString.param(
'jobParams',
rison.encode(jobParams)
)}`;
};

public createReportingJob = async (exportType: string, jobParams: any) => {
const jobParamsRison = rison.encode(jobParams);
const resp = await kfetch({
method: 'POST',
pathname: `${API_BASE_URL}/${exportType}`,
body: JSON.stringify({
jobParams: jobParamsRison,
}),
});
jobCompletionNotifications.add(resp.job.id);
return resp;
};
}
export const getReportingJobPath = (exportType: string, jobParams: JobParams) => {
const params = querystring.stringify({ jobParams: rison.encode(jobParams) });

return `${core.http.basePath.prepend(API_BASE_URL)}/${exportType}?${params}`;
};

export const createReportingJob = async (exportType: string, jobParams: any) => {
const jobParamsRison = rison.encode(jobParams);
const resp = await core.http.post(`${API_BASE_URL}/${exportType}`, {
method: 'POST',
body: JSON.stringify({
jobParams: jobParamsRison,
}),
});

add(resp.job.id);

export const reportingClient = new ReportingClient();
return resp;
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import dateMath from '@elastic/datemath';
import { i18n } from '@kbn/i18n';
import moment from 'moment-timezone';

import { kfetch } from 'ui/kfetch';
import { toastNotifications } from 'ui/notify';
import chrome from 'ui/chrome';

import { npSetup } from 'ui/new_platform';
import { npSetup, npStart } from 'ui/new_platform';
import { IAction, IncompatibleActionError } from '../../../../../../src/plugins/ui_actions/public';

import {
Expand All @@ -22,11 +18,9 @@ import {
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/constants';
import { ISearchEmbeddable } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/types';

import { API_BASE_URL_V1 } from '../../common/constants';

const API_BASE_URL = `${API_BASE_URL_V1}/generate/immediate/csv/saved-object`;
import { API_GENERATE_IMMEDIATE, CSV_REPORTING_ACTION } from '../../common/constants';

const CSV_REPORTING_ACTION = 'downloadCsvReport';
const { core } = npStart;

function isSavedSearchEmbeddable(
embeddable: IEmbeddable | ISearchEmbeddable
Expand Down Expand Up @@ -71,12 +65,6 @@ class GetCsvReportPanelAction implements IAction<ActionContext> {
}

public isCompatible = async (context: ActionContext) => {
const enablePanelActionDownload = chrome.getInjected('enablePanelActionDownload');

if (!enablePanelActionDownload) {
return false;
}

const { embeddable } = context;

return embeddable.getInput().viewMode !== ViewMode.EDIT && embeddable.type === 'search';
Expand All @@ -100,7 +88,7 @@ class GetCsvReportPanelAction implements IAction<ActionContext> {
const searchEmbeddable = embeddable;
const searchRequestBody = await this.getSearchRequestBody({ searchEmbeddable });
const state = _.pick(searchRequestBody, ['sort', 'docvalue_fields', 'query']);
const kibanaTimezone = chrome.getUiSettingsClient().get('dateFormat:tz');
const kibanaTimezone = core.uiSettings.get('dateFormat:tz');

const id = `search:${embeddable.getSavedSearch().id}`;
const filename = embeddable.getTitle();
Expand All @@ -125,7 +113,7 @@ class GetCsvReportPanelAction implements IAction<ActionContext> {

this.isDownloading = true;

toastNotifications.addSuccess({
core.notifications.toasts.addSuccess({
title: i18n.translate('xpack.reporting.dashboard.csvDownloadStartedTitle', {
defaultMessage: `CSV Download Started`,
}),
Expand All @@ -135,7 +123,8 @@ class GetCsvReportPanelAction implements IAction<ActionContext> {
'data-test-subj': 'csvDownloadStarted',
});

await kfetch({ method: 'POST', pathname: `${API_BASE_URL}/${id}`, body })
await core.http
.post(`${API_GENERATE_IMMEDIATE}/${id}`, { body })
.then((rawResponse: string) => {
this.isDownloading = false;

Expand All @@ -162,7 +151,7 @@ class GetCsvReportPanelAction implements IAction<ActionContext> {

private onGenerationFail(error: Error) {
this.isDownloading = false;
toastNotifications.addDanger({
core.notifications.toasts.addDanger({
title: i18n.translate('xpack.reporting.dashboard.failedCsvDownloadTitle', {
defaultMessage: `CSV download failed`,
}),
Expand All @@ -175,5 +164,6 @@ class GetCsvReportPanelAction implements IAction<ActionContext> {
}

const action = new GetCsvReportPanelAction();

npSetup.plugins.uiActions.registerAction(action);
npSetup.plugins.uiActions.attachAction(CONTEXT_MENU_TRIGGER, action.id);
Loading