I currently have a Page Fragment with the following code that creates an entry for a datasource and sends out an email (code below) notifying everyone.
Button:
newSalesEmailMessage(widget);
widget.datasource.createItem();
app.closeDialog();
Client Script Email notification code:
/**
* Calls a server method to send an email.
* #param {Widget} sendButton - widget that triggered the action.
*/
function newSalesEmailMessage(sendButton) {
var pageWidgets = sendButton.root.descendants;
var fullName = app.datasources.Directory.item.FullName;
var htmlbody = '<b><font size="3">' + fullName + '</font></b>' + ' has created a new sales entry for: ' +
'<h1><span style="color:#2196F3">' +pageWidgets.ProjectName.value + '</h1>' +
'<p>Contact: <b>' + pageWidgets.Contact.value + '</b>' +
'<p>Sales Person: <b>' + pageWidgets.SalesPerson.value + '</b>' +
'<p>Notes: <b>' + pageWidgets.Notes.value + '</b>';
google.script.run
.withSuccessHandler(function() {
})
.withFailureHandler(function(err) {
console.error(JSON.stringify(err));
})
.sendEmailCreate(
'test#email.com',
'New Sales Entry for: ' + pageWidgets.ProjectName.value,
htmlbody);
}
onCreate code for the Model:
// onCreate
var email = Session.getActiveUser().getEmail();
var directoryQuery = app.models.Directory.newQuery();
directoryQuery.filters.PrimaryEmail._equals = email;
var reporter = directoryQuery.run()[0];
record.reported_by = email;
record.reported_full_name = reporter.FullName;
record.Date = new Date();
Everything works except for the fullName option. It keeps pulling my name even when another user creates an entry (maybe because I am an admin?). I have a Directory Model setup and that seems to work for when I am displaying the full name for a users's comments.
I would like to have fullName = the name of the person currently creating the entry.
Thank you for your help!
App Startup Script:
// App startup script
// CurrentUser - assuming that it is Directory model's datasource
// configured to load record for current user.
loader.suspendLoad();
app.datasources.Directory.load({
success: function() {
loader.resumeLoad();
},
failure: function(error) {
// TODO: Handle error
}
});
You need to filter your Directory model datasource. If you are planning to use it for different purposes, then I'll recommend to create dedicated datasource for current user. You can filter it on server (preferable) or client side:
Filter on server, load on client:
// Directory model's Server Script for Current User datasource
var query = app.models.Directory.newQuery();
query.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
return query.run();
// ------------------------
// Your startup script will remain almost the same:
loader.suspendLoad();
app.datasources.CurrentUser.load({
success: function() {
loader.resumeLoad();
},
failure: function(error) {
// TODO: Handle error
}
});
Client-only:
var currentUserDs = app.datasources.CurrentUser;
currentUserDs.query.filters.PrimaryEmail._equals = app.user.email;
loader.suspendLoad();
currentUserDs.load({
success: function() {
loader.resumeLoad();
},
failure: function(error) {
// TODO: Handle error
}
});
Thank you to Pavel. Everything worked, but it took me a few to understand exactly what I needed to do. For those who want to try and replicate what I did here were the steps.
First I had to create a Directory Model.
Then under the App Settings section for the app itself (click the gear) I put the following code under the App Startup Script - Client Script section:
loader.suspendLoad();
app.datasources.CurrentUser.load({
success: function() {
loader.resumeLoad();
},
failure: function(error) {
// TODO: Handle error
}
});
Next I went under the Datasources section for the Directory model and added a datasource called CurrentUser.
In the Query - Server Script section I put:
var query = app.models.Directory.newQuery();
query.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
return query.run();
This filters the datasource so that the only entry in there is the current user. Then I adjusted my "var fullName" in the email Client Script to point to the new datasource:
/**
* Calls a server method to send an email.
* #param {Widget} sendButton - widget that triggered the action.
*/
function newSalesEmailMessage(sendButton) {
var pageWidgets = sendButton.root.descendants;
var fullName = app.datasources.CurrentUser.item.FullName;
var htmlbody = '<b><font size="3">' + fullName + '</font></b>' + ' has created a new sales entry for: ' +
'<h1><span style="color:#2196F3">' +pageWidgets.ProjectName.value + '</h1>' +
'<p>Contact: <b>' + pageWidgets.Contact.value + '</b>' +
'<p>Sales Person: <b>' + pageWidgets.SalesPerson.value + '</b>' +
'<p>Notes: <b>' + pageWidgets.Notes.value + '</b>';
google.script.run
.withSuccessHandler(function() {
})
.withFailureHandler(function(err) {
console.error(JSON.stringify(err));
})
.sendEmailCreate(
'test#email.com',
'New Sales Entry for: ' + pageWidgets.ProjectName.value,
htmlbody);
}
Related
I am using ExtendScript to work on metadata information of .indd files in InDesignCC 2019.
My requirement is that I need to access all individual links metadata associated with the .indd file and see whether any of the links metadata is missing DocumentID and InstanceID. If any of the links metadata do not have a value for DocumentID and/or InstanceID properties then I need to display the file name associated with that link, indicating that, that particular file is missing a DocumentID and/or InstanceID.
I have used the below script to access the meta data of .indd file.
$.level=0
// load XMP Library
function loadXMPLibrary() {
if (!ExternalObject.AdobeXMPScript) {
try{ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');}
catch (e){alert('Unable to load the AdobeXMPScript library!'); return false;}
}
return true;
}
var myFile= app.activeDocument.fullName;
var myXmp = null;
// check library and file
if (loadXMPLibrary() && myFile !== null) {
xmpFile = new XMPFile(myFile.fsName, XMPConst.FILE_INDESIGN, XMPConst.OPEN_FOR_UPDATE);
myXmp = xmpFile.getXMP();
$.writeln(xmpFile.getPacketInfo());
}
if (myXmp){
$.writeln (myXmp);
$.writeln (XMPFile.getFormatInfo(XMPConst.FILE_INDESIGN));
}
Can any one help me how can I proceed further in this?
Once you've obtained the XMP from the link, i.e. xmpFile.getXMP(), you'll need to:
Utilize the getProperty() method to retrieve the value of a specific metadata property.
Typically the DocumentID and InstanceID will be associated with the NS_XMP_MM schema namespace, which is described as:
NS_XMP_MM The XML namespace for the XMP digital asset management schema.
For instance, to obtain the DocumentID you'll do something like the following:
var documentID = allXMP.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);
Solution:
The gist below (example.jsx) performs the following:
Checks whether a .indd file is open and notifies the user if there is not one open.
Loads the AdobeXMPScript XMP Library
Checks that the status of all Links are "OK", i.e. it checks that they are not "Modified", nor "Missing". If any link status is not "OK" the user is asked to update their status to "OK".
Checks whether each linked asset has a DocumentID and InstanceID and logs their values to the JavaScript Console.
For any linked asset that does not have a DocumentID and/or InstanceID an alert dialog appears indicating the name and path to the linked asset.
example.jsx
$.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 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_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);
// Useful for testing purposes....
// Log properties for each link to the console.
$.writeln('linkName: ' + linkFileName);
$.writeln('filePath: ' + linkFilepath);
$.writeln('DocumentID: ' + documentID);
$.writeln('InstanceID: ' + instanceID);
$.writeln('-------------------------------------');
// Notify user when XMP is missing...
if (!documentID && !instanceID) {
alert('Link missing DocumentID and InstanceID\n' +
'Name: ' + linkFileName + '\n\n' +
'Path: ' + linkFilepath, 'Missing XMP', true);
} else if (!documentID) {
alert('Link missing DocumentID\n' +
'Name: ' + linkFileName + '\n\n' +
'Path: ' + linkFilepath, 'Missing XMP', true);
} else if (!instanceID) {
alert('Link missing InstanceID\n' +
'Name: ' + linkFileName + '\n\n' +
'Path: ' + linkFilepath, 'Missing XMP', true);
}
}
}
if (loadXMPLibrary() && linksStatusCheck(doc)) {
checkLinksXMP(doc);
}
I am working on Casper JS web scraping, for now I have scraped the title from a site. I am making ajax request to the php file where I am collecting the data through post, but the data is not being sent through it while the response status is 200 and OK I don't know what is causing the problem.
The rest of the data is inserted successfully into the table, but not the title.
var casper = require('casper').create();
casper.start("https://www.google.com/");
casper.then(function(){
var data = this.evaluate(function(){
var title = document.getElementsByTagName('title')[0].textContent;
return title;
})
console.log(data);
casper.thenOpen("http://localhost/fiverr/Crawl%20The%20Jobs/modal_scripts.php",{method:"POST",data:data+"&crawled_jobs=true"}).then(function(res){
console.log(res.status);
})
})
casper.run();
The PHP script, I am collecting data in :
if (isset($_POST["crawled_jobs"])) {
$title = $_POST["data"];
$jobs_list_insert = "INSERT INTO jobs VALUES(null,'$title','nady','ahmad','kahn','yess','yesss')";
$con->query($jobs_list_insert);
}
Found a solution :
var i = 0;
console.log("Data Length : " + d.length);
function sendData(i) {
console.log("Posting Data...");
casper.thenOpen("http://localhost/fiverr/Crawl%20The%20Jobs/modal_scripts.php", {
method: "POST",
data: "title=" + d[i].title + "&loc=" + d[i].loc + "&day=" + d[i].day + "&salary=" + d[i].salary + "&link=" + d[i].link + "&logo=" + d[i].compLogo + "&crawled_jobs=true",
async: false
}).then(function(res) {
console.log(res.status);
sendData(i + 1);
})
}
sendData(i);
I've updated my meteor to 1.2, and I'm now trying to use the email attachment feature, but not sure how to.
Meteor's guide says refer to this, but it's not very helpful..
if(true == true){
var dataAttachments = attachment;
var dataText =
"Client Name: " + name +
"\rEmail: " + email +
"\rPhone: " + phone +
"\rCompany: " + company +
"\rDeliverables: " + deliverables +
"\rCopywriting: " + copywriting +
"\rPrint Services: " + print +
"\rIllustration: " + illustration +
"\rphotography: " + photography +
"\rTimelines: " + timelines +
"\rBudget: " + budget +
"\rDescription: " + description;
Meteor.call('sendEmail', dataText, dataAttachment);
//throwAlert is my helper method which creates popup with message
alert('Email sent');
}else{
alert('An error occurred. Sorry');
return false;
}
}
});
and
Meteor.methods({
sendEmail: function (text) {
check([text], [String]);
this.unblock();
Email.send({
to: 'jaeeun#antarcti.cc',
from: 'contact#myClientProject.com',
subject: 'New message from contact form',
text: text
});
Email.send().addAttachment(attachment);
}
});
I would suggest installing this package: https://atmospherejs.com/ashutosh/email-att
Then do:
var attachments = [];
attachments.push({filename: "xxx", filePath: "xxx"});
var email = {
from: "test#gmail.com",
to: "test2#gmail.com",
subject: "Test!",
text: "Text!"
attachmentOptions: attachments
};
Meteor.call('send_one_email_with_attachments', email, function(){});
Meteor.methods({
send_one_email_with_attachments: function(email){
this.unblock();
EmailAtt.send(email);
};
});
This made my life a lot easier after I fought Meteor's built-in email for a while. It even works side-by-side, so you can still use your old non-attachment email functions!
I am trying to use SQLLItePlugin for Android but its not working. I will list my steps:
1. I have installed cordova pjhonegap from phonegap. I am developing my mobile app Phonegap, html5, javascript, css3 using Netbeans as IDE.
2. Downloaded plugin from https://github.com/brodysoft/Cordova-SQLitePlugin.
3. Added SQLitePlugin.js to js folder of project.
4. Added com.brodysoft.sqlitePlugin.file=https://github.com/brodysoft/Cordova-SQLitePlugin.git in plugin.properties.
5. Am opening database on deviceready as
var app = {
initialize: function () {
this.bindEvents();
},
bindEvents: function () {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function () {
app.receivedEvent('deviceready');
var db = window.sqlitePlugin.openDatabase('gdata.db');
console.log('ready');
db.transaction(function (tx) {
tx.executeSql('DROP TABLE IF EXISTS test_table');
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
// demonstrate PRAGMA:
db.executeSql("pragma table_info (test_table);", [], function (res) {
console.log("PRAGMA res: " + JSON.stringify(res));
});
tx.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], function (tx, res) {
console.log("insertId: " + res.insertId + " -- probably 1");
console.log("rowsAffected: " + res.rowsAffected + " -- should be 1");
db.transaction(function (tx) {
tx.executeSql("select count(id) as cnt from test_table;", [], function (tx, res) {
console.log("res.rows.length: " + res.rows.length + " -- should be 1");
console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
});
});
}, function (e) {
console.log("ERROR: " + e.message);
});
});
},
// Update DOM on a Received Event
receivedEvent: function (id) {
var parentElement = document.getElementById(id);
console.log('Received Event: ' + id);
}
};
app.initialize();
Running the build on android devvice directly.
It keeps on throwing the error
Uncaught TypeError: Object # has no method 'exec'
(13:52:13:450 | error, javascript)
at SQLitePlugin.open (www/js/libs/SQLitePlugin.js:112:15)
at SQLitePlugin (www/js/libs/SQLitePlugin.js:54:10)
at (anonymous function) (www/js/libs/SQLitePlugin.js:425:14)
at (anonymous function) (www/js/libs/SQLitePlugin.js:30:20)
at createandpopulatedb (www/js/dborarray.js:30:30)
at onDeviceReady3 (www/dborarray.html:96:33)
at onload (www/dborarray.html:16:155) SQLitePlugin openargs: {"name":"gdataenter code here.db"} (13:52:19:609) at
www/js/libs/SQLitePlugin.js:39
Can somebody help.
try thhis
window.sqlitePlugin.openDatabase({name: "gdata.db"});
instead of this
window.sqlitePlugin.openDatabase('gdata.db');
In my meteor app, I'm doing infinite scrolling so I must have a limit set on my subscriptions in order to achieve this, but I also need to show the total count from that same collection and update it if the count changes. How would I achieve that?
I have a partial solution that achieves this but only returns the paginated counts, as follows:
function getTotalCount(system) {
var user = Meteor.user(),
queryObject = getSystemQueryObject(system);
if (queryObject) {
var query = queryObject.find({$and: [
{user: user.username},
{status: {$nin: status_complete}}
]});
var count = 0;
var handle = query.observeChanges({
added: function (id, user) {
$('#' + system + 'Count').text(++count);
$('#' + system + 'Count').addClass("ma-count-badge");
console.log(system + " count incremented: " + count);
},
removed: function () {
$('#' + system + 'Count').text(--count);
$('#' + system + 'Count').addClass("ma-count-badge");
console.log(system + " count decremented: " + count);
}
});
}
else {
return 0;
}
}
The other way is to push this method up to the server as a server method, but then it is not reactive, as follows:
Meteor.call('getSystemsTotalCount', system, function (err, counted) {
if (err) {
throw err;
}
if (counted > 0) {
$('#' + system + 'Count').text(counted);
$('#' + system + 'Count').addClass("ma-count-badge");
}
Session.get('listLimit');
});
}
you can to get the count with following way
var count= queryObject.find({$and: [
{user: user.username},
{status: {$nin: status_complete}}
]}).count();
after that, you can to save in a Session
Session('countCollection',count);
if the collection changes your Session also it will do
So the trick really is to combine both options I have in the question. The first part adds reactivity to adds/deletes and the second part calls out to the server to go get the total count. Now my code looks like:
query.observeChanges({
added: function(id, user) { updateListCount(system);},
removed: function(id) { updateListCount(system);}
});
And I just wrap the Method.call from the second excerpt above with a function called updateListCount invoked by the above. This addresses the issue.