Why won't items post to my SharePoint list? - javascript

I am attempting to move data from a JSON format to a SharePoint list. The database that I am pulling the JSON from has a limit of 500 items per request so I am using EPOCH time to make multiple calls to pull all of the data. I am able to pull all of the data perfectly fine, but when I attempt to place it into the SharePoint list, I start to encounter problems. The first 515 items will be added to the SharePoint list without any issue, but any other items after that will not go into the SharePoint list. The last EPOCH time that will go into the SharePoint list is 1523302307, any item with an EPOCH time that is greater than that will not be placed into the list for some reason.
When the item does not get added to the SharePoint list, theOnQueryFailed() function says,
Request failed. Column '' does not exist. It may have been deleted by another user.
A snippet of my code is below.
function testDatabase() {
var settingObj = {
sinceDateTime: '0',
dynoCode: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
custCode: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
formGUID: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
getJSONURL: 'https://www.xxxxxxxxxx.net/api/api/xxxx'
};
var columnArray = ['Quandrant', 'MapNumber', 'Picture1', 'Picture2', 'PoleOwner', 'PoleClass', 'PoleSize', 'PowerTagNumber', 'TelephoneTagNumber', 'AttachmentHeight', 'Guying', 'StreetLightAttached', 'TransformerPole', 'ExistingFiber', 'ExistingCopper', 'Grounds', 'MR1AtMidspanClearanceViolation', 'MR1ClearanceViolation', 'MR2PoleTransferRequired', 'MR3DownguyOrAnchorDeficiency', 'MR4BrokenLashingWire', 'MR5DamagedOrKinkedCoaxOrFiber', 'MR6DropTransferRequired', 'MR7TemporaryCoaxOrFiberCable', 'MR8DamagedElectronics', 'MR9PlaceOrRepairGroundOrBond', 'MR10DrpSplttrOrInsfntTapPrts', 'MR11PedOrVltOrLockbxDmged', 'PoleReplacement', 'PoleGrade', 'HouseCount', 'BuildingInformation'];
$.getJSON(settingObj.getJSONURL, {
sinceDateTime: settingObj.sinceDateTime,
custCode: settingObj.custCode,
dynoCode: settingObj.dynoCode,
formGUID: settingObj.formGUID
}).done(function (data) {
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle('testlist2');
var itemCreateInfo = new SP.ListItemCreationInformation();
$.each(data, function (i, item) {
var contentArray = data[i].FormFieldsList;
this.oListItem = oList.addItem(itemCreateInfo);
this.oListItem.set_item('Title', data[i].resourceName);
this.oListItem.set_item('SinceDateTime', data[i].FormUpdatedDate);
var self = this;
$.each(contentArray, function (i1, item2) {
self.oListItem.set_item(columnArray[i1], contentArray[i1].FieldValue);
console.log(contentArray[i1].FieldValue);
});
this.oListItem.update();
clientContext.load(this.oListItem);
clientContext.executeQueryAsync(onQuerySucceeded, onQueryFailed);
});
console.log('Rows returned: ' + data.length);
console.log(data);
}).fail(function (jqXHR, textStatus, err) {
console.log('Error on web service call: ' + err + ' Text Status: ' + textStatus + ' Message: ' + jqXHR.responseXML);
});
}
function onQuerySucceeded() {
console.log('Item created!');
}
function onQueryFailed(sender, args) {
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

I figured out the issue! The dataset that I was importing had items with 32 columns which matched my array that I created, but then after the 515th item, the dataset switched to having 33 columns which explains the error I am receiving. Just thought I should post my answer in case anyone has this issue in the future.

Related

Azure Devops widget using azure-devops-extension-api to fetch all Pull requests by project only fetching one result

I am trying to create a azure devops widget to pull all PRs associated with the project . The widget is working but only pulling one PR data and not all. Below is the widget code I am using
VSS.require(["TFS/Dashboards/WidgetHelpers","TFS/VersionControl/GitRestClient"],
function (WidgetHelpers, TFS_Wit_WebApi) {
WidgetHelpers.IncludeWidgetStyles();
VSS.register("PRDuration", function () {
var projectId = VSS.getWebContext().project.id;
var getQueryInfo = function (widgetSettings) {
// Get a WIT client to make REST calls to Azure DevOps Services
return TFS_Wit_WebApi.getClient().getPullRequestsByProject(projectId,"status: All ",null,0,100)
.then(function (prs) {
var $list = $('<ul>');
prs.forEach(function(pr) {
//$list.append($('<li>').text("Project ID: " + projectId));
//$list.append($('<li>').text("Pull Request ID: " + pr.pullRequestId));
$list.append($('<li>').text("Pull Request title: " + pr.title));
$list.append($('<li>').text("Pull Request createdBy: " + pr.createdBy))
$list.append($('<li>').text("Pull Request creationDate: " + pr.creationDate));
$list.append($('<li>').text("Pull Request closedDate: " + pr.closedDate));
;
//$list.append($('<li>').text("Query Name: " + query.name));
//$list.append($('<li>').text("Created By: " + (query.createdBy ? query.createdBy.displayName: "<unknown>") ));
})
// Append the list to the query-info-container
var $container = $('#query-info-container');
$container.empty();
$container.append($list);
// Use the widget helper and return success as Widget Status
return WidgetHelpers.WidgetStatusHelper.Success();
}, function (error) {
// Use the widget helper and return failure as Widget Status
return WidgetHelpers.WidgetStatusHelper.Failure(error.message);
});
}
return {
load: function (widgetSettings) {
// Set your title
var $title = $('h2.title');
$title.text('Hello World');
return getQueryInfo(widgetSettings);
}
}
});
VSS.notifyLoadSucceeded();
});
When I used this widget it seems to be making below API call and fetching just one result :
https://dev.azure.com/orgname/projectId/_apis/git/pullRequests?searchCriteria=status:All&api-version=6.0
If I am changing the api URL as below then I get all the results :
https://dev.azure.com/orgname/projectId/_apis/git/pullRequests?searchCriteria.status=All&api-version=6.0
Is there a way I can fix this in search criteria of function getPullRequestsByProject to get all results?
I had to give search criteria in below format and it worked:
var search_criteria = {"status": "All"}
return TFS_Wit_WebApi.getClient().getPullRequestsByProject(projectId,search_criteria)
This translates the URL to :
https://dev.azure.com/org/projectId/_apis/git/pullRequests?searchCriteria[status]=All&api-version=6.0

How can I return different values from a function depending on code inside an Axios promise? NodeJS - a

I have a block of code that calls an Api and saves results if there are differences or not. I would like to return different values for DATA as layed out on the code. But this is obviously not working since Its returning undefined.
let compare = (term) => {
let DATA;
//declare empty array where we will push every thinkpad computer for sale.
let arrayToStore = [];
//declare page variable, that will be the amount of pages based on the primary results
let pages;
//this is the Initial get request to calculate amount of iterations depending on result quantities.
axios.get('https://api.mercadolibre.com/sites/MLA/search?q='+ term +'&condition=used&category=MLA1652&offset=' + 0)
.then(function (response) {
//begin calculation of pages
let amount = response.data.paging.primary_results;
//since we only care about the primary results, this is fine. Since there are 50 items per page, we divide
//amount by 50, and round it up, since the last page can contain less than 50 items
pages = Math.ceil(amount / 50);
//here we begin the for loop.
for(i = 0; i < pages; i++) {
// So for each page we will do an axios request in order to get results
//Since each page is 50 as offset, then i should be multiplied by 50.
axios.get('https://api.mercadolibre.com/sites/MLA/search?q='+ term +'&condition=used&category=MLA1652&offset=' + i * 50)
.then((response) => {
const cleanUp = response.data.results.map((result) => {
let image = result.thumbnail.replace("I.jpg", "O.jpg");
return importante = {
id: result.id,
title: result.title,
price: result.price,
link: result.permalink,
image: image,
state: result.address.state_name,
city: result.address.city_name
}
});
arrayToStore.push(cleanUp);
console.log(pages, i)
if (i === pages) {
let path = ('./compare/yesterday-' + term +'.json');
if (fs.existsSync(path)) {
console.log("Loop Finished. Reading data from Yesterday")
fs.readFile('./compare/yesterday-' + term +'.json', (err, data) => {
if (err) throw err;
let rawDataFromYesterday = JSON.parse(data);
// test
//first convert both items to check to JSON strings in order to check them.
if(JSON.stringify(rawDataFromYesterday) !== JSON.stringify(arrayToStore)) {
//Then Check difference using id, otherwise it did not work. Using lodash to help.
let difference = _.differenceBy(arrayToStore[0], rawDataFromYesterday[0],'id');
fs.writeFileSync('./compare/New'+ term + '.json', JSON.stringify(difference));
//if they are different save the new file.
//Then send it via mail
console.log("different entries, wrote difference to JSON");
let newMail = mail(difference, term);
fs.writeFileSync('./compare/yesterday-' + term +'.json', JSON.stringify(arrayToStore));
DATA = {
content: difference,
message: "These were the differences, items could be new or deleted.",
info: "an email was sent, details are the following:"
}
return DATA;
} else {
console.log("no new entries, cleaning up JSON");
fs.writeFileSync('./compare/New'+ term + '.json', []);
DATA = {
content: null,
message: "There were no difference from last consultation",
info: "The file" + './compare/New'+ term + '.json' + ' was cleaned'
}
return DATA;
}
});
} else {
console.error("error");
console.log("file did not exist, writing new file");
fs.writeFileSync('./compare/yesterday-' + term +'.json', JSON.stringify(arrayToStore));
DATA = {
content: arrayToStore,
message: "There were no registries of the consultation",
info: "Writing new file to ' " + path + "'"
}
return DATA;
}
}
})
}
}).catch(err => console.log(err));
}
module.exports = compare
So I export this compare function, which I call on my app.js.
What I want is to make this compare function return the DATA object, so I can display the actual messages on the front end,
My hopes would be, putting this compare(term) function inside a route in app.js like so:
app.get("/api/compare/:term", (req, res) => {
let {term} = req.params
let data = compare(term);
res.send(data);
})
But as I said, Its returning undefined. I tried with async await, or returning the whole axios first axios call, but Im always returning undefined.
Thank you

Firebase function execution and subscription to list that is being updated by a firebase function

I think a firebase function updating a list that I have in the firebase database is being captured by a subscription that is subscribed to that list. From what the list output looks like on my phone (in the app)...and from what my console output looks like (the way it repeats) it seems like it is capturing the whole list and displaying it each time one is added. So (I looked this up)...I believe this equation represents what is happening:
(N(N + 1))/2
It is how you get the sum of all of the numbers from 1 to N. Doing the math in my case (N = 30 or so), I get around 465 entries...so you can see it is loading a ton, when I only want it to load the first 10.
To show what is happening with the output here is a pastebin https://pastebin.com/B7yitqvD.
In the output pay attention to the array that is above/before length - 1 load. You can see that it is rapidly returning an array with one more entry every time and adding it to the list. I did an extremely rough count of how many items are in my list too, and I got 440...so that roughly matches the 465 number.
The chain of events starts in a page that isn't the page with the list with this function - which initiates the sorting on the firebase functions side:
let a = this.http.get('https://us-central1-mane-4152c.cloudfunctions.net/sortDistance?text='+resp.coords.latitude+':'+resp.coords.longitude+':'+this.username);
this.subscription6 = a.subscribe(res => {
console.log(res + "response from firesbase functions");
loading.dismiss();
}, err => {
console.log(JSON.stringify(err))
loading.dismiss();
})
Here is the function on the page with the list that I think is capturing the entire sort for some reason. The subscription is being repeated as the firebase function sorts, I believe.
loadDistances() {
//return new Promise((resolve, reject) => {
let cacheKey = "distances"
let arr = [];
let mapped;
console.log("IN LOADDISTANCES #$$$$$$$$$$$$$$$$$$$$$");
console.log("IN geo get position #$$$$$$$5354554354$$$$$$$");
this.distancelist = this.af.list('distances/' + this.username, { query: {
orderByChild: 'distance',
limitToFirst: 10
}});
this.subscription6 = this.distancelist.subscribe(items => {
let x = 0;
console.log(JSON.stringify(items) + " length - 1 load");
items.forEach(item => {
let storageRef = firebase.storage().ref().child('/settings/' + item.username + '/profilepicture.png');
storageRef.getDownloadURL().then(url => {
console.log(url + "in download url !!!!!!!!!!!!!!!!!!!!!!!!");
item.picURL = url;
}).catch((e) => {
console.log("in caught url !!!!!!!$$$$$$$!!");
item.picURL = 'assets/blankprof.png';
});
this.distances.push(item);
if(x == items.length - 1) {
this.startAtKey4 = items[x].distance;
}
x++;
})
//this.subscription6.unsubscribe();
})
}
The subscription in loadDistances function works fine as long as I don't update the list from the other page - another indicator that it might be capturing the whole sort and listing it repeatedly as it sorts.
I have tried as as I could think of to unsubscribe from the list after I update...so then I could just load the list of 10 the next time the page with the list enters, instead of right after the update (over and over again). I know that firebase functions is in beta. Could this be a bug on their side? Here is my firebase functions code:
exports.sortDistance = functions.https.onRequest((req, res) => {
// Grab the text parameter.
var array = req.query.text.split(':');
// Push the new message into the Realtime Database using the Firebase Admin SDK.
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("profiles/stylists");
var promises = [];
// Attach an asynchronous callback to read the data at our posts reference
ref.on("value", function(snapshot) {
//console.log(snapshot.val());
var snap = snapshot.val();
for(const user in snap) {
promises.push(new Promise(function(resolve, reject) {
var snapadd = snap[user].address;
console.log(snapadd + " snap user address (((((((())))))))");
if(snapadd != null || typeof snapadd != undefined) {
googleMapsClient.geocode({
address: snapadd
}).asPromise()
.then(response => {
console.log(response.json.results[0].geometry.location.lat);
console.log(" +++ " + response.json.results[0].geometry.location.lat + ' ' + response.json.results[0].geometry.location.lng + ' ' + array[0] + ' ' + array[1]);
var distanceBetween = distance(response.json.results[0].geometry.location.lat, response.json.results[0].geometry.location.lng, array[0], array[1]);
console.log(distanceBetween + " distance between spots");
var refList = db.ref("distances/"+array[2]);
console.log(snap[user].username + " snap username");
refList.push({
username: snap[user].username,
distance: Math.round(distanceBetween * 100) / 100
})
resolve();
})
.catch(err => { console.log(err); resolve();})
}
else {
resolve();
}
}).catch(err => console.log('error from catch ' + err)));
//console.log(typeof user + 'type of');
}
var p = Promise.all(promises);
console.log(JSON.stringify(p) + " promises logged");
res.status(200).end();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
});
What is weird is, when I check the firebase functions logs, all of this appears to only run once...but I still think the subscription could be capturing the whole sorting process in some weird way while rapidly returning it. To be as clear as possible with what I think is going on - I think each stage of the sort is being captured in an (N(N + 1))/2...starting at 1 and going to roughly 30...and the sum of the sorting ends up being the length of my list (with 1-10 items repeated over and over again).
I updated to angularfire2 5.0 and angular 5.0...which took a little while, but ended up solving the problem:
this.distanceList = this.af.list('/distances/' + this.username,
ref => ref.orderByChild("distance").limitToFirst(50)).valueChanges();
In my HTML I used an async pipe, which solved the sorting problem:
...
<ion-item *ngFor="let z of (distanceList|async)" no-padding>
...

Multiple records are added to the database

I'm puzzling over a weird problem I cannot replicate.
Scenario
I wrote a simple nodejs application that, after some UI interaction append some records to an Access 97 database. I'm using node-adodb to connect with it.
Some relevant piece of code.
var DBDATA = require('node-adodb'), dbConnection = DBDATA.open('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=/path/to/my/file.mdb');
function append(data, callback)
{
var table;
var query;
var array = [];
array.push({name: "Date", value: formatDate(data.date)});
array.push({name: "Time", value: formatTime(data.date)});
array.push({name: "Type", value: Number(data.Type)});
array.push({name: "Value", value: Number(exists(data.value, 0))});
// ...other fields
var fields = array.map(function (e) {
return "[" + e.name + "]";
}).join(",");
var values = array.map(function (e) {
return e.value;
}).join(",");
table = "tblData";
query = 'INSERT INTO ' + table + '(' + fields + ') ' + 'VALUES (' + values + ')';
dbConnection
.execute(query)
.on('done', function (data) {
return callback({id: id, success: true});
})
.on('fail', function (data) {
console.log(data);
return callback({id: id, success: false});
});
}
The issue
The above function is called whenever a new record is ready. Usually it works fine, but it happens about 1 time per week (among hundreds of records) that I find in the database multiple rows identical.
Due to the nature of the information this is impossible - I mean, it's impossible that the actual data is the same.
I guessed for a bug in the caller, that for some reasons sends me the same variable's content. Hence I added a check before append the record.
What I tried to do
function checkDuplicate(table, array, callback)
{
var query = "SELECT * FROM " + table + " WHERE ";
array.forEach(function(element)
{
query += "([" + element.name + "]=" + element.value + ") AND ";
});
query = query.substr(0, query.length - 4);
dbConnection
.query(query)
.on("done", function (data) {
return callback(data.records.length > 0);
})
.on("fail", function (data) {
return callback(false);
});
}
in the append function I call this one and if it returns a value > 0 I don't execute the query, because it would mean there already is the same row.
Testing it with fake data gave good results: no multiple records were added.
Unfortunately, this didn't fixed the issue in the real world. After 20 days I noticed that a row was added three times.
Questions
Do you see any evidence of a major mistake in my approach?
Is there a more reliable way to avoid this problem?
Please note I cannot change the database structure because it's not mine.
UPDATE
This is the new code I'm using:
// Add only if there isn't an identical record
query = 'INSERT INTO ' + table + '(' + fields + ') ';
query += ' SELECT TOP 1 ' + values;
query += ' FROM ' + table;
query += ' WHERE NOT EXISTS ( SELECT 1 FROM ' + table + ' WHERE ';
array.forEach(function(element)
{
query += "([" + element.name + "]=" + element.value + ") AND ";
});
query = query.substr(0, query.length - 4);
query += ' );';
dbConnection
.execute(query)
.on('done', function (data) {
return callback({id: id, success: true});
})
.on('fail', function (data) {
console.log(data);
return callback({id: id, success: false});
});
but it doesn't solved the problem, i.e. sometimes I still found two or more records identical in the database.
I'm afraid it could be the same behavior: the client make multiple requests in a while and they are executed in parallel, so each one doesn't find the record, and all will be add it.
Hance, what is the right approach to avoid this without change the database structure?
Is there a way to force node-adodb to execute only one query at time?

SharePoint 2013 - Get a list of all users in JS in apps

I found the code to show the current logged in user in the example from MS.
How do I display the list of ALL users using JS?
var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();
// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
$(document).ready(function () {
getUserName();
});
//This function prepares, loads, and then executes a SharePoint query to get the current users information
function getUserName() {
context.load(user);
context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}
// This function is executed if the above call is successful
// It replaces the contents of the 'message' element with the user name
function onGetUserNameSuccess() {
$('#message').text('Hello ' + user.get_title());
}
You will need to decide on a timeframe as to consider the user being actually logged in (HTTP is stateless). And you can log the currentuser information for that timeframe (using the code you have) and consider them as your currently logged in user list. You can also use a web analytics / logging tool..something like this.
If you just want the list of all the users in all the groups regardless they are considered logged in or not, than you can use this:
var siteUrl = '/sites/MySiteCollection ';
function retrieveAllUsersAllGroups() {
var clientContext = new SP.ClientContext(siteUrl);
this.collGroup = clientContext.get_web().get_siteGroups();
clientContext.load(collGroup);
clientContext.load(collGroup, 'Include(Users)');
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
var userInfo = '';
var groupEnumerator = collGroup.getEnumerator();
while (groupEnumerator.moveNext()) {
var oGroup = groupEnumerator.get_current();
var collUser = oGroup.get_users();
var userEnumerator = collUser.getEnumerator();
while (userEnumerator.moveNext()) {
var oUser = userEnumerator.get_current();
this.userInfo += '\nGroup ID: ' + oGroup.get_id() +
'\nGroup Title: ' + oGroup.get_title() +
'\nUser: ' + oUser.get_title() +
'\nLogin Name: ' + oUser.get_loginName();
}
}
alert(userInfo);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
Look through here for more examples.

Categories