jsreport in amplify
-
jsreport looks like what I want to create statements in my amplify app. Is there any help to make this work? It's OK with me if the report isn't actually part of my app, although that would be preferable. I need to be able to load app data into a report template and have it render for the user who can then download it to PDF.
Edit: I think I see one solution... use the API to the hosted report server for this purpose.
-
jsreport is a server-side solution, it won't run in browser or mobile at least for now.
You need to host jsreport on a server (or use jsreport SaaS) and communicate with it through API.
-
OK, I have tried to follow the code you provide, but not really any luck yet. The screen prints
report has run: {}
If I debug the state.Report, it does show a PromiseState of "fulfilled"
I couldn't find any example of using jsreport with Amplify ReactJS on the internet so I wrote this code.
I think I'm missing some code and not sure how to write it.import React from "react";
const client = require('jsreport-client')('http://localhost:5488/studio/templates/SJVbqZr9f')
class RenderReport extends React.Component {componentDidMount() { var report = ""; report = this.doRender(); this.setState({Report: report}); } doRender = async() => { try { async function renderReport () { const res = await client.render({ template: { content: 'hello {{someText}}', recipe: 'html', engine: 'handlebars' }, data: { someText: 'world!!' } }) const bodyBuffer = await res.body() const report = bodyBuffer; // this will re render the view with new data return report; } } catch(err) { console.log(err); return(err); } } render() { if(this.state != undefined) { const reports = this.state.Report; return ( <div> <div>report has run: {JSON.stringify(this.state.Report)}</div> </div> ); } else return(<div>report has not run</div>); } } export default RenderReport;
-
This looks like front-end browser code, so you should use jsreport browser client. The jsreport-client package is for node.js.
-
This post is deleted!
-
What I decided with regards to Amplify was to follow the directions to create a Lambda function to host jsreport https://jsreport.net/learn/aws-lambda-serverless
Of course, with this method of deployment, I was not using the typical amplify pattern for adding a function, so the way to call this function follows a non-standard pattern. This is the code I use to call the lambda and render the report. Sure, it's probably not very secure because of the access keys, but it works.
import React from "react";
require('dotenv').config();
const AWS = require('aws-sdk')
const fs = require('fs')const client = require('jsreport-client')
class RenderReport extends React.Component {
componentDidMount() { //this is a non-amplify way to call Lambda! const lambda = new AWS.Lambda({ //TODO region: 'us-east-1', accessKeyId: "xxxxxxxxx", secretAccessKey: "xxxxxxxxxxx" }) lambda.invoke({ FunctionName: 'myJsreportLambda', Payload: JSON.stringify({ renderRequest: { template: { name: 'invoice-main' }, data: this.props.data } }) }, (err, res) => { if (err) { return console.error(err) } const response = JSON.parse(res.Payload) if (response.errorMessage) { console.log(response.errorMessage) console.log(response.stackTrace) } else { //Create a Blob from the PDF Stream const file = new Blob( [Buffer.from(response.body, 'base64')], { type: 'application/pdf' }); //Build a URL from the file const fileURL = URL.createObjectURL(file); //Open the URL on new Window this.setState({ Report: fileURL }) } }) } render() { if (this.state != undefined) { return ( < div > < iframe id = "statement" src = { this.state.Report } title = "Statement" / > < /div> ); } else return null; }
}
export default RenderReport;