Line chart generated image that will be sent through email - javascript

I want to create a line chart similar below:
I just wonder if there are available framework or API available in ASP.NET MVC that generates chart images since my goal is to send this via email. I'm thinking if I can just put something like <img src="http://imageapi.com?date1=20170101&date=20170130" /> then api will be handling the chart image generation.
On searching, I found a lot of chart framework using javascript but I doubt it will properly work on different email clients.
Thanks a lot!

Google Image Charts will do that. Pass data and display settings via the URL, and it will return an image.
eg.
<img src="https://chart.googleapis.com/chart?cht=lc&chd=t:30,10,45,38,25|10,20,10,20,10&chls=2.0,0.0,0.0&chs=200x125&chg=0,20,3,3,10,20&chxt=x,y&chxl=0:|Week1|Week2|Week3|Week4|Week5|1:|0|20|40|60|80|100&chs=800x300&chm=o,ff9900,0,-1,10.0|d,ff0000,1,-1,10.0&chco=FFC6A5,DEBDDE&chdl=Click|GRU" />
produces this chart:
They provide a playground for testing: https://developers.google.com/chart/image/docs/chart_playground
Note however that Google are not maintaining it further, but have no plans to remove this functionality:
While the dynamic and interactive Google Charts are actively maintained, we officially deprecated the static Google Image Charts way back in 2012. This gives us the right to turn it off without notice, although we have no plans to do so.

What is your design ?
Your chart must be generated in web page,then it must be having html generated.
If no html is generated and only image is generated then this is best.
now you can send same content in.
If image is not generated then again you have 2 option here
i) Send complete html in email body along with concern js/css
ii) you can convert those html into image using(say c#) then send mail.
Please mention your complete scenario.

There are different types of chart API available in market, both open source and licensed, you can use any one to generate your chart/diagram in page and you can send that page as an email attachment using following code.
[HttpPost]
public ActionResult SendWebPageAsAttachment()
{
var subject = Request.Form["subject"]; // You can provide subject from page or code
var mailContent = Request.Form["bodyInnerHTML"]; // get the body inner HTML by form name
var Body = "<div style='background-color:white;'>" + Request.Form["mailContent"] + "</div>"; // Email Body
var attachmentName = DateTime.Now.ToString("yyyy/MM/dd").Replace("/", "-") + "_" +
DateTime.Now.ToLongTimeString().Replace(" ", "_") + ".html"; // Attachment Name
var baseUrl = HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority +
HttpContext.Request.ApplicationPath.TrimEnd('/') + '/'; // Base URL
string src = #"src=""";
mailContent = mailContent.Replace(src, src + baseUrl.Remove(baseUrl.Length - 1));
mailContent = "<html><head><link href='" + baseUrl + "Themes/styles.css' rel='stylesheet' type='text/css' /><link href='" +
baseUrl + "Themes/style.css' rel='stylesheet' type='text/css' /></head><body>" + WebUtility.HtmlDecode(mailContent) +
"</body></html>";
try
{
SmtpClient smtpClient = new SmtpClient("mail.MyWebsiteDomainName.com", 25);
smtpClient.Credentials = new System.Net.NetworkCredential("info#MyWebsiteDomainName.com", "myIDPassword");
smtpClient.UseDefaultCredentials = true;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.EnableSsl = true;
MailMessage mail = new MailMessage();
//Setting From , To and CC
mail.From = new MailAddress("info#MyWebsiteDomainName", "MyWeb Site");
mail.To.Add(new MailAddress("info#MyWebsiteDomainName"));
mail.CC.Add(new MailAddress("MyEmailID#gmail.com"));
mail.IsBodyHtml = true;
mail.Subject = subject;
mail.Body = Body;
var mailDataBytes = ASCIIEncoding.Default.GetBytes(mailContent);
var mailStream = new MemoryStream(mailDataBytes);
mail.Attachments.Add(new Attachment(mailStream, attachmentName));
smtpClient.Send(mail);
}
catch (Exception ex)
{
//catch
}
ViewBag.IsHttpPost = true;
return View("SendWebPageAsAttachment");
}

Related

Print Google Spreadsheet cells to PDF file

I want to print cells from a sheet to a PDF file. This PDF file should not be created in Google Drive but downloadable to disk.
Here is my code:
function PrintPDF(LigneDebut, ColonneDebut, LigneFin, ColonneFin) {
SpreadsheetApp.flush();
feuilleImprimer = SpreadsheetApp.getActiveSpreadsheet();
var sheet = feuilleImprimer.getActiveSheet();
var gid = sheet.getSheetId();
var pdfOpts = '&size=A4&fzr=false&portrait=true&fitw=true&gridlines=false&printtitle=false&sheetnames=false&pagenum=UNDEFINED&attachment=false&gid='+gid;
var printRange = '&c1='+ColonneDebut + '&r1='+LigneDebut + '&c2='+ColonneFin + '&r2='+LigneFin; // B2:APn
var url = feuilleImprimer.getUrl().replace(/edit$/, '') + 'export?format=pdf' + pdfOpts + printRange;
var app = UiApp.createApplication().setWidth(200).setHeight(150);
app.setTitle('Printing ' + feuilleImprimer.getSheetName());
var link = app.createAnchor('Download PDF', url).setTarget('_new');
app.add(link);
feuilleImprimer.show(app);
}
Some APIs are out of date: UiApp, Anchor, and UiInstance.
This generates warning messages.
By what methods to replace these deprecated API?
Thanks for your help.
To address the deprecated issue, just go to the official Apps Script doc reference. For example, in the case Class UiApp, use the HTML Service instead.
For a working code of converting spreadsheet to pdf and download, check ixhd/gist:3660885 and Convert and Email Google Spreadsheets as PDF Files.

upload file to google drive folder instead of user browser javascript/jsquery

My current script uses the code below to download a CSV file to local drive,
function table2CSV() {
var dataURL = '',
fieldSeparator = ',',
textField = '"',
lineSeparator = '\n',
regExpTesto = /(")/g,
regExp = /[";]/;
$('table tr').each(function() {
var dataRow = '';
if ($('input:checkbox', this).is(':checked') || $(this).is(':first- child'))
{
$('td', this).not(':last').each(function() {
var value = $(this).text();
if (dataRow !== '') dataRow += fieldSeparator;
if (regExp.test(value)) {
value = textField + value.replace(regExpTesto, '$1$1') + textField;
}
dataRow += value;
});
if (dataURL !== '') dataURL += lineSeparator;
dataURL += dataRow;
}
});
window.location.href = 'data:text/csv;charset=utf-8;base64,' + btoa(dataURL);
}
The download is done bye this line as far as I can tell :
window.location.href = 'data:text/csv;charset=utf-8;base64,' + btoa(dataURL);
I would like to be able to have it download(upload/saved) to a shared google drive folder instead.
I have seen similar questions on the forum but can't seem to see how to point the download to a shared google-drive folder.
What must code must be added/changed in order to achieve this ?
Thank you
EDIT: Nevermind, just realised they say it does not support data URIs:
Data URIs and file:// URLs are not supported
I will keep this answer in case anyone else searches for non-data URI uploading
Having a quick look, I came upon Save to Drive
While this might not be exactly what you want, it looks like an easy way to add the ability to save the contents of any URI (hopefully a data URI too) to Google Drive, like so:
<script src="https://apis.google.com/js/platform.js" async defer></script>
<div class="g-savetodrive"
data-src="//example.com/path/to/myfile.pdf"
data-filename="My Statement.pdf"
data-sitename="My Company Name">
</div>

twitter sharing button bit.ly integration on a static website

I am trying to integrate bit.ly on my website in JS to short my url. All my url are too long, what will be the most straight foward way to use the bit.ly restful api for sharing button on a static website in HTML/javascript.
The result I want to get is when my user click share on my website the url is automatically shortened by bit.ly
here is the code I am currently using to share my pages dynamically on twitter:
<script type="text/javascript" charset="utf-8" src="http://bit.ly/javascript-api.js?version=latest&login=LOGINID&apiKey=APIKEY"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script>
function tweetCurrentPage()
{ window.open("https://twitter.com/share?url=" + escape(window.location.href) + "&text=" + document.title, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=300,width=600'); return false; }
var TweetThisLink = {
shorten : function(e) {
e.preventDefault();
var url = this.href.substr(this.href.indexOf('http:',5))
BitlyClient.shorten(url, 'TweetThisLink.response');
},
response : function(data) {
var bitly_link = null;
for (var r in data.results) {
bitly_link = data.results[r]['shortUrl'];
break;
}
var tweet_text = "I am reading documentation of"
document.location = "http://twitter.com/share?url=" + encodeURIComponent(tweet_text + ' ' + bitly_link);
}
}
jQuery('.tweetlink').bind('click', TweetThisLink.shorten);
</script>
tweet this link
Not sure if this is on purposefully obfuscated for the sake of the question, but
In your script tag the src is:
"http://bit.ly/javascript-api.js?version=latest&login=LOGINID&apiKey=APIKEY".
LOGINID & apiKey are placeholders are in-place. You need to replace them with the appropriate keys you should receive from bitly.
if this is on purpose for the sake of the question please ignore this answer.
don't know why but my function "tweetCurrentPage()" for dynamic url won't work it's giving me a respond INVALID_URI from bit.ly, but if I hard code the href value like this twitter.com/share?url=+exemple.com"; it's working...

How to save the current webpage with casperjs/phantomjs?

Is there a way to save the current webpage by using casperjs or phantomjs?
I tried to get the html and save it into a file. But the resulting file was a lot different from the screenshot of that time (with casper.capture). Is there a way to save the current webpage?
Andrey Borisko suggested to use the disk cache to retrieve the resources. My solution is not that efficient, but you don't need to decompress text files.
I use XMLHttpRequest to retrieve all resources after I registered them with the resource.received event handler. I then filter the resources into images, css and fonts. The current limitation is that remote resource paths that contain something like ../ or ./ are not handled correctly.
I retrieve the current page content with getHTML and iterate over all captured resources to replace the path used in the markup, that is identified by a portion of the complete resource URL, with a randomly generated file name. The file extension is created from the content type of the resource. It is converted using mimeType from this gist.
Since CSS files may contain background images or fonts, they have to be processed before saving to disk. The provided loadResource function loads the resource, but does not save it.
Since XMLHttpRequest to download the resources the script has to be invoked with the --web-security=false flag:
casperjs script.js --web-security=false
script.js
var casper = require("casper").create();
var utils = require('utils');
var fs = require('fs');
var mimetype = require('./mimetype'); // URL provided below
var cssResources = [];
var imgResources = [];
var fontResources = [];
var resourceDirectory = "resources";
var debug = false;
fs.removeTree(resourceDirectory);
casper.on("remote.message", function(msg){
this.echo("remote.msg: " + msg);
});
casper.on("resource.error", function(resourceError){
this.echo("res.err: " + JSON.stringify(resourceError));
});
casper.on("page.error", function(pageError){
this.echo("page.err: " + JSON.stringify(pageError));
});
casper.on("downloaded.file", function(targetPath){
if (debug) this.echo("dl.file: " + targetPath);
});
casper.on("resource.received", function(resource){
// don't try to download data:* URI and only use stage == "end"
if (resource.url.indexOf("data:") != 0 && resource.stage == "end") {
if (resource.contentType == "text/css") {
cssResources.push({obj: resource, file: false});
}
if (resource.contentType.indexOf("image/") == 0) {
imgResources.push({obj: resource, file: false});
}
if (resource.contentType.indexOf("application/x-font-") == 0) {
fontResources.push({obj: resource, file: false});
}
}
});
// based on http://docs.casperjs.org/en/latest/modules/casper.html#download
casper.loadResource = function loadResource(url, method, data) {
"use strict";
this.checkStarted();
var cu = require('clientutils').create(utils.mergeObjects({}, this.options));
return cu.decode(this.base64encode(url, method, data));
};
function escapeRegExp(string) {
// from https://stackoverflow.com/a/1144788/1816580
return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
function replaceAll(find, replace, str) {
// from https://stackoverflow.com/a/1144788/1816580
return str.replace(find, replace);
}
var wrapFunctions = [
function wrapQuot1(s){
return '"' + s + '"';
},
function wrapQuot2(s){
return "'" + s + "'";
},
function csswrap(s){
return '(' + s + ')';
}
];
function findAndReplace(doc, resources, resourcesReplacer) {
// change page on the fly
resources.forEach(function(resource){
var url = resource.obj.url;
// don't download again
if (!resource.file) {
// set random filename and download it **or** call further processing which in turn will load ans write to disk
resource.file = resourceDirectory+"/"+Math.random().toString(36).slice(2)+"."+mimetype.ext[resource.obj.contentType];
if (typeof resourcesReplacer != "function") {
if (debug) casper.echo("download resource (" + resource.obj.contentType + "): " + url + " to " + resource.file);
casper.download(url, resource.file, "GET");
} else {
resourcesReplacer(resource);
}
}
wrapFunctions.forEach(function(wrap){
// test the resource url (growing from the back) with a string in the document
var lastURL;
var lastRegExp;
var subURL;
// min length is 4 characters
for(var i = 0; i < url.length-5; i++) {
subURL = url.substring(i);
lastRegExp = new RegExp(escapeRegExp(wrap(subURL)), "g");
if (doc.match(lastRegExp)) {
lastURL = subURL;
break;
}
}
if (lastURL) {
if (debug) casper.echo("replace " + lastURL + " with " + resource.file);
doc = replaceAll(lastRegExp, wrap(resource.file), doc);
}
});
});
return doc;
}
function capturePage(){
// remove all <script> and <base> tags
this.evaluate(function(){
Array.prototype.forEach.call(document.querySelectorAll("script"), function(scr){
scr.parentNode.removeChild(scr);
});
Array.prototype.forEach.call(document.querySelectorAll("base"), function(scr){
scr.parentNode.removeChild(scr);
});
});
// TODO: remove all event handlers in html
var page = this.getHTML();
page = findAndReplace(page, imgResources);
page = findAndReplace(page, cssResources, function(cssResource){
var css = casper.loadResource(cssResource.obj.url, "GET");
css = findAndReplace(css, imgResources);
css = findAndReplace(css, fontResources);
fs.write(cssResource.file, css, "wb");
});
fs.write("page.html", page, "wb");
}
casper.start("http://www.themarysue.com/").wait(3000).then(capturePage).run(function(){
this.echo("DONE");
this.exit();
});
The magic happens in findAndReplace. capturePage is completely synchronous so it can be dropped anywhere without much head ache.
URL for mimetype.js
No, I don't think there is an easy way to do this as phantomjs doesn't support rendering pages in mht format (Render as a .mht file #10117). I believe that's what you wanted.
So, it needs some work to accomplish this. I did something similar, but i was doing it the other way around I had a rendered html code that I was rendering into image/pdf through phantomjs. I had to clean the file first and it worked fine for me.
So, what I think you need to do is:
strip all js calls, like script tags or onload attributes, etc..
if you have access from local to the resources like css, images and so on (and you don't need authentication to that domain where you grab the page) than you need to change relative paths of src attributes to absolute to load images/etc.
if you don't have access to the resources when you open the page then I think you need to implement similar script to download those resources at the time phantomjs loads the page and then redirect src attributes to that folder or maybe use data uri.
You might need to change links in css files as well.
This will bring up the images\fonts and styling you are missing currently.
I'm sure there are more points. I'll update the answer if you need more info, once I see my code.

Response Email Activity Images in CRM 2011

How can I preserve images in a response to an email activity?
The images in the email show when viewed in CRM - they are added as attachments. When I click the 'respond' button, write a response, and send the response the images are stripped from the email and are not attached to the email.
I have been trying all sorts of things with JScript .
I would rather not have to write anything other than JScript.
This is possible with javascript. I don't know what you tried but this can be done. I.e. catch the send event of your form and create the attachment with Javascript.
Other options are:
You could use a workflow to attach the note of the parent email to
the response. But then you will be forced to save your email wait a
little while (execution of the workflow) and then send the email.
Write plug-in code (but you won't use anything else but Javascript
Javascript to delete attachment:
function deleteAttachments(){
var notesId = {GUID of notes};
var objNotes = new Object();
objNotes.DocumentBody = null;
objNotes.FileName = null;
objNotes.FileSize = null;
objNotes.IsDocument = false;
updateRecord(notesId, objNotes, “AnnotationSet”);
}
function updateRecord(id, entityObject, odataSetName) {
var jsonEntity = window.JSON.stringify(entityObject);
var serverUrl = Xrm.Page.context.getServerUrl();
var ODATA_ENDPOINT = “/XRMServices/2011/OrganizationData.svc”;
var updateRecordReq = new XMLHttpRequest();
var ODataPath = serverUrl + ODATA_ENDPOINT;
updateRecordReq.open(‘POST’, ODataPath + “/” + odataSetName + “(guid’” + id + “‘)”, false);
updateRecordReq.setRequestHeader(“Accept”, “application/json”);
updateRecordReq.setRequestHeader(“Content-Type”, “application/json; charset=utf-8″);
updateRecordReq.setRequestHeader(“X-HTTP-Method”, “MERGE”);
updateRecordReq.send(jsonEntity);
}
I can access the attachments here: https:{org. URL}/xrmServices/2011/OrganizationData.svc/EmailSet(guid'3848cb4d-673f-e211-b9af-005056bd0001')/email_activity_mime_attachment
guid is the guid of the email.
The image is stored in d:Body as Base64.
Now all I need to do is rewrite img for each inline image with src="data:image/png;base64,theverylongstring...
All inline images will be preserved in the response as Base64.

Categories

Resources