How to display PDF in Camunda Embedded form - camunda

I have seen many discussions on how to display a PDF file within a embedded form ( User Task ) But realised camunda does not support this. Are there any solutions?
I have tried using IFrame, Object, embed , and directly linking to a variable did not work ?

My solution is to fetch the variable and convert to a blob as follows:
HTML
<embed class="col-sm-12" style="height:100vh;width:100%" type="application/pdf" id="pdf-frame">
JS
<script cam-script type="text/javascript">
camForm.on('form-loaded', function () {
fetch("http://localhost:8181/camunda/api/engine/engine/default/task/" + camForm.taskId + "/variables/ACORD_FORM/data").then(function (response) {
return response.blob();
}).then(function (myBlob) {
var objectURL = URL.createObjectURL(myBlob);
document.querySelector('#pdf-frame').src = '';
document.querySelector('#pdf-frame').src = objectURL;
objectURL = URL.revokeObjectURL(myBlob);
});
});
</script>

Related

Mobile view is not being shown for embedded powerbi report

We have created a PowerBI report having both the desktop verion and mobile virson.
Its showing desktop and pone view properly when we are testing at following sample site after putting correct information.
https://microsoft.github.io/PowerBI-JavaScript/demo/v2-demo/index.html
But when we open the website on mobile It is still showing the desktop version of the report. File version used of powerbi.js file is 'powerbi-client v2.5.1'.
The HTML and javascript used is provided below
We are also appending '&isMobile=true' with embed report url.
Are we missing any reference to show the mobile version.
<html>
<head>
</head>
<body>
<div id="reportContainer" style="width: 100%; height: 610px" aria-atomic="True" aria-multiline="True" aria-multiselectable="True" aria-orientation="vertical">
</div>
<script src="~/Scripts/powerbi.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
var txtAccessToken = "#Model.EmbedToken.Token";
var txtEmbedUrl = "#Html.Raw(Model.EmbedUrl)";
var txtEmbedReportId = "#Model.Id";
var tokenType = $('input:radio[name=tokenType]:checked').val();
var models = window['powerbi-client'].models;
var permissions = models.Permissions.All;
var config = {
type: 'report',
tokenType: tokenType == '0' ? models.TokenType.Aad : models.TokenType.Embed,
accessToken: txtAccessToken,
embedUrl: txtEmbedUrl,
id: txtEmbedReportId,
permissions: permissions,
settings: {
layoutType: models.LayoutType.MobilePortrait
}
};
// Get a reference to the embedded report HTML element
var embedContainer = $('#reportContainer')[0];
// Embed the report and display it within the div container.
var report = powerbi.embed(embedContainer, config);
// Report.off removes a given event handler if it exists.
report.off("loaded");
// Report.on will add an event handler which prints to Log window.
report.on("loaded", function() {
Log.logText("Loaded");
});
report.on("error", function(event) {
Log.log(event.detail);
report.off("error");
});
report.off("saved");
report.on("saved", function(event) {
Log.log(event.detail);
if (event.detail.saveAs) {
Log.logText('In order to interact with the new report, create a new token and load the new report');
}
});
});
</script>
</body>
</html>
Issue is resolved. I was appending isMobile=true in embededUrl property of configuration.
report.EmbedUrl = report.EmbedUrl + "&isMobile=true";
We need not to append "&isMobile=true" explicitly, this parameter will be updated in the iframe url automatically.

Power BI Premium - embed using Power BI API and javascript not working like previous way

Earlier I used to use 'loadReport' from javascript which is not working with new PBI Premium, e.g. the below is not working anymore & it always says "This content isn't available". BTW this is still working for PBI embedded reports.
<html>
<body>
<iframe id="iFrameEmbedReport"></iframe>
</body>
<script type="text/javascript">
window.onload = function () {
var iframe = document.getElementById('iFrameEmbedReport');
iframe.src = 'https://app.powerbi.com/reportEmbed?reportId=******-088f-4967-***-279bd5a**df&groupId=*****-****-4033-862d-1cd4f4fa72c1';
iframe.onload = function()
{
var m = {
action: 'loadReport',
accessToken: 'H4s*****'
};
message = JSON.stringify(m);
iframe = document.getElementById('iFrameEmbedReport');
iframe.contentWindow.postMessage(message, "*");
};
};
</script>
</html>
But if we use powerbi.js with the same configs its working fine (below)
<html>
<body>
<div id="reportContainer"></div>
</body>
<script src="https://microsoft.github.io/PowerBI-JavaScript/demo/node_modules/jquery/dist/jquery.js"></script>
<script src="https://microsoft.github.io/PowerBI-JavaScript/demo/node_modules/powerbi-client/dist/powerbi.js"></script>
<script type="text/javascript">
window.onload = function () {
var accessToken = '******************';
var embedUrl = 'https://app.powerbi.com/reportEmbed?reportId=**********&groupId=**********';
var embedReportId = '*****-088f-****-aa2d-279bd5a662df';
var models = window['powerbi-client'].models;
var config = {
type: 'report',
tokenType: models.TokenType.Embed,
accessToken: accessToken,
embedUrl: embedUrl,
id: embedReportId,
permissions: models.Permissions.All,
settings: {
filterPaneEnabled: true,
navContentPaneEnabled: true
}
};
var reportContainer = $('#reportContainer')[0];
var report = powerbi.embed(reportContainer, config);
}
</script>
</html>
Not able to figure out what has changed. I really don't want to include powerbi.js in my application if not needed. I know I have a working copy but really need to understand what has changed and if there is any way I can avoid powerbi.js. End goal is to use the first approach in UWP App.
Thanks
The main thing that's changed in the 2 approaches is the property TokenType.Embed which is not available in the 'old way', i.e. 'loadReport' message format.
This is a deprecated way of communicating with embedded entities from Power BI, and all users are encouraged to write their code against the new and maintained Javascript SDK: https://microsoft.github.io/PowerBI-JavaScript/
The 'loadReport' way work for backward compatibility concerns but you won't be able to write new code in new methods using this way.

Wkhtmltopdf does not render Chart.JS 2.5.0 graph

Using:
WKpdftohml version 0.12.3.2
PHPwkhtmltopdf version 2.2.0
Chart.JS version 2.5.0
I'm trying to print a line graph using the above libraries. I can reproduce a pdf using the shell command: wkhtmltopdf --javascript-delay 5000 " http://netdna.webdesignerdepot.com/uploads7/easily-create-stunning-animated-charts-with-chart-js/chartjs-demo.html" test2.pdf
So there is no problem with WKhtmltopdf.
The problem is when I do it in my app, using the PHPwkhtmltopdf library. I get a blank page.
From my research these are the things I tried:
Added 'javascript-delay' => 500 to Chart.JS options;
Added animation:{onComplete: function () {window.JSREPORT_READY_TO_START =true} to Chart.JS options;
Added <div style="width:800px;height:200;font-size:10px;"> to the parent div of canvas html tag
Added ctx.canvas.width = 800;ctx.canvas.height = 200; to javascript initialization of the chart.
Well nothing worked. I love Chart.JS and WKhtmltopdf, but if I can't print I'll have to drop one of them. Is there any solution?
This is my php code for the PHPwkhtmltopdf:
public function imprimir ($request, $response)
{
// include_once 'config/constants.php';
// include_once 'resources/auxiliar/helpers.php';
$folha = $_POST['printit'];
$variaveis = explode(',', $folha);
$nomeFicheiro = $variaveis[0];
$printName = substr($nomeFicheiro, 5);
if (isset($variaveis[2])) {
$_SESSION['mesNumero'] = $variaveis[2];
$_SESSION['mes'] = $variaveis[1];
} else {
$mesNumero = 0;
$mes = '';
}
ob_start();
if ($nomeFicheiro == 'printPpiam') {
require ('C:/xampp/htdocs/.../'.$nomeFicheiro.'.php');
} else {
require ('C:/xampp/htdocs/.../'.$nomeFicheiro.'.php');
}
$content = ob_get_clean();
// You can pass a filename, a HTML string, an URL or an options array to the constructor
$pdf = new Pdf($content);
// On some systems you may have to set the path to the wkhtmltopdf executable
$pdf->binary = 'C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf';
$pdf -> setOptions(['orientation' => 'Landscape',
'javascript-delay' => 500,
// 'enable-javascript' => true,
// 'no-stop-slow-scripts' => true]
]);
if (!$pdf->send($printName.'.pdf')) {
throw new Exception('Could not create PDF: '.$pdf->getError());
}
$pdf->send($printName.'.pdf');
}
# Update 1
Made a php file with the page output. Run it in the browser and the graph rendered. When I do it in the console it renders everything except the graph!
How can it be wkhtmltopdf renders the graphics in this page : http://netdna.webdesignerdepot.com/uploads7/easily-create-stunning-animated-charts-with-chart-js/chartjs-demo.html but not my own?!
# Update 2
After Quince's comment, I tried just turning the animations off, but I'm not sure on how to do that. I tried:
$pdf -> setOptions(['orientation' => 'Landscape',
'javascript-delay' => 500,
// 'window-status' => 'myrandomstring ',
'animation' => false,
'debug-javascript',
'no-stop-slow-scripts',
]);
But it fails.
Here's the code that works with wkhtmltopdf version 0.12.5:
chart.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<style>
.reportGraph {width:900px}
</style>
</head>
<body>
<div class="reportGraph"><canvas id="canvas"></canvas></div>
<script type="text/javascript">
// wkhtmltopdf 0.12.5 crash fix.
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192
'use strict';
(function(setLineDash) {
CanvasRenderingContext2D.prototype.setLineDash = function() {
if(!arguments[0].length){
arguments[0] = [1,0];
}
// Now, call the original method
return setLineDash.apply(this, arguments);
};
})(CanvasRenderingContext2D.prototype.setLineDash);
Function.prototype.bind = Function.prototype.bind || function (thisp) {
var fn = this;
return function () {
return fn.apply(thisp, arguments);
};
};
function drawGraphs() {
new Chart(
document.getElementById("canvas"), {
"responsive": false,
"type":"line",
"data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
"options":{}
}
);
}
window.onload = function() {
drawGraphs();
};
</script>
</body>
</html>
Run:
$ wkhtmltopdf chart.html chart.pdf:
Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done
Found the answer. After I created a separate file, outside the framework, i did some tests again. It rendered the graph in the browser so I tried to use the command tool WKhtmltopdf, and it did not worked, when it did with other examples (see Update #1). So there is something wrong with my php page.
Ran the same tests that I did in the framework, and got the answer for my problem. By introducing a parent div tag width dimensions in the canvas tag it made the graph render in the page.
<div style="width:800px;height:200;">
<canvas id="myChart" style="width:800px;height:200;"></canvas>
</div>
The proposition was found in this site: Github, so thanks laguiz.
Try adding this, as according to this github source
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.0.0/polyfill.min.js"></script>
Solved it by downgrading wkhtmltopdf: 0.12.4 > 0.12.2.1
chart.js version seemed to have no influence. I used 2.7.0.
Fixed width and height seem to be required as well.
Edit: Since wkhtmltopdf is dead, I switched to Puppeteer recently.
I was dealing with the same issue using rotativa to export my ASP.NET MVC page with Chart.JS to PDF with no luck.
After a couple of days I finally found a super-easy solution to achieve my goal. What I did is simply to use the .toBase64Image() method of Chart.JS to encode the chart to a base64 string variable in Javascript. Then I saved this string into a model and then on the PDF html page a used tag where i put the base64encoded string to a scr property and the result is great :-)
javascript:
//save Chart as Image
var url_base64 = document.getElementById('myChart').toDataURL('image/png');
//set the string as a value of a hidden element
document.getElementById('base64graph').value = url_base64;
PDF view:
<img style='display:block; width:900px;height:400px;position:relative;margin:auto;text-align:center;' id='base64image'
src='#Model.base64graph' />
I'm trying to improve on the answer by temuri, which is great, but a bit bloated. I ran into the OP's issues (even same WKpdftohml version) and this did the trick for me:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<div style="width: 400px;"><canvas id="canvas"></canvas></div>
<script type="application/javascript">
// wkhtmltopdf 0.12.5 crash fix.
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192
Function.prototype.bind = Function.prototype.bind || function (thisp) {
const fn = this;
return function () {
return fn.apply(thisp, arguments);
};
};
new Chart(
document.getElementById("canvas"), {
"responsive": false,
"type":"line",
"data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
"options":{}
}
);
</script>
I'm yet to figure out how to get the chart library via ordinary tools like npm, instead of getting it via ajax like here in the first line. Note that this can impact your chart resolution.
I was strugling with that too and you self-answer did not help my case. I am using symfony 3.3 and Chart.js 2 and whatever I did, did not work properly. So I have solved it in a different manner (maybe not a clean one) and I wanted to post it here for inspiration to others.
I needed to export a page, that I was presenting to the user in a browser. In browser, I used Javascript to get picture out of the rendered graph with
animation: {
onComplete: function(animation) {
console.log('done');
var url=document.getElementById("barChartByCountryWeight{{ part }}{{ subsetKey }}").toDataURL();
$.ajax({
url: 'saveChartImages',
type: 'POST',
data: { 'barChartByCountryWeight{{ part }}{{ subsetKey }}': url },
success: function(result) {
console.log(result);
console.log('the request was successfully sent to the server');
},
error: function (request, error) {
console.log(arguments[0]['responseText']);
console.log(" Can't do because: " + error);
}
});
}
}
And on server side I put it in session and in a controller for the PDF export, I have taken the image from session and put the image in the HTML, that is converted to PDF.
Hope that helps.
I have implemented the working code for this issue. You can check out the working code here.
NOTE: For generating pdf you must disable the Chart JS animation or add the option javascript-delay=>1000 to the wkhtmltopdf options.
I have solved this problem when I tried to use Chartjs 1 instead of a new chart js. The reason for this is because laravel snappy uses wkhtmltopdf, which doesn't support css animation, while new chartjs uses css animation.
This github issue shows that.
The solution i found is to use google chart instead. It also uses svg, so you can get high resolution charts.

Backbone Collection

I was trying to make a Backbone Application with Django at its backend. I was following a Backbone tutorial. I used the following code:
Code
<!doctype html>
<html lang = "en">
<meta charset = "utf-8">
<title>IstreetApp</title>
<link rel="stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>Book Manager</h1>
<hr />
<div class="page"></div>
</div>
<script type = "text/template" id = "booklist.template">
</script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>
<script>
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
options.url = 'http://backbonejs-beginner.herokuapp.com' + options.url;
});
var Books = Backbone.Collection.extend({
url: '/books'
});
var BookList = Backbone.View.extend({
el: '.page',
render: function () {
var that = this;
var books = new Books();
books.fetch({
success: function(books) {
var template = _.template($('#booklist.template').html(), {books: books.models});
that.$el.html(template);
}
})
}
});
var Router = Backbone.Router.extend({
routes: {
'': 'home'
}
})
var bookList = new BookList();
var router = new Router();
router.on('route:home', function () {
bookList.render();
});
Backbone.history.start();
</script>
</body>
</html>
Since the collection is not defined, the success code doesn't execute. I suppose the collection data should come from the server through Django but I am not sure how and in what form. Kindly help. I am pretty much new to backbone and Django.
When you call fetch on your collection, it makes an AJAX request to:
http://backbonejs-beginner.herokuapp.com/books
However, there is no API set up there. Either one of two things needs to happen:
1) you need to modify your code to point to a different URL, one that does have an existing API (perhaps whatever tutorial you are using has such an API)
2) you need to create such an API yourself on yoursever.com (and then make your Backbone code point to that API's URL instead)
Without a server to support it, operations like save and fetch and such in Backbone simply cannot function.
As a side note, Django is a web site framework. While you can use it to create server-side APIs, that's not really Django's focus. Because of this, several good third party libraries exist for doing RESTful APIs (ie. the kind that Backbone likes) in Django; personally I'd recommend either Django REST Framework (I use it and it works great) or TastyPie (never used it, but it's very popular).
When using a backbone collection you need to return a json array of objects from your api url (http://backbonejs-beginner.herokuapp.com/books)
Example
{[{"name":"bookname", "publisher": "penguin"}, {"name":"bookname", "publisher":"penguin"}]}
You'll also want a model for your collection. A model would look like this
Example:
var Book = Backbone.Model.extend({
defaults: {
"name": "",
"publisher": ""
}
});
The way that the collection works is by parsing the json array and turning each object in the array in to a model that you specific (in this instant an individual book with values for the name and publisher).
When you make a .fetch() on your model you are making a GET request, so make sure that your http://backbonejs-beginner.herokuapp.com/books url is prepared to receive GET requests and respond with the json data in the format I specified up top.

Remember preferable language

I've made a simple website for my daughter.
It is in Dutch and for every page there is a English version as well.
Dutch URL: nl/index.html
English URL: eng/index.html
What I would like to do is give the visitor the option to set one language as preference. So if they come to this site the next time they will automatically linked to the preferable page.
I know this can be done with a cookie and saw the explanation on this forum ( How to remember the currently clicked url? javascript?PHP? ).
I've tried to make this work but apparently I am doing something wrong?
Can somebody guide me through step by step? That would be great!
Kind regards,
Jurgen
If you are familiar with jQuery you can use the cookies plug-in to persist the user's language choice and redirect him to the appropriate page every time he comes back to your site. Bellow is a sample code that uses two buttons to set the language:
First you declare the jQuery scripts (I use to store them in a Script folder, hence the following):
<script type="text/javascript" src="../Script/jquery-1.7.2.js"></script>
<script type="text/javascript" src="../Script/jquery.cookie.js"></script>
Then you define the page ready event like this:
$(function () {
var url = 'your_url';
var english_page = 'eng/index.html';
var dutch_page = 'nl/index.html';
if ($.cookie('default_page') != null) {
if (window.location.href != url + '/' + $.cookie('default_page')) {
window.location.href = url + '/' + $.cookie('default_page');
}
}
$('#set_english_butt').click(function () {
$.cookie('default_page', english_page, { expires: 999 });
alert('English was set as the default language');
});
$('#set_dutch_butt').click(function () {
$.cookie('default_page', dutch_page, { expires: 999 });
alert('Dutch was set as the default language');
});
});
Which is hooked to some html buttons in you page:
<div>
<span>Select your language:</span>
<button id="set_english_butt">English</button>
<button id="set_dutch_butt">Dutch</button>
</div>