Skip to content
This repository has been archived by the owner on Jul 31, 2024. It is now read-only.

Commit

Permalink
FDS-653 Dashboard as pdf report export feature
Browse files Browse the repository at this point in the history
  • Loading branch information
vikas-cldcvr committed Mar 11, 2024
1 parent a3e502f commit b2346e8
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 62 deletions.
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
],
"devDependencies": {
"@changesets/cli": "^2.25.0",
"@faker-js/faker": "^8.3.1",
"@ollion/custom-elements-manifest-to-types": "workspace:*",
"@ollion/prettier-config": "^2.1.0",
"@faker-js/faker": "^8.3.1",
"@storybook/addon-actions": "^7.5.3",
"@storybook/addon-essentials": "^7.5.3",
"@storybook/addon-links": "^7.5.3",
Expand All @@ -47,6 +47,7 @@
"@storybook/blocks": "^7.5.3",
"@storybook/web-components": "^7.5.3",
"@storybook/web-components-vite": "^7.5.3",
"@types/d3": "7.4.3",
"@types/eslint": "^8.4.3",
"@types/jest": "29.5.5",
"@types/prettier": "^3.0.0",
Expand All @@ -66,13 +67,13 @@
"sass": "^1.52.3",
"storybook": "^7.5.3",
"typescript": "^5.2.2",
"vite": "^4.4.11",
"@types/d3": "7.4.3"
"vite": "^4.4.11"
},
"dependencies": {
"@ollion/flow-aws-icon": "latest",
"@ollion/flow-code-editor": "workspace:*",
"@ollion/flow-core": "workspace:*",
"@ollion/flow-dashboard": "workspace:*",
"@ollion/flow-form-builder": "workspace:*",
"@ollion/flow-gcp-icon": "latest",
"@ollion/flow-lineage": "workspace:*",
Expand All @@ -81,10 +82,10 @@
"@ollion/flow-product-icon": "1.14.0",
"@ollion/flow-system-icon": "latest",
"@ollion/flow-table": "workspace:*",
"@ollion/flow-dashboard": "workspace:*",
"d3": "^7.6.1",
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"lit": "^3.1.0",
"d3": "^7.6.1"
"lit": "^3.1.0"
},
"loki": {
"configurations": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class FDashboard extends FRoot {
render() {
return html`
<div class="grid-stack" ${ref(this.gridStackElement)}>
${this.config.widgets.map(wgt => {
${this.config?.widgets.map(wgt => {
return keyed(
wgt.id,
html`<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class FTimeseriesChart extends FRoot {
* @attribute comments baout title
*/
@property({ type: Object })
config!: FTimeseriesChartConfig;
config: FTimeseriesChartConfig = { data: [] };

chartContainer: Ref<FDiv> = createRef<FDiv>();
chartLegends: Ref<FDiv> = createRef<FDiv>();
Expand Down Expand Up @@ -252,7 +252,7 @@ export class FTimeseriesChart extends FRoot {
height="100%"
>
<f-div class="f-timeseries-container" ${ref(this.chartContainer)}
>${svg`<svg xmlns="http://www.w3.org/2000/svg"></svg>`}
>${svg`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>`}
<f-div
state="custom,#000000"
variant="curved"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { FButton, FDiv, flowElement, FRoot, FSearch, FText } from "@ollion/flow-core";
import { html, HTMLTemplateResult, nothing, PropertyValueMap, unsafeCSS } from "lit";
import { ifDefined } from "lit-html/directives/if-defined.js";
import { property, query, state } from "lit/decorators.js";
import { FTable, FTableSelectable, FTableSize, FTableVariant } from "../f-table/f-table";
import { FTcell, FTcellActions, FTcellAlign } from "../f-tcell/f-tcell";
Expand Down Expand Up @@ -219,8 +218,8 @@ export class FTableSchema extends FRoot {
.width=${width}
.align=${columnHeader[1].align}
data-background="${this.stickyCellBackground}"
?sticky-left=${ifDefined(sticky)}
?sticky-top=${ifDefined(this.stickyHeader)}
?sticky-left=${sticky}
?sticky-top=${this.stickyHeader}
@selected-column=${this.handleColumnSelection}
@update-row-selection=${(event: CustomEvent<boolean>) =>
this.handleHeaderInput(event, columnHeader[1])}
Expand Down Expand Up @@ -288,7 +287,7 @@ export class FTableSchema extends FRoot {
.actions=${actions}
.align=${cell.align}
data-background="${this.stickyCellBackground}"
?sticky-left=${ifDefined(sticky)}
?sticky-left=${sticky}
>${this.getCellTemplate(row.data[columnHeader[0]], highlightTerm)}
</f-tcell>`;
})}
Expand Down
8 changes: 3 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

122 changes: 78 additions & 44 deletions stories/flow-dashboard/f-dashboard.stories.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { Meta } from "@storybook/web-components";
import { html } from "lit-html";
import {
FDashboard,
FDashboardConfig,
FDashboardWidget,
FTimeseriesChartConfig
} from "@ollion/flow-dashboard";
import type { FDashboard, FDashboardConfig, FDashboardWidget } from "@ollion/flow-dashboard";
import { generateTimeseriesChartData } from "./mock-data-utils";
import { faker } from "@faker-js/faker";
import { createRef, ref } from "lit/directives/ref.js";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";

export default {
title: "@ollion/flow-dashboard/f-dashboard",
Expand Down Expand Up @@ -40,41 +37,11 @@ const getWidgets = () => {
data: generateTimeseriesChartData(startFrom)
},
id: faker.string.alpha(10),
header() {
const name = faker.company.name();
const description = faker.lorem.sentences(3);
return html`<f-div
align="middle-left"
height="hug-content"
padding="medium"
gap="medium"
border="small solid subtle bottom"
>
<f-icon .source=${faker.helpers.arrayElement(iconsNames)} size="large"></f-icon>
<f-div direction="column" align="middle-left">
<f-text ellipsis .tooltip=${name} variant="heading" weight="medium">${name}</f-text>
<f-text ellipsis .tooltip=${description} size="small">${description}</f-text>
</f-div>
</f-div>`;
},
footer: () => {
const date = faker.date.recent({ refDate: new Date() });
const state = faker.helpers.arrayElement(["danger", "success", "warning"]);
return html`<f-div
padding="medium"
gap="auto"
border="small solid subtle top"
height="hug-content"
>
<f-div gap="small" align="middle-left">
<f-icon source="i-clock-outline" size="small" .state=${state}></f-icon>
<f-text .state=${state} size="small"
>Last updated on ${date.toLocaleDateString()} ${date.toLocaleTimeString()}</f-text
>
</f-div>
<f-button label="view details" size="x-small" icon-right="i-new-tab"></f-button>
</f-div>`;
header: {
title: faker.company.name(),
description: faker.lorem.sentences(3)
},
footer: `Powered by Flow`,
placement: {
w: faker.number.int({ min: 4, max: 8 }),
h: faker.number.int({ min: 3, max: 4 })
Expand Down Expand Up @@ -103,6 +70,7 @@ const getWidgets = () => {
};
const Template = () => {
const dashboardRef = createRef<FDashboard>();
const imgRef = createRef<HTMLImageElement>();
const dashboardConfig: FDashboardConfig = {
widgets: getWidgets()
};
Expand All @@ -114,7 +82,67 @@ const Template = () => {
}
};

return html`<f-div height="100%" width="100%" gap="small" direction="column">
/**
* Download file as image in pdf
*
*
*/
// const downloadFile = () => {
// const element = document.querySelector("#dashboard-to-export") as FDashboard;

// html2canvas(element, { scale: 1 }).then(function (canvas) {
// // Initialize jsPDF
// const pdf = new jsPDF({
// orientation: "p",
// unit: "px",
// format: [element.scrollWidth, element.scrollHeight]
// });
// pdf.setDisplayMode("original");
// //const dataURL = canvas.toDataURL("image/png", 1.0);
// // Add canvas image to PDF
// //imgRef.value!.src = dataURL;

// pdf.addImage(canvas, "PNG", 0, 0, element.scrollWidth, element.scrollHeight);

// // Save the PDF
// pdf.save("canvas_to_pdf.pdf");
// });
// };

const downloadFile = () => {
// const allSVGS = document.querySelectorAll("svg");
// console.log(allSVGS);
// for (let i = 0; i < allSVGS.length; i++) {
// console.log(allSVGS[i]);
// html2canvas(allSVGS.item(i) as unknown as HTMLElement, { scale: 1 }).then(function (canvas) {
// allSVGS[i].outerHTML = `<img src="${canvas.toDataURL()}"/>`;
// });
// }

const element = document.querySelector("#dashboard-to-export") as FDashboard;
const doc = new jsPDF({
orientation: "p",
unit: "px",
format: [element.scrollWidth, element.scrollHeight]
});

doc.html(element, {
html2canvas: {
scale: 1,
async: true,
svgRendering: true
},
callback: function (doc) {
doc.save("sample-document.pdf");
},
width: element.scrollWidth,
windowWidth: 2400
});
};

return html`<f-div width="100%" gap="small" overflow="scroll" direction="column">
<img ${ref(imgRef)} />
<f-div
variant="curved"
state="primary"
Expand All @@ -123,11 +151,17 @@ const Template = () => {
gap="auto"
align="middle-left"
>
<f-text state="inherit">Click on randomize button to generate new data</f-text>
<f-button @click=${randomize} label="randomize"></f-button>
<f-text state="inherit">Click on export button to generate pdf</f-text>
<f-button @click=${downloadFile} label="export"></f-button>
</f-div>
<f-dashboard ${ref(dashboardRef)} .config=${dashboardConfig}> </f-dashboard>
<f-dashboard
style="background:var(--color-surface-default)"
id="dashboard-to-export"
${ref(dashboardRef)}
.config=${dashboardConfig}
>
</f-dashboard>
</f-div>`;
};

Expand Down

0 comments on commit b2346e8

Please sign in to comment.