Problems with programmatically selecting node in jsTree on page start-up - jstree

I can't select a tree element on page start-up. There is a JSFiddle with the setup: https://jsfiddle.net/voltel/aszn3h46/
My data is JSON array:
const a_data = [
{
"id": "1296",
"text": "Disposable and Single-Use Medical Supplies",
"children": null
},
{
"id": "1275",
"text": "Implantables",
"children": [
{
"id": "1276",
"text": "Defibrillators, Implantable",
"children": null
},
{
"id": "1338",
"text": "Analysers, Laboratory In-Vitro Diagnostic, Clinical Chemistry, Manual",
"children": null
},
]}
];
// Rest of JavaScript code
const $tree = $("#display");
$tree.jstree({
'plugins' : [ "wholerow", "checkbox" ],
'core': {
data : a_data
},
'checkbox': {
three_state: false
},
});
//
// The problem: I can't select/check node with this id
const c_icd_device_type = "1338";
// show initial value
if (c_icd_device_type) {
console.log(`Request to select node with id ${c_icd_device_type}`);
const o_selected_node = $tree.jstree('get_node', c_icd_device_type);
console.log('Selected node: ', o_selected_node);
// Uncomment ONE of the following:
if (o_selected_node) {
$tree.jstree('select_node', o_selected_node, true);
} else {
$tree.jstree(true).select_node(c_icd_device_type);
}//endif
}//endif
Please, help select a node on start-up, and get rid of some suspicious errors in console (see JSFiddle).
Now, I understand from other questions on jsTree here on StackOverflow, that if wrap my code selecting an element in an event handler, it works. I don't quite understand why it is so complicated, provided there are no asynchronous calls. And if it's unavoidable, why not use Promise?
$tree.on('ready.jstree', function (e, data) {
console.log(`Request to select node with id ${c_icd_device_type}`);
const o_selected_node = data.instance.get_node(c_icd_device_type);
//const o_selected_node = $tree.jstree('get_node', c_icd_device_type);
console.log('Selected node: ', o_selected_node);
// Uncomment ONE of the following:
if (o_selected_node) {
$tree.jstree('select_node', o_selected_node, true);
} else {
$tree.jstree(true).select_node(c_icd_device_type);
}//endif
});

I don't see any errors in console on Chrome:
Your code is fine. It just that the tree isn't ready yet. If you wrap your existing code inside ready.jstree event, it'll work.
$tree.on('ready.jstree', function (e, data) {
// Copy line 38 onward and place your existing code here
});

Related

How to create in mongoose, if it exists, update it in mongoose

I have problem when I want create new model or if not exist, update it.
For example, I have data in a database:
{
"unix": 1668380400,
"type": "soup",
"order": 1,
"value": "Chicken"
},
{
"unix": 1668380400,
"type": "main",
"order": 0,
"value": "Gulash"
},
{
"unix": 1668553200,
"type": "soup",
"order": 0,
"value": "Asian"
}
}
I want to get to the point that when unix and type and order are the same - modify the value. But if the element with the same unix, order and type is not found in the database - add a completely new record to the db.
I thought this was how I would achieve the desired state. But a mistake.
router.post("/add", async (req, res) => {
const data = req.body;
await data.map((el) => {
const { unix, type, order, value } = el;
Menu.findOneAndUpdate(
{ unix, type, order },
{ unix, type, order, value },
{ new: true, upsert: true }
);
});
res.status(201).json({ status: true });
});
req.body:
[
{
"unix": 1668380400,
"type": "main",
"order": 2,
"value": "Sushi"
},
{
"unix": 1668553200,
"type": "soup",
"order": 0,
"value": "Thai"
}
]
Thanks for any help.
I think I found a solution. Everything works as it should, but wouldn't it be better to send the data with JSON.stringify() and then parse this data on the servers using JSON.parse()?
Another thing is the map method. Is it OK like this? Can't cause throttling?
router.post("/add", (req, res) => {
const data = req.body;
data.map(async (el) => {
const { unix, type, order, value } = el;
await Menu.findOneAndUpdate(
{ unix, type, order },
{ value },
{ upsert: true }
);
});
res.status(201).json({ status: true });
});

How to return the a formatted response from a mongo query/projection?

I'm trying to create an API to validate a promocode. I have minimal experience with mongo and the backend in general so I'm a bit confused in what is the best approach to do what I'm trying to accomplish.
I have this PromoCode form in the client. When a user types a promocode I would like for my backend to
verify if the code exists in one of the docs.
if it exists then return that code, the value for that code and the couponId
if the code doesn't exist then return an error.
My db is structured like this. The user will type one of those codes inside the codes: []
{
"_id": {
"$oid": "603f7a3b52e0233dd23bef79"
},
"couponId": "rate50",
"value": 50,
"codes": ["K3D01XJ50", "2PACYFN50", "COKRHEQ50"]
},
{
"_id": {
"$oid": "603f799d52e0233dd23bef78"
},
"couponId": "rate100",
"value": 100,
"codes": ["rdJ2ZMF100", "GKAAYLP100", "B9QZILN100"]
}
My route is structure like this:
router.post('/promoCode', (req, res, next) => {
const { promoCode } = req.body;
console.log('this is the req.body.promoCode on /promoCode', promoCode)
if (!promoCode) {
throw new Error('A promoCode needs to be passed')
}
promoCodesModel
.validatePromoCode(req.body.promoCode)
.then((response) => {
console.log('response inside /promoCode', response)
res.status(200).json({ data: response })
})
.catch((error) => {
res.status(400).json({ result: 'nok', error: error })
})
})
The validatePromoCode function is the following:
const validatePromoCode = async (code) => {
try {
let promoCode = await PromoCodesModel.find(
{"codes": code},
{_id: 0, codes: { $elemMatch: { $eq: code }} })
console.log('This is the promocode', promoCode)
return promoCode
} catch (err) {
throw new Error (err.stack)
}
}
All this seems to sort of work since I get the following response when the code is typed correctly
{
"data": [
{
"codes": [
"COKRHEQ50"
]
}
]
}
when typed incorrectly I get
{
"data": []
}
What I would like to get back is. (How can I accomplish this ?). Thanks
// when typed correctly
{
"data": { value: 50, couponId: "rate50", code: "COKRHEQ50" }
}
// when typed incorrectly
{
"error": "this is not valid code"
}
TL;DR: I would like to return a formatted query with specific values from a mongo query or an error object if that value does not exist on the document object.
Ok just figured it out
To be able to get the this responsed (what I wanted):
{
"data": [
{
"codes": [
"K3D01XJ50"
],
"couponId": "rate50",
"value": 50
}
]
}
I ended up having to do this on validatePromoCode
onst validatePromoCode = async (code) => {
try {
let promoCode = await PromoCodesModel.find(
{ codes: code },
{ _id: 0, codes: { $elemMatch: { $eq: code } }, couponId: 1, value: 1 },
)
return promoCode
} catch (err) {
throw new Error(err.stack)
}
}
But is there a better way on doing this ? Thanks

Rearrrange populated json result in mongoose

A simple json response for Post.find().populate("name") will return json result as follow. Note: The focus of the question is to rearrange the "name":"Alex" in json to the final structure as shown. Ignore the part that need hiding _id and __v. Thanks.
[
{
"_id": "54cd6669d3e0fb1b302e54e6",
"title": "Hello World",
"postedBy": {
"_id": "54cd6669d3e0fb1b302e54e4",
"name": "Alex",
"__v": 0
},
"__v": 0
},
...
]
How could i rearrange and display the entire json as follow?
[
{
"_id": "54cd6669d3e0fb1b302e54e6",
"title": "Hello World",
"name": "Alex"
},
...
]
You can use the lean() method to return a pure JSON object (not a mongoose document) that you can then manipulate using lodash helper methods such as map(), like in the following example:
Post.find()
.populate("name")
.lean().exec(function (err, result) {
if(result){
var posts = _.map(result, function(p) {
p.name = p.postedBy.name;
p.postedBy = undefined;
return p;
});
console.log(posts);
}
});
You can disable the "__v" attribute in your Schema definitions by setting the versionKey option to false. For example:
var postSchema = new Schema({ ... attributes ... }, { versionKey: false });
As follow-up to your question on rearranging the order of the properties in the JSON, JS does not define the order of the properties of an object. However, you
can use both the JSON.parse() and JSON.stringify() methods to change the order, for example
var json = {
"name": "Alex",
"title": "Hello World",
"_id": "54cd6669d3e0fb1b302e54e6"
};
console.log(json);
//change order to _id, title, name
var changed = JSON.parse(JSON.stringify(json, ["_id","title","name"] , 4));
console.log(k);
Check the demo below.
var json = {
"name": "Alex",
"title": "Hello World",
"_id": "54cd6669d3e0fb1b302e54e6"
};
//change order to _id, title, name
var changed = JSON.parse(JSON.stringify(json, ["_id","title","name"] , 4));
pre.innerHTML = "original: " + JSON.stringify(json, null, 4) + "</br>Ordered: " + JSON.stringify(changed, null, 4);
<pre id="pre"></pre>

jsTree: with lazy loading the plugin "dnd" is not working

I'm using jsTree (latest version) in my web app. I have a lot of nodes to display in the tree, so I am using lazy loading otherwise I would run into a time out.
When the tree is loaded, the user can pick values from a second tree and move them into the lazy loaded tree (jsTree plugin "dnd"). Both tree have the jsTree plugin "dnd" installed. But I can not drop a element into the lazy loaded tree, when I try to do so the node to be dropped is having an icon with a red cross (indication: not allowed here).
This is the code for the lazy loaded tree:
$('#target_tree').jstree({
'core' : {
'data' : {
"url" : "get_current_hierachy",
"data" : function (node) {
return {'p_parent_id': node.id};
},
"dataType": "json",
"check_callback": true
}
},
"plugins" : ["dnd"]
});
When I load some data in the first tree without the lazy loading, the drag'n'drop is working as expected.
When I load data in the first tree with lazy loading, the drag'n'drop is not working any more.
Any help would be greatly appreciated.
Try this ...
$(document).ready(function () {
$('#target_tree').jstree({
'core': {
'data': {
"url": function (node) {
var url;
if (node.id == '#') {
url = "getRootNode";
} else {
var id = $(node).data("id");
url = "getChildNode?nodeid=" + id;
}
return url;
},
"data": function (node) {
return { "id": node.id };
},
"type": "GET",
"dataType": "json",
"contentType": "application/json charset=utf-8",
},
'check_callback': true,
},
"plugins": ["dnd"]
});
});
I think you need to prepare url

How to get all versions of an object in Google cloud storage bucket?

In a web page hosted in Google cloud storage, I will like to show revision history, which require listing all versions of the object.
Sending GET request to the bucket with ?versions parameter return list versions all objects. Is there any way to list all versions of a single object, as in gsutil ls -la, in javascript?
There is not. The closest you can do is to use versions=true and prefix=YOUR_OBJECT_NAME.
GCS will respond with a listing of objects beginning with all of the versions of your object and continuing on to any other objects that begin with YOUR_OBJECT_NAME. You'll have to check those items to see when the listing runs out of versions of your object and moves on to other objects.
If it so happens that only one object begins with YOUR_OBJECT_NAME (for example, your object is "foo.txt" and there are no files named, say, "foo.txt.backup", you will get exactly the files you want. You probably don't want to rely on this as a general practice, though.
Brondon's answer work with XML, but not with gapi client.
/**
* Get versions meta data of the object.
* #return {goog.async.Deferred} return history of the object.
*/
mbi.data.Object.prototype.history = function() {
var df = new goog.async.Deferred();
var use_gapi = true;
var name = this.getName();
if (use_gapi) {
// GAPI does not return result for versions request.
var params = {
'bucket': this.getBucketName(),
'versions': true,
'prefix': name
};
// console.log(params);
var req = gapi.client.rpcRequest('storage.buckets.get',
mbi.app.base.GAPI_STORAGE_VERSION, params);
req.execute(function(json, row) {
if (json) {
df.callback(json);
} else {
df.errback();
throw new Error(row);
}
});
} else {
var xm = mbi.data.Object.getXhr();
var uri = new goog.Uri(this.getUrl());
uri.setParameterValue('versions', 'true');
uri.setParameterValue('max-keys', '25');
uri.setParameterValue('prefix', name);
var url = uri.setPath('').setFragment('').toString();
xm.send(url, url, 'GET', null, {}, 1, function(e) {
var xhr = /** #type {goog.net.XhrIo} */ (e.target);
if (xhr.isSuccess()) {
var xml = xhr.getResponseXml();
// console.log(xml);
var json = mbi.utils.xml.xml2json(xml);
var items = json['ListBucketResult']['Version'];
var versions = goog.isArray(items) ? items : items ? [items] : [];
versions = versions.filter(function(x) {
return x['Key'] == name;
});
df.callback(versions);
} else {
df.errback(xhr.getStatus() + ' ' + xhr.getResponseText());
}
});
}
return df;
};
GAPI return as follow without version meta:
[
{
"id": "gapiRpc",
"result": {
"kind": "storage#bucket",
"id": "mbiwiki-test",
"name": "mbiwiki-test",
"timeCreated": "2013-08-20T01:18:46.957Z",
"metageneration": "9",
"owner": {
"entity": "group-00b4903a97262a358b97b95b39df60893ece79605b60280ad389c889abf70645",
"entityId": "00b4903a97262a358b97b95b39df60893ece79605b60280ad389c889abf70645"
},
"location": "US",
"website": {
"mainPageSuffix": "index.html",
"notFoundPage": "error404.html"
},
"versioning": {
"enabled": true
},
"cors": [
{
"origin": [
"http://static.mechanobio.info",
"http://mbinfo-backend.appspot.com",
"https://mbinfo-backend.appspot.com",
"http://localhost",
"chrome-extension://pbcpfkkhmlbicomenogobbagaaenlnpd",
"chrome-extension://mhigmmbegkpdlhjaphlffclbgkgelnbe",
"chrome-extension://jhmklemcneaienackijjhdikoicmoepp"
],
"method": [
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"PATCH"
],
"responseHeader": [
"content-type",
"Authorization",
"Cache-Control",
"x-goog-meta-reviewer"
]
}
],
"storageClass": "STANDARD",
"etag": "CAk="
}
}
]