Maximo Anywhere - Dynamic List Creation using Work Execution App - maximo

I am customizing Anywhere(7.5.2)-WorkExecution. I am trying to create a dynamic list on the Work Log execution but it always creates only one. Kindly help.
CREATE Action
Work Log
File: WorkLogHandler.js
Function: _saveTransaction
Existing Code:
_saveTransaction: function(){
try{
var workOrderSet = CommonHandler._getAdditionalResource(this,"workOrder");
var workOrder = workOrderSet.getCurrentRecord();
if (!workOrder.isNew()) {
ModelService.save(workOrderSet);
}
this.ui.hideCurrentView();
}catch(e){
throw e;
}
},
New Code:
_saveTransaction: function(){
debugger;
try{
var workOrderSet = CommonHandler._getAdditionalResource(this,"workOrder");
var workLogdata = CommonHandler._getAdditionalResource(this,'workOrder.workloglist').getCurrentRecord();
var workOrder = workOrderSet.getCurrentRecord();
debugger;
for(var i=0; i<2; i++){
debugger;
if (!workOrder.isNew()) {
debugger;
workLogdata.set('summary',i+" Round");
}
ModelService.save(workLogdata);
this.ui.hideCurrentView();
}
return;
}catch(e){
throw e;
}
},

If you're trying to create a new worklog entry every time the record is saved, the issue is here..
var workLogdata = CommonHandler._getAdditionalResource(this,'workOrder.workloglist').getCurrentRecord();
You need to create a new record for each new worklog that you're trying to add, not retrieve the current one.
var workLogdata = CommonHandler._getAdditionalResource(this,'workOrder.workloglist').createNewRecord()

Related

Not able to figure out how to wait until forEach loop iterates completely and use that result

I am new to cloud functions (node js with typescript). I am using it to fetch data from Firebase database( as the code below). But Not able to figure out how to wait until forEach loop iterates completely and use that result.
const reference = admin.database().ref('/books')
var path_key:string
var total_count:number = 0
reference .forEach(function (snapshot) {
path_key= snapshot(key).val()
ref_users_advance_bookings.child(path_key)
.once('value').then((snapshot2)=>{
if(condidtion met){
return response.send("failed")
}
else{
total_count++
}
)}
return true
})
// i want to use total_count value here
return response.send("count :"+total_count) // but every time I gets 0, as it get executed before forEach has ended
)}
My guess is that you're trying to wait for a number of items to load from the database. For that you'll want to use Promise.all(), in something like:
var promises = [];
ref.forEach(function (snapshot) {
path_key= snapshot(key).val()
promises.push(ref_users_advance_bookings.child(path_key).once('value'));
});
Promise.all(promises).then(function(snapshots) {
var failed = false;
snapshot.forEach(function(snapshot2) {
if(condition met){
failed = true;
}
else {
total_count++;
}
)}
if (failed) {
return response.status(500).send("ERROR");
}
else {
return response.send("count :"+total_count);
}
});

Mongoose add multiple items to database

I have two problems with this code.
1) Only the last element of beerObjects is saved to the database.
2) There are n duplicates of the last element (n = beerObjects.length) saved to the database.
function addBeersToDatabase(beerObjects) {
for (i = 0; i < beerObjects.length; i++) {
console.log(beerObjects[i].beerId);
var currentBeer = beerObjects[i];
// check if beer is already in database
Beer.findOne({'beerId': currentBeer.beerId}, function(err, beer){
if (err) {
handleError(err);
}
if (beer) {
// beer is already in database
}
else {
// add new beer to database
console.log(currentBeer.beerId);
var newBeer = new Beer();
newBeer.beerId = currentBeer.beerId;
newBeer.name = currentBeer.name;
newBeer.description = currentBeer.description;
newBeer.abv = currentBeer.abv;
newBeer.image = currentBeer.image;
newBeer.save(function(err) {
if (err) {
throw err;
}
});
}
});
}
}
I want to loop through each beer and save its info to the database. I used findOne to prevent duplicates but this is not working. The first console.log() statement prints each beer id but the seconds console.log() statement prints just the last beer id multiple times.
The issue here is that in the findOne callback - your beerId will always be set to the last beer in beerObjects, because the loop finishes before you get to your first callback - welcome to asynchronous javascript.
One remedy for this is to wrap your findOne code in an IFFE (Immediately Invoked Function Expression). This code will complete before moving on to the next beer from beerObject.
Here is some more info on IFFE
Stack Overflow on IFFE
I took a quick pass at the code, I believe this should work, but you may have to make some adjustments with the internal code...
for(var i = 0; i < beerObjects.length; i++) {
console.log(beerObjects[i].beerId);
//var currentBeer = beerObjects[i]; dont need this now
(function (currentBeer) {
Beer.findOne({ beerId: currentBeer},
function(err, beer) {
if(!err && !beer) {
var newBeer = new Beer();
newBeer.beerId = currentBeer.beerId;
newBeer.name = currentBeer.name;
newBeer.description = currentBeer.description;
newBeer.abv = currentBeer.abv;
newBeer.image = currentBeer.image;
newBeer.save(function(err) {
// log your error here...
});
} else if(!err) {
console.log("Beer is in the system");
} else {
console.log("ERROR: " + err);
}
}
);
})(beerObjects[i].beerId);
}

Get returned value from async function using async library

So, i'm using express locals to create custom function. I have this:
Menu.getMenu(function(err, menu) {
app.locals.buildMenuStructure = function(){
var ids = [];
for (var i = 0; i < menu.length; i++) {
ids.push(menu[i]._id);
}
return ids;
};
});
But the problem is that when i add some data to Menu collection the function doesn't know about menu being populated. To see new ids i need to restart the server.
Now i realized that i need to retrieve menus inside buildMenuStructure function to see effect immediately. In that case i need to get the value of getMenu asynchronous function and return it. Something like this:
app.locals.buildMenuStructure = function(){
var ids = [];
Menu.getMenu(function(err, menu) {
for (var i = 0; i < menu.length; i++) {
ids.push(menu[i]._id);
}
});
return ids;
}
I plan to use async library for that but i can't make it work((
Note! This functions are simplified.
Menu.getMenu function is the same as mongoose Menu.find({});
Thanks for your answers.
Looks like you want to synchronously retrieve the value of asynchronous function, but is's impossible (unless you're using fibers).
The best solution for you is to keep your original code, but to move it into express middleware and use res.locals instead of app.locals:
app.use(function(req, res, next) {
Menu.getMenu(function(err, menu) {
res.locals.buildMenuStructure = function(){
var ids = [];
for (var i = 0; i < menu.length; i++) {
ids.push(menu[i]._id);
}
return ids;
};
next(err);
});
})
In this case buildMenuStructure helper will be built anew for every new request.
Here is an example of using both app.locals and res.locals in express with ejs engine.

How to get rid of the asynchoronous code here

I have been trying to retrieve the data using the MongoJS driver for node.js.The Code which I am using is as follows
req.on('end', function(){
var decodedBody = querystring.parse(fullBody);
story=decodedBody.name;
var z=new Array();
console.log(story);
res.writeHead(200,{'Content-Type': 'text/html'});
res.write('<html><body>');
db.frames.find({str_id:story}).toArray(function(err,doc){
console.log(doc);
for(var t=0;t<doc.length;t++)
{
var picid=doc[t].pic_id;
console.log(picid);
db.pictures.find({_id:picid}).toArray(function(err,pic){
res.write('<img src="'+pic[0].name+'"/>');
});
}
})
res.end('</body></html>');
});
The problem here is that because of the asynchronous nature of the code the response gets ends first and then the code inside the block of database gets executed and because of that nothing gets displayed on the browser i.e an image in this case .Thankx in advance.
Don't fight the asynchronous nature of node.js, embrace it!
So you should fire off all your requests, marking each one as completed when the response arrives. When all requests are completed, render your images and body/html closing tags.
I don't usually work with node.js, so I can make some mistakes, but it may look like this:
res.write('<html><body>');
db.frames.find({str_id:story}).toArray(function(err,doc){
console.log(doc);
var completed = {};
for(var t = 0; t < doc.length; t++) {
var picid = doc[t].pic_id;
completed.picid = false;
console.log(picid);
db.pictures.find({_id: picid}).toArray(function(err, pic) {
// mark request as completed
completed.picid = pic;
// check if all requests completed
var all_finished = true;
for(var k in completed) {
if(completed[k] === false) {
all_finished = false;
break;
}
}
// render final markup
if(all_finished) {
for(var k in completed) {
var pic = completed[k];
res.write('<img src="'+pic[0].name+'"/>');
}
res.end('</body></html>);
}
});
}
})
just put the res.end('</body></html>'); inside your db.frames.find function. Check when you reached doc.length - 1 and then send the end command.

chrome extension connection issues

I have written an extension for google chrome and I have a bug I need a help solving.
what I do is using either a text selection or an input of text search for photos on flickr and then create a results tab.
The extension works most of the times. but sometimes it creates a blank tab with no results and when I repeat the same search it then shows results. I figured that it's something to do with the html files messaging maybe something to do with them communicating. I have to say that I always receive the results from flickr so that the request/responce with flickr works ok. Sometimes the error happens when I play with other tabs or do something on other tabs while waiting for results. can you please help me figure out where's the fault?
the background file:
function searchSelection(info,tab){
var updated;
if(info.selectionText==null){
var value = prompt("Search Flickr", "Type in the value to search");
updated=makeNewString(value);
}
else{
updated=makeNewString(info.selectionText);
}
var resultHtml;
var xhReq = new XMLHttpRequest();
xhReq.open(
"GET",
"http://api.flickr.com/services/rest/?method=flickr.photos.search&text="+updated+
"&api_key=a0a60c4e0ed00af8d70800b0987cae70&content_type=7&sort=relevance&per_page=500",
true);
xhReq.onreadystatechange = function () {
if (xhReq.readyState == 4) {
if (xhReq.status == 200) {
chrome.tabs.executeScript(tab.id, {code:"document.body.style.cursor='auto';"});
var photos = xhReq.responseXML.getElementsByTagName("photo");
if(photos.length==0){
alert("No results found for this selection");
chrome.tabs.executeScript(tab.id, {code:"document.body.style.cursor='auto';"});
return;
}
var myJSPhotos=[];
for(var i=0; i<photos.length; i++){
var data={"id":photos[i].getAttribute("id"),"owner":photos[i].getAttribute("owner"),
"secret":photos[i].getAttribute("secret"),"server":photos[i].getAttribute("server"),
"farm":photos[i].getAttribute("farm"),"title":photos[i].getAttribute("title")};
myJSPhotos[i]=data;
}
chrome.tabs.create({"url":"results.html"},function(thistab){
var port= chrome.tabs.connect(thistab.id);
port.postMessage({photos:myJSPhotos});
});
}
};
};
xhReq.send(null);
chrome.tabs.executeScript(tab.id, {code:"document.body.style.cursor='wait';"});
}
var context="selection";
var id = chrome.contextMenus.create({"title": "search Flickr", "contexts":[context,'page'],"onclick":searchSelection});
results html: has only a reference to the js file res.js
res.js :
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
//*****//
var photos=msg.photos;
createPage(photos);
});
});
I have to mention that when the tab is empty if I put alert on the //*****// part it won't
fire.
but when I print out the photos.length at the tab create call back function part it prints out the correct result.
Try to set "run_at":"document_start" option for your res.js in the manifest.
I think callback from chrome.tabs.create is fired right away without waiting for page scripts to be loaded, so you might try something like this instead:
//global vars
var createdTabId = null;
var myJSPhotos = null;
xhReq.onreadystatechange = function () {
//assign myJSPhotos to a global var
chrome.tabs.create({"url":"results.html"},function(thistab){
createdTabId = thistab.id;
});
}
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "complete" && tab.id == createdTabId) {
createdTabId = null;
//now page is loaded and content scripts injected
var port = chrome.tabs.connect(tab.id);
port.postMessage({photos:myJSPhotos});
}
});

Resources