From 021ac328f63576c1d0122bbee117aa11cef93862 Mon Sep 17 00:00:00 2001 From: Zhongnan Su Date: Fri, 21 May 2021 14:29:56 -0700 Subject: [PATCH] Unhash page url in case store URLs in session storage is enabled from Kibana advanced setting (#371) --- kibana-reports/kibana.json | 2 +- .../components/context_menu/context_menu.js | 27 +++----------- .../context_menu/context_menu_helpers.js | 28 ++++++++++++++- kibana-reports/public/plugin.ts | 1 - .../__tests__/visualReportHelper.test.ts | 4 +-- .../utils/visual_report/visualReportHelper.ts | 36 ++++++++++++------- 6 files changed, 58 insertions(+), 40 deletions(-) diff --git a/kibana-reports/kibana.json b/kibana-reports/kibana.json index 3b12cf20..5bbd74df 100644 --- a/kibana-reports/kibana.json +++ b/kibana-reports/kibana.json @@ -2,7 +2,7 @@ "id": "opendistroReportsKibana", "version": "1.13.0.0", "kibanaVersion": "7.10.2", - "requiredPlugins": ["navigation", "data"], + "requiredPlugins": ["navigation", "data", "kibanaUtils"], "optionalPlugins": ["share"], "server": true, "ui": true diff --git a/kibana-reports/public/components/context_menu/context_menu.js b/kibana-reports/public/components/context_menu/context_menu.js index 19268b5b..244d045e 100644 --- a/kibana-reports/public/components/context_menu/context_menu.js +++ b/kibana-reports/public/components/context_menu/context_menu.js @@ -23,6 +23,7 @@ import { displayLoadingModal, addSuccessOrFailureToast, contextMenuViewReports, + replaceQueryURL, } from './context_menu_helpers'; import { popoverMenu, @@ -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, @@ -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 }); }); diff --git a/kibana-reports/public/components/context_menu/context_menu_helpers.js b/kibana-reports/public/components/context_menu/context_menu_helpers.js index 5d154d4e..ebfd0fc1 100644 --- a/kibana-reports/public/components/context_menu/context_menu_helpers.js +++ b/kibana-reports/public/components/context_menu/context_menu_helpers.js @@ -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('?')); @@ -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, ''); @@ -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; +}; diff --git a/kibana-reports/public/plugin.ts b/kibana-reports/public/plugin.ts index c3bf5f45..9d7f6d07 100644 --- a/kibana-reports/public/plugin.ts +++ b/kibana-reports/public/plugin.ts @@ -26,7 +26,6 @@ import { } from './types'; import './components/context_menu/context_menu'; import { PLUGIN_NAME } from '../common'; - export class OpendistroKibanaReportsPlugin implements Plugin< diff --git a/kibana-reports/server/routes/utils/__tests__/visualReportHelper.test.ts b/kibana-reports/server/routes/utils/__tests__/visualReportHelper.test.ts index e015bb5a..fb86b014 100644 --- a/kibana-reports/server/routes/utils/__tests__/visualReportHelper.test.ts +++ b/kibana-reports/server/routes/utils/__tests__/visualReportHelper.test.ts @@ -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); @@ -94,5 +94,5 @@ describe('test create visual report', () => { expect(fileName).toContain(`${reportParams.report_name}`); expect(fileName).toContain('.pdf'); expect(dataUrl).toBeDefined(); - }, 30000); + }, 60000); }); diff --git a/kibana-reports/server/routes/utils/visual_report/visualReportHelper.ts b/kibana-reports/server/routes/utils/visual_report/visualReportHelper.ts index c62b845e..bb8eb4f8 100644 --- a/kibana-reports/server/routes/utils/visual_report/visualReportHelper.ts +++ b/kibana-reports/server/routes/utils/visual_report/visualReportHelper.ts @@ -59,24 +59,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({ @@ -160,7 +170,7 @@ export const createVisualReport = async ( `report source can only be one of [Dashboard, Visualization]` ); } - + // wait for dynamic page content to render await waitForDynamicContent(page);