Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate multiple commits from OpenDistro Kibana report #57

Merged
merged 3 commits into from
May 24, 2021
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 dashboards-reports/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "reportsDashboards",
"version": "1.0.0.0-beta1",
"opensearchDashboardsVersion": "1.0.0-beta1",
"requiredPlugins": ["navigation", "data"],
"requiredPlugins": ["navigation", "data", "opensearchDashboardsUtils"],
"optionalPlugins": ["share"],
"server": true,
"ui": true
Expand Down
27 changes: 5 additions & 22 deletions dashboards-reports/public/components/context_menu/context_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
displayLoadingModal,
addSuccessOrFailureToast,
contextMenuViewReports,
replaceQueryURL,
} from './context_menu_helpers';
import {
popoverMenu,
Expand All @@ -42,25 +43,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/opensearch_dashboards_utils/public';

const generateInContextReport = async (
timeRanges,
Expand Down Expand Up @@ -190,21 +173,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 @@ -33,6 +33,7 @@ import {
permissionsMissingOnGeneration,
} from './context_menu_ui';
import { timeRangeMatcher } from '../utils/utils';
import { unhashUrl } from '../../../../../src/plugins/opensearch_dashboards_utils/public';

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

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 @@ -84,7 +85,9 @@ export const contextMenuCreateReportDefinition = (baseURI) => {
};

export const displayLoadingModal = () => {
const opensearchDashboardsBody = document.getElementById('opensearch-dashboards-body');
const opensearchDashboardsBody = document.getElementById(
'opensearch-dashboards-body'
);
if (opensearchDashboardsBody) {
try {
const loadingModal = document.createElement('div');
Expand Down Expand Up @@ -133,3 +136,28 @@ export const addSuccessOrFailureToast = (status, reportSource) => {
}
}
};

export const replaceQueryURL = (pageUrl) => {
// we unhash the url in case OpenSearch Dashboards 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;
};
5 changes: 1 addition & 4 deletions dashboards-reports/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ import { PLUGIN_NAME } from '../common';

export class ReportsDashboardsPlugin
implements
Plugin<
ReportsDashboardsPluginSetup,
ReportsDashboardsPluginStart
> {
Plugin<ReportsDashboardsPluginSetup, ReportsDashboardsPluginStart> {
public setup(core: CoreSetup): ReportsDashboardsPluginSetup {
// Register an application into the side navigation menu
core.application.register({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@ describe('test create saved search report', () => {
}, 20000);

test('create report with expected file name extension', async () => {
const csvReport = await createSavedSearchReport(input, mockOpenSearchClient([]));
const csvReport = await createSavedSearchReport(
input,
mockOpenSearchClient([])
);
expect(csvReport.fileName).toContain('.csv');

input.report_definition.report_params.core_params.report_format = 'xlsx';
const xlsxReport = await createSavedSearchReport(input, mockOpenSearchClient([]));
const xlsxReport = await createSavedSearchReport(
input,
mockOpenSearchClient([])
);
expect(xlsxReport.fileName).toContain('.xlsx');
}, 20000);

Expand Down Expand Up @@ -289,6 +295,20 @@ describe('test create saved search report', () => {
}, 20000);
});

test('create report for data set contains null field value', async () => {
const hits = [
hit({ category: 'c1', customer_gender: 'Ma' }),
hit({ category: 'c2', customer_gender: 'le' }),
hit({ category: 'c3', customer_gender: null }),
];
const client = mockOpenSearchClient(hits);
const { dataUrl } = await createSavedSearchReport(input, client);

expect(dataUrl).toEqual(
'category,customer_gender\n' + 'c1,Ma\n' + 'c2,le\n' + 'c3, '
);
}, 20000);

/**
* Mock Elasticsearch client and return different mock objects based on endpoint and parameters.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,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 @@ -105,5 +105,5 @@ describe('test create visual report', () => {
expect(fileName).toContain(`${reportParams.report_name}`);
expect(fileName).toContain('.pdf');
expect(dataUrl).toBeDefined();
}, 30000);
}, 60000);
});
2 changes: 2 additions & 0 deletions dashboards-reports/server/routes/utils/dataReportHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ function traverse(data, keys, result = {}) {
*/
function sanitize(doc: any) {
for (const field in doc) {
if (doc[field] == null)
continue
if (
doc[field].toString().startsWith('+') ||
(doc[field].toString().startsWith('-') && typeof doc[field] !== "number") ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,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 @@ -188,7 +198,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