Export Html to Pdf using JsReport in Asp.net core - jsreport

I have a html page with images, tables and some styling with Bootstrap 4. I tried to convert the pages to pdf using the JsReportMVCService, the pdf doesnot load with the proper css class from bootstrap.
HTML CONTENT
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WeekelyReport</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="jumbotron">
<h1> Hello John Doe,</h1>
<p>
This is a generic email about something.<br />
<br />
</p>
</div>
</body>
</html>
ASP.NET CORE IMPLEMENTATION
var generatedFile = await GeneratePDFAsync(htmlContent);
File.WriteAllBytes(#"C:\temp\hello.pdf", generatedFile);
async Task<byte[]> GeneratePDFAsync(string htmlContent)
{
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf
}
});
using (var memoryStream = new MemoryStream())
{
await report.Content.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
}
How my Pdf Looks after the conversion to PDF.
It is possible to convert to pdf with the same bootstrap 4 layout? or am i missing something during the conversion here?

The pdf printing uses print media type and the bootstrap has quite different styles for printing. This causes that the pdf looks different than html, but it looks the same as you would print it. I would generally not recommend using responsive css framework as bootstrap for printing static pdf, but it is of course your choice.
To make your example looking the same on pdf you just need to change the media type on the chrome settings.
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf,
Chrome = new Chrome {
MediaType = MediaType.Screen,
PrintBackground = true
}
}
});
make sure you have the latest jsreport.Types#2.2.2

Related

Detect broken images in webbrowser control document?

Is there any way to detect whether or not an image has not loaded/is broken in a webbrowser control? I am loading html from a file like so:
Here is some html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META content="text/html; charset=unicode" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 11.00.10586.589">
</HEAD>
<BODY>
<A href="https://web.archive.org/web/20120124023601/http://www.flatfeets.com/wp-content/uploads/2012/01/shoes-for-flat-feet.jpg">
<IMG title="shoes for flat feet" class="alignleft size-medium wp-image-18" alt="" src="https://web.archive.org/web/20120124023601im_/http://www.flatfeets.com/wp-content/uploads/2012/01/shoes-for-flat-feet-300x238.jpg">
</A>
</BODY>
</HTML>
And simple load this into webbrowser
webbrowser1.DocumentText = thehtml
I would just like to be able to detect whether or not the image has loaded properly. This should work for all images on the page.
You could create a separate WebClient request for each image in the html file and then see if any return a html response error code.
You would first have to parse the html and make a list of all the images urls. I would suggest using a package like HTML Agility Pack to easily parse out the image urls. Then you could use this code to identify any bad paths.
WebClient requester = new WebClient();
foreach (string url in urls)
{
try
{
Byte[] imageBytes = requester.DownloadData(url);
}
catch(Exception ex)
{
//Do something here to indicate that the image file doesn't exist or couldn't be downloaded
}
}
You can also convert the byte array to an Image and then make sure that it is RGB Encoded since that is the only encoding that can reliably be displayed in a web browser.

Open URL in new safari tab - safari extention

generaly i ask exactly the same question as here:
Safari extension: Event for a completely new tab?
in this answer (case 3) he guide to listen click event inside inject.js.
can someone show this implementation?
Here's an implementation I used for one of my previous extensions:
Create a global.html file, and inside the Extension Builder, select that file under the Extension Global Page section:
Source for global.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>My Extension</title>
</head>
<body>
<script>
function messageHandler(event) {
var newTab = null;
var url = null;
if (event.name === "open_new_tab") {
url = event.message;
newTab = safari.application.activeBrowserWindow.openTab();
newTab.url = url;
}
}
safari.application.addEventListener("message", messageHandler, false);
</script>
</body>
</html>
Create an extension.js file, and add it to the Injected Extension Content -> End Scripts section:
Source for extension.js:
(function() {
// ... rest of you extension code
openNewTabWithUrl("http://google.com")
function openNewTabWithUrl(url) {
safari.self.tab.dispatchMessage("open_new_tab", url);
}
}());
This will send a message containing a URL from your extension.js to global.html, which will pick up the message and open the new tab.

Is there a way to call a function before the dependencies are loaded in Sencha Touch application

Sencha Touch application has requires:[] option to specify the list of controllers and models and stores etc that are loaded that we need for the application to work but is there a way to execute something that we need even before the loading of the dependencies. FOr e.g. I need the Browsers Language even before the loading of all dependencies. So is it possible to do?
Keep in mind: Sencha Touch is nothing but JavaScript.
You can add some script in your index.html in front of the script tag that loads the sencha microloader.
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>FNL</title>
<style type="text/css">
<!-- sencha stuff -->
</style>
<script id="myScript" type="text/javascript" src="myScript.js"></script>
<!-- The line below must be kept intact for Sencha Command to build your application -->
<script id="microloader" type="text/javascript" src=".sencha/app/microloader/development.js"></script>
</head>
<body>
<div id="appLoadingIndicator">
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
I added some lines to the ST Microloader:
this.css = processAssets(manifest.css, 'css');
// Load language strings
var xhr = new XMLHttpRequest();
xhr.open('GET', 'api/Settings', false);
xhr.send(null);
var settings = eval("(" + xhr.responseText + ")");
Lang = settings.Translations[0];
Options = settings.Options[0];
// End Load Language Strings
this.js = processAssets(manifest.js, 'js');
In ExtJS i accomplished this by loading a Dependency class first
Ext.require([
'MyApp.Dependencies',
..
]);
so the Dependecies class is loaded before all controllers which looks like this
Dependencies.js:
Ext.define('MyApp.Dependencies', {
singleton: true,
init: function() {
// load translation data
}
});
MyApp.Dependecies.init();
and for completition my init function looks something like this:
inti: function(){
function loadScriptSync(url) {
var xhrObj = new XMLHttpRequest();
// open and send a synchronous request
xhrObj.open('GET', url, false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);
}
var language = this.getLanguage();
loadScriptSync("resources/locale/locale." + language + ".js");
}

rally.sdk.ui.StandardReport.ReleaseDefectTrend does not produce accurate results outside of Rally using loginkey

I am trying to create a Release trend chart, but I am getting different results if I run the code inside a rally app versus running the app outside of rally using a valid login key. Below is the code in question.
After getting the chart to work correctly, I would love to be able to show some subset of the data, similar to the actual ReleaseDefectTrend chart inside of Rally, that lets you specifiy XXX number of days/weeks/months/etc. Are there setting(s) for the config of the chart that will allow you to do this.
Thanks in advance!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2011 Rally Software Development Corp. All rights reserved -->
<html>
<head>
<!-- <script type="text/javascript" src="/apps/1.32/sdk.js?debug=false"></script> -->
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.32/sdk.js?loginKey=myvalidloginkeyhere"></script>
<script type="text/javascript">
function onLoad() {
//alert('ProjOID = ' + __PROJECT_OID__);
/
var rallyDataSource = new rally.sdk.data.RallyDataSource("myvalidworkspaceID","myvalidprojectID","false","false");
var ddown1=document.getElementById("ddown1");
var config = { label: "Select a release " };
var releaseDropdown = new rally.sdk.ui.ReleaseDropdown(config,rallyDataSource);
releaseDropdown.display(ddown1,releaseSelected);
}
function releaseSelected(dropdown,eventArgs) {
var selectedItem=eventArgs.item;
var selectedValue = eventArgs.value;
var releaseObjids = new Array();
releaseObjids[1]=selectedItem.ObjectID;
displayChart1(releaseObjids[1]);
}
function displayChart1(release) {
var config = {
report: rally.sdk.ui.StandardReport.ReleaseDefectTrend,
//itle: 'Technical Debt',
width : 600,
height: 250,
releases: release
};
alert('chart1 release = ' + release);
var report = new rally.sdk.ui.StandardReport(config);
var div1=document.getElementById("div1");
report.display(div1);
}
rally.addOnLoad(onLoad);
</script>
</head>
<body>
<table border="1">
<tr>
<td align="center"><div id="ddown1"></div></td>
</tr>
<tr>
<td><div id="div1"></div></td>
</tr>
</table>
</body>
</html>
Looks like there is no hardcoded Object IDs of releases in your code, and workspace is also not specified. All WS API queries are bound to a workspace, and in the absence of specified workspace and a default for a given user there is no guarantee that what you see inside Rally is going to be the same outside. To narrow this down, you do not need to use login key in this stage of troubleshooting. Please make sure the app works outside of Rally as expected - the login key only allows you to avoid the prompt to login. The scope is not specified in your code, but the app needs to pull available releases from somewhere.
Before you customize the original code found here see if the original code produces identical results for you outside and inside of Rally when you hard code Object ID of a specific release, and then move on to more complex scenarios when you have multiple ObjectIDs hardcoeded, and only then try to use a variable set dynamically from a dropdown value:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta name="Name" content="Component Example: Standard Report">
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.26/sdk.js"></script>
<script type="text/javascript">
function initPage() {
var config = {
report: rally.sdk.ui.StandardReport.ReleaseDefectTrend,
width : 800,
height: 400,
releases: [1111,2222]
};
var report = new rally.sdk.ui.StandardReport(config);
report.display("aDiv");
}
rally.addOnLoad(initPage);
</script>
</head>
<body>
<div id="aDiv"></div>
</body>
</html>
For more info see Apps Outside of Rally
Generally standard reports are canned reports and cannot be customized further outside of what the JSON configuration object allows. AppSDK1 allows you to load a report in a custom page by providing access to them via this syntax:
report: rally.sdk.ui.StandardReport.ReleaseDefectTrend
but if you want to zoom in, to display more information, perhaps in a chart, this has to be coded from scratch.

"Container is not defined" Google chart

I have solved my issue but can't answer it myself since I am too new to this site:
turns out I needed to use the following:
chart = new google.visualization.PieChart(document.getElementById('pie_today_div'));
I was using JQuery to access the element, $('#pie_today_div'). As of now the evidence points to the fact that the PieChart constructor has to have standard JS code, document.getElementById('pie_today_div')
Maybe something else going on, but changing the way I access the container element fixes my code
ORIGINAL ISSUE FOR REFERENCE TO MY SOLUTION
I am getting a "Container is not defined" error when I am trying to instantiate a Google PieChart object.
I validated my page at http://validator.w3.org/ and i get a pretty green banner saying it validates.
I receive no js errors when the page loads. My Ajax call is making a full round trip with the data I want from the DB.
Here is my HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<link href="/css/note.css?10022012" rel="stylesheet" type="text/css" media="screen">
<script type="text/javascript" language="javascript" src="/call/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">google.load('visualization', '1.0', {'packages':['corechart']});</script>
<script type="text/javascript" language="javascript" src="/call/js/init.js?10042012-2"></script>
<title>Call Stats</title>
</head>
<body>
Today Stats
<div id="pie_today_div"></div>
</body>
</html>
here is the js:
function drawPieChartToday() {
$.post('/call/ajax.php5',{
action:'pieToday'
}, function(ticketData) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Count');
data.addColumn('number', 'Topic');
for (var key in ticketData){
data.addRow([key, ticketData[key]]);
}
options = {
title: 'Issue Topics'
};
alert($('#pie_today_div').attr('id'));
chart = new google.visualization.PieChart($('#pie_today_div'));
chart.draw(data, options);
},'json');
}
here is my debugging code to make sure the element was being found:
alert($('#pie_today_div').attr('id')); <-- alerts "pie_today_div"
I'm not a jquery fan, but I think that $('#pie_today_div') returns a set of matched elements. The attribute computation works because (from jquery documentation) it "gets the value of an attribute for the first element in the set of matched elements".
So try
chart = new google.visualization.PieChart($('#pie_today_div')[0]);
or directly
chart = new google.visualization.PieChart(document.getElementById('pie_today_div'));
A container error is exactly that, It is looking for the ID
example:
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
You WILL get this error “Container is not defined” for Google Charts if you are missing
that ID
Thus a Div with that chart_div id would fix this
There must be line where you load the types of visualization you want to have in your web page. It looks like this
google.load("visualization", "1", {packages: ["corechart"]});
Here I am loading package corechart. Place this line as the first line after in the <script> tag inside your HTML page like index.html. That should solve he problem.
use $timeout before init, it works well, else you need to destroy the instance
Just wanted to mention, this happened for me after a simple mistake. I changed
var data = new google.visualization.DataTable(huh);
to the following in an effort to change the chart type:
var data = new google.visualization.BarChart(huh);
but this is all wrong, you change the chart where you mention the container:
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));