I am using Mac with InDesign CC 219, and in my .indd file, some of the links are missing DocumentID and InstanceID, the below is the code I am using to get those details. If for any of the links, DocumentID and InstanceID are missing then I need to generate random DocumentID and InstanceID, and update the relevant links meta data. Is it possible through scripting, any directions please...
var doc = app.activeDocument;
for (var i = 0, len = doc.links.length; i < len; i++) {
var linkFilepath = File(doc.links[i].filePath).fsName;
var linkFileName = doc.links[i].name;
var xmpFile = new XMPFile(linkFilepath, XMPConst.FILE_INDESIGN, XMPConst.OPEN_FOR_READ);
var allXMP = xmpFile.getXMP();
// Retrieve values from external links XMP.
var documentID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);
var instanceID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'InstanceID', XMPConst.STRING);
}
$.level=0;
// Warn if there are no documents open.
if (!app.documents.length) {
alert('Open a document and try again.', 'Missing Document', false);
exit();
}
var doc = app.activeDocument;
// load XMP Library
function loadXMPLibrary() {
if (!ExternalObject.AdobeXMPScript) {
try {
ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
} catch (e) {
alert('Failed loading AdobeXMPScript library\n' + e.message, 'Error', true);
return false;
}
}
return true;
}
// Check all link statuses are be ok.
function linksStatusCheck(doc) {
for (var i = 0, len = doc.links.length; i < len; i++) {
if (doc.links[i].status !== LinkStatus.NORMAL) {
alert('The status of all links must be OK \nPlease update link status ' +
'via the Links panel and try again', 'Link Status', true);
exit();
}
}
return true;
}
function randomString(length, chars) {
var randomGenStr = '';
for (var i = length; i > 0; --i) {
randomGenStr += chars[Math.floor(Math.random() * chars.length)];
}
return randomGenStr;
}
function randomString(length) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for(var k = 0; k < length; k++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
function checkLinksXMP(doc) {
for (var i = 0, len = doc.links.length; i < len; i++) {
var linkFilepath = File(doc.links[i].filePath).fsName;
var linkFileName = doc.links[i].name;
var xmpFile = new XMPFile(linkFilepath, XMPConst.FILE_INDESIGN, XMPConst.OPEN_FOR_UPDATE);
var allXMP = xmpFile.getXMP();
// Retrieve values from external links XMP.
var documentID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);
var instanceID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'InstanceID', XMPConst.STRING);
// Useful for testing purposes....
// Log properties for each link to the console.
// Notify user when XMP is missing...
var docMissingCnt = 0;
var insMissingCnt = 0;
if (!documentID && !instanceID) {
alert('Link missing DocumentID and InstanceID\n' +
'Name: ' + linkFileName + '\n\n' +
'Path: ' + linkFilepath, 'Missing XMP', true);
docMissingCnt++;
insMissingCnt++;
} else if (!documentID) {
alert('Link missing DocumentID\n' +
'Name: ' + linkFileName + '\n\n' +
'Path: ' + linkFilepath, 'Missing XMP', true);
docMissingCnt++;
} else if (!instanceID) {
alert('Link missing InstanceID\n' +
'Name: ' + linkFileName + '\n\n' +
'Path: ' + linkFilepath, 'Missing XMP', true);
insMissingCnt++;
}
if(docMissingCnt > 0) {
documentID = randomString(32);
allXMP.setProperty(XMPConst.NS_XMP_MM, 'DocumentID', documentID);
var documentIDNew = allXMP.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);
$.writeln('DocumentID - New : ' + documentIDNew);
docMissingCnt = 0;
}
if(insMissingCnt > 0) {
instanceID = randomString(32);
allXMP.setProperty(XMPConst.NS_XMP_MM, 'InstanceID', instanceID);
var instanceIDNew = allXMP.getProperty(XMPConst.NS_XMP_MM, 'InstanceID', XMPConst.STRING);
$.writeln('InstanceID - New : ' + instanceIDNew);
insMissingCnt = 0;
}
}
}
if (loadXMPLibrary() && linksStatusCheck(doc)) {
checkLinksXMP(doc);
}
Function execution took 60002 ms, finished with status: 'timeout'
I have cloud function that collects users product & price data, hits an external API to get the latest prices and sends a notification if the price has changed. I've read several similar questions like this but I am in fact sending a response back to the client. I've tried increasing the timeout to 120 seconds, but it still times out. So, I think there might be an issue with how I'm returning promises? Any suggestions?
Here is my code:
exports.pushTestWithRP = functions.https.onRequest((req, res) => {
var uidsAndTokens = [];
ref.child('tokens').once('value').then(snap => {
snap.forEach(childSnap => {
uidsAndTokens.push({
uid: childSnap.key,
deviceToken: childSnap.val()
});
});
return uidsAndTokens;
}).then((uidsAndTokens) => {
var uidsAndCruises = [];
ref.child('watchlist-items/users').once('value').then(snap => {
snap.forEach(childSnap => {
var uid = childSnap.key;
childSnap.forEach(childChildSnap => {
var product = childChildSnap.key;
var productWatchInfo = childChildSnap.val();
uidsAndProducts.push({
uid: uid,
product: product,
watchInfo: productWatchInfo
});
}); // end childChildSnap
}); // end childSnap
return uidsAndProducts;
}).then((uidsAndProducts) => { // end snap watchlist-items/users
var uidsOnly = [];
for (var i=0; i<uidsAndTokens.length; i++) {
uidsOnly.push(uidsAndTokens[i].uid);
}
// user has a FCM token
var uidsAndProductsWithTokens = [];
for (var i=0; i<uidsAndProducts.length; i++) {
//check if exists in tokens array
var currUid = uidsAndProducts[i].uid;
if (uidsOnly.includes(currUid)) {
//console.log('this uid has a token: ', currUid);
uidsAndProductsWithTokens.push(uidsAndProducts[i]);
} else {
//this uid does NOT have a token
}
}
function getTokenForUid(uid) {
for (var i in uidsAndTokens) {
if (uidsAndTokens[i].uid == uid) {
var deviceToken = uidsAndTokens[i].deviceToken;
break;
}
}
return deviceToken;
}
var allPromises = [];
// call API only for uids with tokens
for (var i=0; i<uidsAndProductsWithTokens.length; i++) {
const product = uidsAndProductsWithTokens[i].product;
const uid = uidsAndProductsWithTokens[i].uid;
const deviceToken = getTokenForUid(uid);
const pDates = uidsAndProductsWithTokens[i].watchInfo.pDates;
const pName = uidsAndProductsWithTokens[i].watchInfo.pName;
getCurrentPricesFromAPI(product).then((response) => {
if (typeof response.response != 'undefined') {
const productId = response.response.product.product_id;
const allPrices = response.response.prices;
const promises = [];
// parse thru prices and send notifications
for (var date in pDates) {
// get all current prices and sort by price to get cheapest
var cheapest = [];
for (var i = 0; i < allPrices.length; i++) {
if (allPrices[i].data[productId][date] && allPrices[i].data[productId][date].hasOwnProperty('Inside')) {
const iPrice = allPrices[i].data[productId][date].Inside;
cheapest.push(iPrice);
}
}
if (cheapest[0] > 0) {
cheapest = cheapest.sort(function (a, b) { return a - b; });
if (sDates[date].hasOwnProperty('Inside')) {
const priceDiff = cheapest[0] - sDates[date].Inside.price;
if (priceDiff < -10) {
const payload = {
notification: {
title: pName + ' Price DROP Alert!',
body: 'prices for the ' + date + ' are $' + cheapest[0] + ' (DOWN $' + Math.abs(priceDiff) + ')',
sound: 'default'
}
};
promises.push(admin.messaging().sendToDevice(deviceToken, payload));
}
else if (priceDiff > 10) {
const payload = {
notification: {
title: pName + ' Price Hike Alert',
body: 'prices for the ' + date + ' are $' + cheapest[0] + ' (UP $' + priceDiff + ')',
sound: 'default'
}
};
promises.push(admin.messaging().sendToDevice(deviceToken, payload));
}
}
}
}
allPromises = allPromises.concat(promises);
}
}) // end handle API response
} // end for loop
return allPromises;
}).then((allPromises) => {
return Promise.all(allPromises);
res.send('got tokens and ids');
}).catch(error => {
res.send('there was an error');
});
}); // end uidsAndTokens
}); // end function
I can't figure this out and would appreciate any help!
I got an infinite loop inserting an item to my Firebase, so when I click on my post form, it inserts my item until I kill the process. Can you help me how to solve it?
PS : I'm using VueJS
var usersRef = new Firebase('https://xxxxxxxxxxxxxxxxxx.firebaseio.com/userslist/');
var vm = new Vue({
el: '#list1',
data: function () {
return{
// Initialisation du tableau de users
users: [],
sortKey: 'id',
reverse: 1,
nextKey: null
};
},
ready: function () {
// this works
//this.sortKey = 'name';
},
methods: {
updateUsers: function () {
},
removeUser: function (item) {
usersRef.child(item.id).remove();
},
addItem: function (e) {
e.preventDefault();
// get form data as Json
var jsonData = ConvertFormToJSON('form_add');
//console.log(jsonData);//test ok
//get the last item id and save it to next key
usersRef.limitToLast(1).on('child_added', function (snapshot) {
var lastKey = parseInt(snapshot.key());
this.nextKey = lastKey + 1;
console.log('nextKey ' + nextKey);//test ok
//
// save data to firebase
usersRef.child(this.nextKey).set(jsonData, function (snap) {
//console.log('add success');//test
//Notification par Jquery
var itemAdded = snap.val();
$.notify(itemAdded.firstname + " " + itemAdded.name + " à été ajouté", "success", {position: "top right"});
this.pendingKey = 0;
});
});
},
// Tri des colonnes
sortBy: function (_sortKey) {
this.reverse = (this.reverse == -1) ? 1 : -1;
this.sortKey = _sortKey;
console.log("SortKey " + this.sortKey);
}
}
});
usersRef.on('child_added', function (snapshot) {
var item = snapshot.val();
item.id = snapshot.key();
console.log('id ' + item.id);
vm.users.push(item);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
thanks for your help
OK I've found a solution :
//get the last item id and save it to next key
var _nextKey = this.nextKey;
usersRef.limitToLast(1).on('child_added', function (snapshot) {
var lastKey = parseInt(snapshot.key());
_nextKey = lastKey + 1;
});
this.nextKey = _nextKey;
console.log('nextKey ' + this.nextKey);//test ok
// save data to firebase
usersRef.child(this.nextKey).set(jsonData, function (snap) {
//console.log('add success');//test
//Notification par Jquery
var itemAdded = snap.val();
$.notify(itemAdded.firstname + " " + itemAdded.name + " à été ajouté", "success", {position: "top right"});
});
May it help someone!
I'm looking around for an extension that count the number I visit a site daily, and I have edited an extension from store and it work perfectly
But the problem is when I put that site into an iframe, it's not counting anymore, somebody plz take a look and give me some advice here? many thanks
manifest.json
{
"background": {
"persistent": true,
"scripts": [ "jquery.js", "counter.js", "background.js" ]
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "counter.html"
},
"description": "Counter",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgrQn46/0KFBVFH0l9mKUXPOns5h0YMQ0isRXkB/GzK1h8JfvILDuxkIC7jbyePzMgbY0b8TO7L7FR3m4qcnPJZemz2yrGnHOkppaOWaAuyJm2cQeOul89qNPsC1GROoKfBmajag5OaOr02y4de3MEKSTubtjlO5crbg8xKnp7nHbqkeIq9MOMsEo0/uOQMqvixMnIAfPamUPOQfqmG2lUeo9UgTUoFBaxpf5VhgcuDcLHnkkSrzRrL0DoYeYFqyXwGmiCdvmwkWF+Eax/+s2xGemqMSUj0mrMxzz8KfoWuAWn9pcXYMEINSelIwS/x+wf+NWWmsCY0pV9yF54+vprQIDAQAB",
"manifest_version": 2,
"name": "counter",
"permissions": [ "tabs", "history", "background", "webNavigation", "http://*/*", "activeTab" ],
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "0.4"
}
counter.js
$(document).ready(function(){
// Display day count
$('.day-count').text(countForToday());
// Display yesterday count
var yesterdayToday = new Date();
var yesterday = new Date(yesterdayToday.setDate(yesterdayToday.getDate() - 1));
var yesterdayString = dateStringForDate(yesterday);
var yesterdayCount = countForDay(yesterdayString);
$('.yesterday-count').text(yesterdayCount);
// Display last 7 days
var weeklyTotal = countForDaysFromToday(7);
$('.week-count').text(weeklyTotal);
// Display last 28 days
var monthlyTotal = countForDaysFromToday(28);
$('.month-count').text(monthlyTotal);
// Total
var total = 0;
for (var i = 0; i < localStorage.length; i++){
var key = localStorage.key(i);
if (key.indexOf("dayCount") > -1) {
var entry = JSON.parse(localStorage.getItem(key));
total += entry.length;
}
}
$('.all-count').text(total);
chrome.browserAction.setBadgeBackgroundColor({ color: '#3BAFDA' });
});
function countForToday() {
// Display day count
var today = new Date();
var todayString = dateStringForDate(today);
var todayCount = countForDay(todayString);
return todayCount;
}
function appendUrlForDay(pageUrl, dateString) {
// get
var currentUrls = urlsForDay(dateString);
// append
var found = false;
for(var i = 0; i < currentUrls.length; i++) {
if (currentUrls[i] == pageUrl) {
found = true;
break;
}
}
if (!found) {
currentUrls.push(pageUrl);
}
// set
localStorage.setItem("dayCount-" + dateString, JSON.stringify(currentUrls));
}
function dateStringForDate(dateObj) {
var month = dateObj.getUTCMonth() + 1;
var day = dateObj.getUTCDate();
var year = dateObj.getUTCFullYear();
var dateString = year + "/" + month + "/" + day;
return dateString;
}
function countForDaysFromToday(number_of_days) {
console.log(number_of_days);
var total = 0;
for (var i = 0; i < number_of_days; i++) {
var today = new Date();
var dayToLookup = new Date(today.setDate(today.getDate() - i));
var dayString = dateStringForDate(dayToLookup);
var dayCount = countForDay(dayString);
total += dayCount;
}
return total;
}
function urlsForDay(dateString) {
var item = localStorage.getItem("dayCount-" + dateString);
return JSON.parse(item);
}
function countForDay(dateString) {
var currentUrls = urlsForDay(dateString);
if (currentUrls != null) {
return currentUrls.length;
} else {
return 0;
}
}
background.js
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
// Get chrome history
chrome.history.search({text: '', maxResults: 1}, function(data) {
data.forEach(function(page) {
var dateObj = new Date(page.lastVisitTime);
var dateString = dateStringForDate(dateObj);
// Display last page visit
var pageUrl = page.url;
// Set value to 0 on first load
if (localStorage.getItem("dayCount-" + dateString) === null) {
localStorage.setItem("dayCount-" + dateString, JSON.stringify([]));
}
// Check if last page contains mysite.com
if (pageUrl.indexOf("mysite.com") > -1) {
appendUrlForDay(pageUrl, dateString);
}
chrome.browserAction.setBadgeText({ text: countForToday().toString() });
});
});
});
By default, your content script will only run in the top frame of a page. If you want it to run for all frames, you have to set all_frames to true in your manifest.
Google documents this here: https://developer.chrome.com/extensions/content_scripts (just search for all_frames on the page).
I am using CRM ONLINE 2013.
How to automate below process?
On Approval Of Quotation, Run Report.
Generate PDF.
Send an Email With PDF as attachment.
As I have gone through many forums for this topic, but creating a plugin code for generating Report PDF is not possible in CRM ONLINE.
What is the alternate way to do this..?
I have tried below code and it is working fine for me.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script type="text/javascript">
if (typeof (SDK) == "undefined")
{ SDK = { __namespace: true }; }
SDK.JScriptRESTDataOperations = {
_context: function () {
if (typeof GetGlobalContext != "undefined")
{ return GetGlobalContext(); }
else {
if (typeof Xrm != "undefined") {
return Xrm.Page.context;
}
else { return new Error("Context is not available."); }
}
},
_getServerUrl: function () {
var serverUrl = this._context().getServerUrl()
if (serverUrl.match(/\/$/)) {
serverUrl = serverUrl.substring(0, serverUrl.length - 1);
}
return serverUrl;
},
_ODataPath: function () {
return this._getServerUrl() + "/XRMServices/2011/OrganizationData.svc/";
},
_errorHandler: function (req) {
return new Error("Error : " +
req.status + ": " +
req.statusText + ": " +
JSON.parse(req.responseText).error.message.value);
},
_dateReviver: function (key, value) {
var a;
if (typeof value === 'string') {
a = /Date\(([-+]?\d+)\)/.exec(value);
if (a) {
return new Date(parseInt(value.replace("/Date(", "").replace(")/", ""), 10));
}
}
return value;
},
Create: function (object, type, successCallback, errorCallback) {
var req = new XMLHttpRequest();
req.open("POST", this._ODataPath() + type + "Set", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
if (this.status == 201) {
successCallback(JSON.parse(this.responseText, SDK.JScriptRESTDataOperations._dateReviver).d);
}
else {
errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
}
}
};
req.send(JSON.stringify(object));
},
Retrieve: function (id, type, successCallback, errorCallback) {
var req = new XMLHttpRequest();
req.open("GET", this._ODataPath() + type + "Set(guid'" + id + "')", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
if (this.status == 200) {
successCallback(JSON.parse(this.responseText, SDK.JScriptRESTDataOperations._dateReviver).d);
}
else {
errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
}
}
};
req.send();
},
Update: function (id, object, type, successCallback, errorCallback) {
var req = new XMLHttpRequest();
req.open("POST", this._ODataPath() + type + "Set(guid'" + id + "')", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("X-HTTP-Method", "MERGE");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
if (this.status == 204 || this.status == 1223) {
successCallback();
}
else {
errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
}
}
};
req.send(JSON.stringify(object));
},
Delete: function (id, type, successCallback, errorCallback) {
var req = new XMLHttpRequest();
req.open("POST", this._ODataPath() + type + "Set(guid'" + id + "')", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("X-HTTP-Method", "DELETE");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
if (this.status == 204 || this.status == 1223) {
successCallback();
}
else {
errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
}
}
};
req.send();
},
RetrieveMultiple: function (type, filter, successCallback, errorCallback) {
if (filter != null) {
filter = "?" + filter;
}
else { filter = ""; }
var req = new XMLHttpRequest();
req.open("GET", this._ODataPath() + type + "Set" + filter, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
if (this.status == 200) {
successCallback(JSON.parse(this.responseText, SDK.JScriptRESTDataOperations._dateReviver).d.results);
}
else {
errorCallback(SDK.JScriptRESTDataOperations._errorHandler(this));
}
}
};
req.send();
},
__namespace: true
};
</script>
<script type="text/javascript">
//Create Email and link it with Order as Regarding field
var Xrm;
var email = new Object();
var ownerID = "";
var CustomerId = "";
if (window.opener) { Xrm = window.opener.Xrm; }
else if (window.parent) { Xrm = window.parent.Xrm; }
//Get ownerid who send email of quotation to customer
function GetOwnerID() {
var owner = Xrm.Page.getAttribute("ownerid").getValue();
ownerID = owner[0].id;
var ownerName = owner[0].name;
var entityType = owner[0].entityType;
GetToEmailGUID();
}
//Get customerid who receive email of quotation from owner
function GetToEmailGUID() {
var Customer = Xrm.Page.getAttribute('customerid').getValue();
CustomerId = Customer[0].id;
var CustomerName = Customer[0].name;
var entityType = Customer[0].entityType;
//if CustomerId is type of "Account" then get Primary Contact id of that account
if (entityType == "account") {
var contact = Xrm.Page.getAttribute("customerid").getValue();
if (contact === null) return;
var serverUrl = Xrm.Page.context.getClientUrl();
var oDataSelect = serverUrl + "/XRMServices/2011/OrganizationData.svc/AccountSet(guid'" + contact[0].id + "')?$select=PrimaryContactId";
var req = new XMLHttpRequest();
req.open("GET", oDataSelect, false);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json;charset=utf-8");
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status === 200) {
var retrieved = JSON.parse(req.responseText).d;
CustomerId = retrieved.PrimaryContactId.Id;
}
else {
alert(this.statusText);
}
}
};
req.send();
}
}
function CreateEmail() {
GetOwnerID();
email.Subject = "Email with Report Attachment";
//Set The current order as the Regarding object
email.RegardingObjectId = {
Id: Xrm.Page.data.entity.getId(), //Get the current entity Id , here OrderId
LogicalName: Xrm.Page.data.entity.getEntityName()//Get the current entity name, here it will be “salesOrder”
};
//Create Email Activity
SDK.JScriptRESTDataOperations.Create(email, "Email", EmailCallBack, function (error) { alert(error.message); });
}
// Email Call Back function
function EmailCallBack(result) {
email = result; // Set the email to result to use it later in email attachment for retrieving activity Id
var activityPartyFrom = new Object();
// Set the From party of the ActivityParty to relate an entity with Email From field
activityPartyFrom.PartyId = {
Id: CustomerId, //"79EBDD26-FDBE-E311-8986-D89D6765B238", // id of entity you want to associate this activity with.
LogicalName: "contact"
};
// Set the "activity" of the ActivityParty
activityPartyFrom.ActivityId = {
Id: result.ActivityId,
LogicalName: "email"
};
// Now set the participation type that describes the role of the party on the activity).
activityPartyFrom.ParticipationTypeMask = { Value: 2 }; // 2 means ToRecipients
// Create the from ActivityParty for the email
SDK.JScriptRESTDataOperations.Create(activityPartyFrom, "ActivityParty", ActivityPartyFromCallBack, function (error) { alert(error.message); });
var activityPartyTo = new Object();
// Set the From party of the ActivityParty to relate an entity with Email From field
activityPartyTo.PartyId = {
Id: ownerID, //"79EBDD26-FDBE-E311-8986-D89D6765B238", // id of entity you want to associate this activity with.
LogicalName: "systemuser"
};
// Set the "activity" of the ActivityParty
activityPartyTo.ActivityId = {
Id: result.ActivityId,
LogicalName: "email"
};
// Now set the participation type that describes the role of the party on the activity).
activityPartyTo.ParticipationTypeMask = { Value: 1 }; // 1 means Sender
// Create the from ActivityParty
SDK.JScriptRESTDataOperations.Create(activityPartyTo, "ActivityParty", ActivityPartyToCallBack, function (error) { alert(error.message); });
}
//ActivityParty From Callback
function ActivityPartyFromCallBack(result) {
}
//ActivityParty To Callback
function ActivityPartyToCallBack(result) {
GetReportId('Quotation');
}
//Create attachment for the created email
function CreateEmailAttachment() {
//get reporting session and use the params to convert a report in PDF
var params = getReportingSession();
//Email attachment parameters
var activitymimeattachment = Object();
activitymimeattachment.ObjectId = Object();
activitymimeattachment.ObjectId.LogicalName = "email";
activitymimeattachment.ObjectId.Id = email.ActivityId;
activitymimeattachment.ObjectTypeCode = "email",
activitymimeattachment.Subject = "File Attachment";
activitymimeattachment.Body = encodePdf(params);
activitymimeattachment.FileName = "Report.pdf";
activitymimeattachment.MimeType = "application/pdf";
//Attachment call
SDK.JScriptRESTDataOperations.Create(activitymimeattachment, "ActivityMimeAttachment", ActivityMimeAttachmentCallBack, function (error) { alert(error.message); });
}
//ActivityMimeAttachment CallBack function
function ActivityMimeAttachmentCallBack(result) {
var features = "location=no,menubar=no,status=no,toolbar=no,resizable=yes";
var width = "800px";
var height = "600px";
window.open(Xrm.Page.context.getServerUrl() + "main.aspx?etc=" + 4202 + "&pagetype=entityrecord&id=" + email.ActivityId, "_blank", features);
// To open window which works in outlook and IE both
//openStdWin(Xrm.Page.context.getServerUrl() + "main.aspx?etc=" + 4202 + "&pagetype=entityrecord&id=" + email.ActivityId, "_blank", width, height, features);
}
//This method will get the reportId based on a report name that will be used in getReportingSession() function
function GetReportId(reportName) {
var oDataSetName = "ReportSet";
var columns = "ReportId";
var filter = "Name eq '" + reportName + "'";
retrieveMultiple(oDataSetName, columns, filter, onSuccess);
}
function retrieveMultiple(odataSetName, select, filter, successCallback) {
var serverUrl = Xrm.Page.context.getServerUrl();
var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";
var odataUri = serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "?";
if (select) {
odataUri += "$select=" + select + "&";
}
if (filter) {
odataUri += "$filter=" + filter;
}
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: odataUri,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function (data) {
if (successCallback) {
if (data && data.d && data.d.results) {
successCallback(data.d.results);
}
else if (data && data.d) {
successCallback(data.d);
}
else {
successCallback(data);
}
}
},
error: function (XmlHttpRequest, errorThrown) {
if (XmlHttpRequest && XmlHttpRequest.responseText) {
alert("Error while retrieval ; Error – " + XmlHttpRequest.responseText);
}
}
});
}
function onSuccess(data) {
reportId = data[0].ReportId.replace('{', ").replace('}', ");
CreateEmailAttachment(); // Create Email Attachment
}
//Gets the report contents
function getReportingSession() {
var pth = Xrm.Page.context.getServerUrl() + "/CRMReports/rsviewer/reportviewer.aspx";
var retrieveEntityReq = new XMLHttpRequest();
var Id = Xrm.Page.data.entity.getId();
var quotationGUID = Id.replace('{', ""); //set this to selected quotation GUID
quotationGUID = quotationGUID.replace('}', "");
var reportName = "Quotation"; //set this to the report you are trying to download
var reportID = "7C39D18F-1DC6-E311-8986-D89D6765B238"; //set this to the guid of the report you are trying to download
var rptPathString = ""; //set this to the CRMF_Filtered parameter
var strParameterXML = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'><entity name='quote'><all-attributes /><filter type='and'><condition attribute='quoteid' operator='eq' uitype='quote' value='" + quotationGUID + "' /> </filter></entity></fetch>";
retrieveEntityReq.open("POST", pth, false);
retrieveEntityReq.setRequestHeader("Accept", "*/*");
retrieveEntityReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
rptPathString = "id=%7B" + reportID + "%7D&uniquename=" + Xrm.Page.context.getOrgUniqueName() + "&iscustomreport=true&reportnameonsrs=&reportName=" +
reportName + "&isScheduledReport=false&p:CRMAF_Filteredquote=" + strParameterXML;
//remove the part starting from &p:salesorderid if your report has no parameters
retrieveEntityReq.send(rptPathString);
var x = retrieveEntityReq.responseText.indexOf("ReportSession=");
var ret = new Array();
ret[0] = retrieveEntityReq.responseText.substr(x + 14, retrieveEntityReq.responseText.indexOf("&", x) - x - 14); //the session id
x = retrieveEntityReq.responseText.indexOf("ControlID=");
ret[1] = retrieveEntityReq.responseText.substr(x + 10, retrieveEntityReq.responseText.indexOf("&", x) - x - 10); //the control id
return ret;
}
var bdy = new Array();
var bdyLen = 0;
function concat2Bdy(x) {
bdy[bdyLen] = x;
bdyLen++;
}
function encodePdf(params) {
bdy = new Array();
bdyLen = 0;
var retrieveEntityReq = new XMLHttpRequest();
var pth = Xrm.Page.context.getServerUrl() + "/Reserved.ReportViewerWebControl.axd?ReportSession=" + params[0] +
"&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=" + params[1] +
"&OpType=Export&FileName=Public&ContentDisposition=OnlyHtmlInline&Format=PDF";
retrieveEntityReq.open("GET", pth, false);
retrieveEntityReq.setRequestHeader("Accept", "*/*");
retrieveEntityReq.send();
BinaryToArray(retrieveEntityReq.responseBody);
return encode64(bdy);
}
var StringMaker = function () {
this.parts = [];
this.length = 0;
this.append = function (s) {
this.parts.push(s);
this.length += s.length;
}
this.prepend = function (s) {
this.parts.unshift(s);
this.length += s.length;
}
this.toString = function () {
return this.parts.join('');
}
}
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function encode64(input) {
var output = new StringMaker();
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
while (i < input.length) {
chr1 = input[i++];
chr2 = input[i++];
chr3 = input[i++];
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output.append(keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4));
}
return output.toString();
}
</script>
<script type="text/vbscript">
Function BinaryToArray(Binary)
Dim i
ReDim byteArray(LenB(Binary))
For i = 1 To LenB(Binary)
byteArray(i-1) = AscB(MidB(Binary, i, 1))
concat2Bdy(AscB(MidB(Binary, i, 1)))
Next
BinaryToArray = byteArray
End Function
</script>
</head>
<body>
<input type="button" onclick="CreateEmail();" value="Attach Report" />
</body>
</html>