Skip to content

Commit

Permalink
Make the generated report use the correct background color (#165)
Browse files Browse the repository at this point in the history
Also:
* Remove font and color overrides from generated reports
* Remove side-nav from the exported report
* Avoid creating a footer when it has no content
* Fix report dimensions

Signed-off-by: Miki <[email protected]>
  • Loading branch information
AMoo-Miki authored Aug 31, 2023
1 parent 0c7dd27 commit 13288ec
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 33 deletions.
17 changes: 5 additions & 12 deletions public/components/visual_report/assets/report_styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,14 @@ iframe, embed, object {
display: none !important;
}
/* nice padding + matches Kibana default UI colors you could also set this to inherit if
the wrapper gets inserted inside a kibana section. I might also remove the manual text color here as well, potentially */
.reportWrapper {
padding: 8px;
background-color: #fafbfd;
}
/* Notice that I'm using an ID of #reportingHeader, and #reportingFooter, instead of a classname (.reportingHeader, .reportingFooter). This is
in order to force specificity here higher in case any other styles would conflict */
#reportingHeader,
#reportingFooter {
font-family: 'Inter UI', -apple-system, BlinkMacSystemFont, 'Segoe UI',
Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol';
background-color: #fff;
border: 1px solid #d3dae6;
box-shadow: 0 2px 2px -1px rgba(152, 162, 179, 0.3),
0 1px 5px -2px rgba(152, 162, 179, 0.3);
Expand Down Expand Up @@ -99,11 +92,11 @@ iframe, embed, object {
margin-bottom: inherit;
}
</style>
<style>
/* mde style sheet*/
.mde-preview .mde-preview-content {
padding: 10px;
}
<style>
/* mde style sheet*/
.mde-preview .mde-preview-content {
padding: 10px;
}
.mde-preview .mde-preview-content p,
.mde-preview .mde-preview-content blockquote,
.mde-preview .mde-preview-content ul,
Expand Down
58 changes: 37 additions & 21 deletions public/components/visual_report/generate_report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ const removeNonReportElements = (
doc
.querySelectorAll("button[class^='euiButton']:not(.visLegend__button)")
.forEach((e) => e.remove());
// remove top navBar
doc.querySelectorAll("[class^='euiHeader']").forEach((e) => e.remove());

// remove anything that shouldn't be shared
doc.querySelectorAll('.hide-for-sharing').forEach((e) => e.remove());

// remove visualization editor
if (reportSource === VISUAL_REPORT_TYPE.visualization) {
doc.querySelector('[data-test-subj="splitPanelResizer"]')?.remove();
Expand All @@ -84,6 +86,8 @@ const addReportHeader = (doc: Document, header: string) => {
};

const addReportFooter = (doc: Document, footer: string) => {
// If there is no content, don't bother creating an element
if (!footer) return;
const footerHtml = `<div id="reportingFooter">
<div class="mde-preview" data-testid="mde-preview">
<div class="mde-preview-content">${footer}</div>
Expand All @@ -104,19 +108,6 @@ const addReportStyle = (doc: Document, style: string) => {
doc.body.style.paddingTop = '0px';
};

const computeHeight = (height: number, header: string, footer: string) => {
let computedHeight = height;
const headerLines = header.split('\n').length;
const footerLines = footer.split('\n').length;
if (headerLines) {
computedHeight += 24 * headerLines;
}
if (footerLines) {
computedHeight += 50 + 24 * footerLines;
}
return computedHeight;
};

export const generateReport = async (id: string, forceDelay = 15000) => {
const http = uiSettingsService.getHttpClient();
const useForeignObjectRendering = uiSettingsService.get('reporting:useFOR');
Expand Down Expand Up @@ -179,26 +170,48 @@ export const generateReport = async (id: string, forceDelay = 15000) => {
await timeout(1000);
}

const width = document.documentElement.scrollWidth;
const height = computeHeight(
document.documentElement.scrollHeight,
header,
footer
);
/* The left-nav impacts the dimensions of the report; `#opensearch-dashboards-body`
* is the safest way to know the width.
* Since `html2canvas` without `foreignObjectRendering` copies computed styles of
* elements, we cannot rely on re-calculation of cloned widths after we remove all
* `.hide-for-sharing` elements in `removeNonReportElements`. The only option is to
* produce a narrower report when left-nav is docked.
*
* If `#opensearch-dashboards-body` is not found, it will fall back to `scrollWidth`.
*/
const innerBodyDims = document.getElementById('opensearch-dashboards-body')?.getBoundingClientRect();
const width = innerBodyDims?.width || document.documentElement.scrollWidth;
const height = document.documentElement.scrollHeight;

const documentBackgroundColor: string = (window.getComputedStyle(document.documentElement) as CSSStyleDeclaration).backgroundColor;
const bgColor = documentBackgroundColor.startsWith('#')
? documentBackgroundColor
// convert rgb() and rgba() to hex
: '#' + documentBackgroundColor.split(/[,()]/, 4).slice(1).map(v => parseInt(v).toString(16)).join('');

/* ToDo: `html2canvas` doesn't copy stylesheets when `foreignObjectRendering` is false. As a result
* `@font-family` definitions are lost; find a way to get them from the document and add
* them to the cloned document.
* ToDo: Don't add the header and footer to the document before cloning as they mess with what the
* users see.
*/
return html2canvas(document.body, {
scrollX: 0,
scrollY: 0,
windowWidth: width,
windowHeight: height,
width,
height,
backgroundColor: bgColor,
imageTimeout: 30000,
useCORS: true,
removeContainer: false,
allowTaint: true,
foreignObjectRendering: useForeignObjectRendering,
onclone: function (documentClone) {
removeNonReportElements(documentClone, reportSource);
// When the left nav is docked, the body element gets left-padded; this forces it to left-align
documentClone.body.style.padding = '0px';
if (!useForeignObjectRendering) {
addReportHeader(documentClone, header);
addReportFooter(documentClone, footer);
Expand Down Expand Up @@ -259,6 +272,9 @@ export const generateReport = async (id: string, forceDelay = 15000) => {
} else {
const orient = canvas.width > canvas.height ? 'landscape' : 'portrait';
const pdf = new jsPDF(orient, 'px', [canvas.width, canvas.height]);
pdf.setFillColor(bgColor);
// `+ 10` to fill in any uncolored areas that appear on the right and bottom edges of the PDF
pdf.rect(0, 0, canvas.width + 10, canvas.height + 10, "F");
pdf.addImage(canvas, 'JPEG', 0, 0, canvas.width, canvas.height);
pdf.save(fileName);
}
Expand Down

0 comments on commit 13288ec

Please sign in to comment.