Skip to content
This repository has been archived by the owner on Aug 9, 2022. It is now read-only.

Fix pdf/png report generation for hashed page url #371

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kibana-reports/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "opendistroReportsKibana",
"version": "1.13.2.0",
"kibanaVersion": "7.10.2",
"requiredPlugins": ["navigation", "data"],
"requiredPlugins": ["navigation", "data", "kibanaUtils"],
"optionalPlugins": ["share"],
"server": true,
"ui": true
Expand Down
27 changes: 5 additions & 22 deletions kibana-reports/public/components/context_menu/context_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
displayLoadingModal,
addSuccessOrFailureToast,
contextMenuViewReports,
replaceQueryURL,
} from './context_menu_helpers';
import {
popoverMenu,
Expand All @@ -31,25 +32,7 @@ import {
} from './context_menu_ui';
import { timeRangeMatcher } from '../utils/utils';
import { parse } from 'url';

const replaceQueryURL = () => {
let url = location.pathname + location.hash;
let [, fromDateString, toDateString] = url.match(timeRangeMatcher);
fromDateString = fromDateString.replace(/[']+/g, '');

// convert time range to from date format in case time range is relative
const fromDateFormat = dateMath.parse(fromDateString);
toDateString = toDateString.replace(/[']+/g, '');
const toDateFormat = dateMath.parse(toDateString);

// replace to and from dates with absolute date
url = url.replace(fromDateString, "'" + fromDateFormat.toISOString() + "'");
url = url.replace(
toDateString + '))',
"'" + toDateFormat.toISOString() + "'))"
);
return url;
};
import { unhashUrl } from '../../../../../src/plugins/kibana_utils/public';

const generateInContextReport = async (
timeRanges,
Expand Down Expand Up @@ -179,21 +162,21 @@ $(function () {
// generate PDF onclick
$(document).on('click', '#generatePDF', function () {
const timeRanges = getTimeFieldsFromUrl();
const queryUrl = replaceQueryURL();
const queryUrl = replaceQueryURL(location.href);
generateInContextReport(timeRanges, queryUrl, 'pdf');
});

// generate PNG onclick
$(document).on('click', '#generatePNG', function () {
const timeRanges = getTimeFieldsFromUrl();
const queryUrl = replaceQueryURL();
const queryUrl = replaceQueryURL(location.href);
generateInContextReport(timeRanges, queryUrl, 'png');
});

// generate CSV onclick
$(document).on('click', '#generateCSV', function () {
const timeRanges = getTimeFieldsFromUrl();
const queryUrl = replaceQueryURL();
const queryUrl = replaceQueryURL(location.href);
const saved_search_id = getUuidFromUrl()[1];
generateInContextReport(timeRanges, queryUrl, 'csv', { saved_search_id });
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
permissionsMissingOnGeneration,
} from './context_menu_ui';
import { timeRangeMatcher } from '../utils/utils';
import { unhashUrl } from '../../../../../src/plugins/kibana_utils/public';

const getReportSourceURL = (baseURI) => {
const url = baseURI.substr(0, baseURI.indexOf('?'));
Expand All @@ -33,7 +34,7 @@ export const contextMenuViewReports = () =>
window.location.assign('opendistro_kibana_reports#/');

export const getTimeFieldsFromUrl = () => {
const url = window.location.href;
const url = unhashUrl(window.location.href);

let [, fromDateString, toDateString] = url.match(timeRangeMatcher);
fromDateString = fromDateString.replace(/[']+/g, '');
Expand Down Expand Up @@ -122,3 +123,28 @@ export const addSuccessOrFailureToast = (status, reportSource) => {
}
}
};

export const replaceQueryURL = (pageUrl) => {
// we unhash the url in case Kibana advanced UI setting 'state:storeInSessionStorage' is turned on
const unhashedUrl = new URL(unhashUrl(pageUrl));
let queryUrl = unhashedUrl.pathname + unhashedUrl.hash;
let [, fromDateString, toDateString] = queryUrl.match(timeRangeMatcher);
fromDateString = fromDateString.replace(/[']+/g, '');

// convert time range to from date format in case time range is relative
const fromDateFormat = dateMath.parse(fromDateString);
toDateString = toDateString.replace(/[']+/g, '');
const toDateFormat = dateMath.parse(toDateString);

// replace to and from dates with absolute date
queryUrl = queryUrl.replace(
fromDateString,
"'" + fromDateFormat.toISOString() + "'"
);
queryUrl = queryUrl.replace(
toDateString + '))',
"'" + toDateFormat.toISOString() + "'))"
);
console.log(`log output queryUrl\n` + queryUrl);
return queryUrl;
};
1 change: 0 additions & 1 deletion kibana-reports/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
} from './types';
import './components/context_menu/context_menu';
import { PLUGIN_NAME } from '../common';

export class OpendistroKibanaReportsPlugin
implements
Plugin<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('test create visual report', () => {
expect(fileName).toContain(`${reportParams.report_name}`);
expect(fileName).toContain('.png');
expect(dataUrl).toBeDefined();
}, 30000);
}, 60000);

test('create pdf report', async () => {
expect.assertions(3);
Expand All @@ -94,5 +94,5 @@ describe('test create visual report', () => {
expect(fileName).toContain(`${reportParams.report_name}`);
expect(fileName).toContain('.pdf');
expect(dataUrl).toBeDefined();
}, 30000);
}, 60000);
});
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,34 @@ export const createVisualReport = async (
? DOMPurify.sanitize(header)
: DEFAULT_REPORT_HEADER;
const reportFooter = footer ? DOMPurify.sanitize(footer) : '';

// add waitForDynamicContent function
const waitForDynamicContent = async(page, timeout = 30000, interval = 1000, checks = 5) => {
const maxChecks = timeout / interval;
let passedChecks = 0;
const waitForDynamicContent = async (
page,
timeout = 30000,
interval = 1000,
checks = 5
) => {
const maxChecks = timeout / interval;
let passedChecks = 0;
let previousLength = 0;

let i=0; while(i++ <= maxChecks){
let pageContent = await page.content();

let i = 0;
while (i++ <= maxChecks) {
let pageContent = await page.content();
let currentLength = pageContent.length;

(previousLength === 0 || previousLength != currentLength) ? passedChecks = 0 : passedChecks++;
if (passedChecks >= checks) { break; }


previousLength === 0 || previousLength != currentLength
? (passedChecks = 0)
: passedChecks++;
if (passedChecks >= checks) {
break;
}

previousLength = currentLength;
await page.waitFor(interval);
}
}
};

// set up puppeteer
const browser = await puppeteer.launch({
Expand Down Expand Up @@ -172,7 +182,7 @@ export const createVisualReport = async (
`report source can only be one of [Dashboard, Visualization]`
);
}

// wait for dynamic page content to render
await waitForDynamicContent(page);

Expand Down