Mapping data that contains dots in React - json

I am trying to map the data in React that is coming from the API but I am having problems mapping the object that contains dots for example this: name.en_US.
What is the proper way to map this object and keeping the data structure that I have?
I am getting the date in this format from the API:
{
"user": "User",
"employeeId": "0000",
"businessCustomer": "customer",
"endCustomer": {
"name": "",
"address": "",
"place": ""
},
"device": {
"shipmentIds": "23",
"name.en_US": "wasi",
"name.fi_FI": " masi"
},
"task": {
"time": "2019-02-10T16:55:46.188Z",
"duration": "00:00:24",
"sum": "75€"
}
},
And then I am trying to map it using the following code.
const {
user,
employeeId,
businessCustomer,
endCustomer,
device,
task
} = task;
const{
endCustomerName,
address,
place
} = endCustomer;
const {
shipmentIds,
names
} = device;
const{
en_US,
fi_FI
} = names;
const {
time,
duration,
summa
} = task;

const data = {
"user": "User",
"employeeId": "0000",
"businessCustomer": "customer",
"endCustomer": {
"name": "",
"address": "",
"place": ""
},
"device": {
"shipmentIds": "23",
"name.en_US": "wasi",
"name.fi_FI": " masi"
},
"task": {
"time": "2019-02-10T16:55:46.188Z",
"duration": "00:00:24",
"sum": "75€"
}
};
const { device } = data;
const {
shipmentIds,
'name.en_US': name_en_US,
'name.fi_FI': name_fi_FI
} = device;
const nameUS = device['name.en_US'];
console.log(name_en_US, nameUS);
Use [ ] notation like, device['name.en_US'] .

You can destructure your propery as #Vishnu mentioned, or you could also destructure it by providing a valid key name
const {
shipmentIds,
'name.en_US': name_en_US,
'name.fi_FI': name_fi_FI
} = device;
And then you could access your variable with name_en_US.

Related

Get Values form Json, using jpath

{
"data": [
{
"id": "52fb62dc-a446-4fbb-9c7e-e75d8c90f6d9",
"name": "abx",
"address": {
"address1": "New Address 1",
"address2": "New Address 2",
"Pin":"800001"
}
},
{
"id": "52fb62dc-a446-4fbb-9c7e-e75d8c90f6d9",
"name": "xyz",
"address": {
"address1": "New Address 1",
"address2": "New Address 2",
"Pin":"800002"
}
},
{
"id": "52fb62dc-a446-4fbb-9c7e-e75d8c90f6d9",
"name": "ijk",
"address": {
"address1": "New Address 1",
"address2": "New Address 2",
"Pin":"800003"
}
}
]
}
Out put json should be like this
[
{
"name": "abx",
"Pin": "800001"
},
{
"name": "xyz",
"Pin": "800002"
},
{
"name": "ijk",
"Pin": "800003"
}
]
From the input json, I want to extract all values using
jpath
Name Path = "data.name"
Pin Path = "data.address.pin"
I need all values, I will create an output json.
If both json and jpath are dynamic then try using the below code, here i have used the same input json and output json in my code block.
$(document).ready(function () {
var outputArr = [];
//Assume that these jpaths are dynamic.
var name = "data.name", pin = "data.address.Pin";
//Assigned input json object to sampleData variable.
$.each(sampleData.data, function (item, value) {
//Replacing 'data.' with empty('') as we are looping through data array.
var nameValue = extractValue(value, name.replace('data.', ''));
var pinValue = extractValue(value, pin.replace('data.', ''));
outputArr.push({ 'name': nameValue, 'Pin': pinValue });
});
//logging into console for testing purpose.
console.log(outputArr);
--to do with outputArr --
//Recursive function that returns the required value from the json
function extractValue(value, jPathKey) {
if (jPathKey.split(".").length > 1) {
//Here use of replace function is must as we need to get the object with the mentioned jPathKey to loop further.
return extractValue(value[jPathKey.replace('.', '$').split('$')[0]], jPathKey.replace('.', '$').split('$')[1])
}
else {
return value[jPathKey];
}
}
});
Note: Here only thing that need to take care is the case of jpath should match with case of input json

Dwg comparison through design automation

I would like to know if it is possible, and if yes, how can I achieve dwg comparison through the design automation? I there a way to create a comparison activity accepting 2 dwg in input, and post a boolean as output?
Yes you can create an activity accepting two drawings.
Following activity JSON uses an in-built compare and output the result diff drawing.
Sample Activity Json
{
"HostApplication": "",
"RequiredEngineVersion": "23.0",
"Parameters": {
"InputParameters": [
{
"Name": "HostDwg",
"LocalFileName": "$(HostDwg)"
},
{
"Name": "ToCompareWith",
"LocalFileName": "ToCompareWith.dwg"
}
],
"OutputParameters": [
{
"Name": "Result",
"LocalFileName": "output.dwg"
}
]
},
"Instruction": {
"CommandLineParameters": null,
"Script": "COMPAREINPLACE\nON\n-COMPARE\n\nToCompareWith.dwg\n_SAVEAS\n\noutput.dwg\n"
},
"Id": "FPDCompare"
}
Workitem Json
{
"Arguments": {
"InputArguments": [
{
"Resource": "https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens1.dwg",
"Name": "HostDwg"
},
{
"Resource": "https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens2.dwg",
"Name": "ToCompareWith"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST"
}
]
},
"ActivityId": "FPDCompare"
}
If you are using your own custom compare logic, you can output the
results to txt file or json file.
Activity Json
{
"HostApplication": "",
"RequiredEngineVersion": "23.0",
"Parameters": {
"InputParameters": [
{
"Name": "HostDwg",
"LocalFileName": "$(HostDwg)"
},
{
"Name": "ToCompareWith",
"LocalFileName": "ToCompareWith.dwg"
}
],
"OutputParameters": [
{
"Name": "Result",
"LocalFileName": "output.txt"
}
]
},
"Instruction": {
"CommandLineParameters": null,
"Script": "ISDWGSIMILAR\nToCompareWith.dwg\n"
},
"AppPackages":["Compare"],
"Version": 1,
"Id": "Compare"
}
Workitem Json
{
"Arguments": {
"InputArguments": [
{
"Resource":"https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens.dwg",
"Name": "HostDwg"
},
{
"Resource":"https://madhukar-fda.s3.us-west-2.amazonaws.com/Kitchens1.dwg",
"Name": "ToCompareWith"
}
],
"OutputArguments": [
{
"Name": "Result",
"HttpVerb": "POST"
}
]
},
"ActivityId": "Compare"
}
Note: In the script argument - "ISDWGSIMILAR" is a custom command where you will process two drawings, the first one will be current and second one is the drawing to which you are willing compare [ToCompareWith]
Custom NET Command
[CommandMethod("FDACOMMANDS", "ISDWGSIMILAR", CommandFlags.Transparent)]
public static void CompareDrawing()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var promptResult = ed.GetString("Select Drawing To Compare With");
if (promptResult.Status != PromptStatus.OK) return;
var drawingToCompareWith = promptResult.StringResult;
ed = Application.DocumentManager.MdiActiveDocument.Editor;
using (OpenCloseTransaction o = new OpenCloseTransaction())
{
/*
{
Here your logic code to compare two drawings
}
*/
/*output.txt / json is pushed to your cloud storage as provided in workitem json*/
using (var writer = File.CreateText("output.txt"))
{
if (b != null) /*b value is result of your compare*/
{
writer.WriteLine("TRUE Drawings are same");
}
else writer.WriteLine("FALSE Drawings aren't same");
}
}
}

Set next step for the waterfall dialogue in Microsoft BotBuilder NodeJS SDK

I am using Microsoft Bot Framework for my facebook messenger bot. I want to load the dialog data from json files instead of hard coding in the js file. I would like to configure the next step in the dialog, based on result from the "current" step, which is part of the json file configuration, something like this.
{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "goto step 2"
},
{
"result": "option2",
"action": "goto step 5"
}
]
}
]
}
I would like to process all the incoming messages and respond with correct dialog or correct step in the dialog for the user.
I am trying something like this;
handleMessage = function (session) {
var step = session.dialogData["BotBuilder.Data.WaterfallStep"] || 0;
// check response data from previou step and identify the next step.
// set the waterfall step id
session.dialogData["BotBuilder.Data.WaterfallStep"] = 2;
session.send("Hello");
}
var bot = new builder.UniversalBot(connector, function (session) {
handleMessage(session);
})
.set('storage',tableStorage);
With this code, I am always getting step as zero for session.dialogData["BotBuilder.Data.WaterfallStep"] even after setting this to a different number.
Also, as soon as I set the waterfall step number, all other state data that is stored in my table storage for this conversation is gone.
Storage data before setting waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 0
}
},
{
"id": "*:welcome",
"state": {
"BotBuilder.Data.WaterfallStep": 1
}
},
{
"id": "BotBuilder:prompt-text",
"state": {
"options": {
"prompt": {
"type": "message",
"agent": "botbuilder",
"source": "facebook",
"address": {
"id": "mid.$cAAAlr-0LRH9niO21L1hV6hs83GuJ",
"channelId": "facebook",
"user": {
"id": "XXXX",
"name": "XXXX"
},
"conversation": {
"isGroup": false,
"id": "XX"
},
"bot": {
"id": "XXX",
"name": "XXX"
},
"serviceUrl": "https://facebook.botframework.com"
},
"text": "what do you want to next"
//ignored for simplicity
},
"promptAfterAction": true,
"libraryNamespace": "*"
},
"turns": 0,
"lastTurn": 1517594116372,
"isReprompt": false
}
}
],
"lastAccess": 1517594112740,
"version": 0
}
}
After I set the waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 2
}
}
],
"lastAccess": 1517602122416,
"version": 0
}
}
Interestingly the step number is saved to the database (but in session state) but my "session" variable do not have this value anywhere. Also, even after configuring custom state service, the serviceUrl is still https://facebook.botframework.com which I thought is the default state service used if there is no state service set for the bot.
Per your code, as your bot actually contains only one waterfall step: handleMessage(session);, which raised your issue. You can consider to create multiple dialogs from json configration instead of complex waterfall steps.
Here is my quick test, for your information:
const json = `
[{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "dialog2"
},
{
"result": "option2",
"action": "dialog3"
}
]
}
]
},{
"name":"dialog2",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig2."
}]
}
]
},{
"name":"dialog3",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig3."
}]
}
]
}]
`;
const generateSignleStep = (step) => {
return (session, args, next) => {
step.forEach(sentence => {
switch (sentence.type) {
case 'quickReplies':
let choices = sentence.options.map(item => {
return item.value
});
let card = new builder.ThumbnailCard(session)
.text(sentence.value)
.buttons(sentence.options.map(choice => new builder.CardAction.imBack(session, choice.value, choice.text)))
let message = new builder.Message(session).addAttachment(card);
builder.Prompts.choice(session, message, choices);
break;
case 'text':
default:
session.send(sentence.value)
break;
}
})
}
}
const generatenextAction = (actions) => {
return (session, args, next) => {
const response = args.response;
actions.map(action => {
if (action.result == response.entity) {
session.beginDialog(action.action);
}
})
}
}
const generateWaterfallSteps = (steps) => {
let waterfall = [];
steps.forEach(step => {
waterfall.push(generateSignleStep(step.data));
if (step.next) {
waterfall.push(generatenextAction(step.next));
}
});
return waterfall;
}
var bot = new builder.UniversalBot(connector);
const jsonobj = JSON.parse(json);
jsonobj.forEach(dialog => {
bot.dialog(dialog.name, generateWaterfallSteps(dialog.steps))
.triggerAction({
matches: new RegExp(dialog.name, "g")
})
});
The result is:

Three-Way Relationship in Firebase

I've been learning a lot about denormalised data over the past few months, but I wanted to know if the following is possible in a flattened architecture world. I know how to handle two-way relationships in Firebase, but what about a three-way relationship. Let me explain...
I have 5 items in my database, services, providers, serviceAtProvider, reviews and users. I want to be able to add providers to services and vice versa.
I'd also like there to be a specific page for a provider inside a service, and for there to be reviews linked to the provider at that specific service. The page url might look like this (site.com/serviceId/providerId). The rating is unique to that providerId inside of that serviceId – you can't rate serviceIds or providerIds separately.
I'm not sure how to go about creating such a complex relationship. How would I join the serviceId and providerId in that serviceAtProvider item?
This is what I've got so far:
"services": {
"service1": {
"name": "Hernia Repair",
"providers": {
"provider1": true,
"provider2": true
}
}
},
"providers": {
"provider1": { "name": "The Whittington Hospital" },
"provider2": { "name": "Homerton Hospital" }
},
"serviceAtProvider": {
"service1AtProvider1": { "rating": 4 },
"service1AtProvider2": { "rating": 3 }
},
"reviews": {
"service1AtProvider1": {
"review1": {
"body": "A review from user 1",
"user": "user1"
}
},
"service1AtProvider2": {
"review1": {
"body": "A review from user 2",
"user": "user2"
}
}
},
"users": {
"user1": { "name": "Ben Thomas" },
"user2": { "name": "Beatrix Potter" }
}
I don't know how to create that serviceAtProviderjoin, or how would I go about accessing the service1.name, provider1.name, service1AtProvider1.rating, reviews.service1AtProvider1 on one page. Can anyone explain how to do this?
Also, are there any best practices I should follow?
Any help is appreciated. Thanks in advance!
UPDATE
{
"availableServices": {
"service1": { "name": "Hernia Repair" },
"service2": { "name": "Chemotherapy" }
},
"services": {
"provider": {
"name": "The Whittington Hospital",
"service": {
"service1": {
"rating": 4,
"reviewId1": true
},
"service2": {
"rating": 3,
"reviewId2": true
},
}
}
},
"reviews": {
"reviewId1": {
"review1": {
"rating": 4,
"body": "A review from user 1",
"user": "user1"
}
}
},
"users": {
"user1": { "name": "Raphael Essoo-Snowdon" },
"user2": { "name": "Sharlyne Slassi" }
}
}
I would start by making the data structure a bit simpler and more direct. It's hard to determine the correct data structure for your needs without a detailed use case. I'll do my best to make some generic assumptions here. You'll have to adapt as necessary.
{
"service": {
"service1": { "name": "Foo Service" },
...
},
"provider": {
"provider1": { name: "Foo Place" },
...
},
"ratings": {
"service1": { // service id
"provider1": { // provider id
"average_rating": 4
},
...
},
...
},
"reviews": {
"service1": { // service id
"provider1": { // provider id
"user": "user1",
"rating": 4
},
...
},
...
},
"user": {
"user1": { "name": "Foo Bar" },
...
}
}
Now, to look up the providers who offer a given service, and grab their reviews, I would do the following:
var ref = new Firebase(...);
ref.child('ratings/service1').on('child_added', function(reviewSnap) {
console.log(
'Provider ' + reviewSnap.key(),
'Average rating ' + reviewSnap.val().average_rating
);
});
Joining in the names of the services and providers could be done in several ways. Here's a manual technique:
var ref = new Firebase(...);
ref.child('ratings/service1').on('child_added', accumulateReview);
function accumulateReview(reviewSnap) {
var reviewData = reviewSnap.val();
var reviewid = reviewSnap.key();
fetchService(reviewSnap.parent().key(), function(serviceSnap) {
loadRec('provider', reviewSnap.key(), function(providerSnap) {
console.log('Provider: ', providerSnap.key(), providerSnap.val().name);
console.log('Service: ', serviceSnap.key(), serviceSnap.val().name);
console.log('Average rating: ', reviewData.average_rating);
});
});
}
var serviceCache = {};
function fetchService(serviceid, done) {
// demonstrates creating a local cache for things that will be
// looked up frequently
if( !serviceCache.hasOwnProperty(serviceid) ) {
cacheService(serviceid, done);
}
else {
done(serviceCache[serviceid]);
}
}
function cacheService(serviceid, done) {
loadRec('service', function(ss) {
serviceCache[serviceid] = ss;
fetchService(serviceid, done);
});
}
function loadRec(type, key, done) {
ref.child(type).child(key).once('value', done);
}
I could also automate some of this process with Firebase.util's NormalizedCollection:
var ref = new Firebase(...);
var nc = Firebase.util.NormalizedCollection(
[ref.child('reviews/service1'), 'review'],
ref.child('provider'),
ref.child('user')
)
.select('review.rating', {key: 'provider.name', alias: 'providerName'}, {key: 'user.name', alias: 'userName'})
.ref();
nc.on('child_added', function(snap) {
var data = snap.val();
console.log('Provider', data.providerName);
console.log('User', data.userName);
console.log('Rating', data.rating);
});
Note that nothing here is set in stone. This is how I would approach it. There are probably dozens of structures at least as good or better.

evaluating json object returned from controller and attaching it to prepopulate attribute of tokeninput

I am using loopjs tokeninput in a View. In this scenario I need to prePopulate the control with AdminNames for a given Distributor.
Code Follows :
$.getJSON("#Url.Action("SearchCMSAdmins")", function (data) {
var json=eval("("+data+")"); //doesnt work
var json = {
"users": [
eval("("+data+")") //need help in this part
]
}
});
$("#DistributorCMSAdmin").tokenInput("#Url.Action("SearchWithName")", {
theme: "facebook",
preventDuplicates: true,
prePopulate: json.users
});
There is successful return of json values to the below function. I need the json in the below format:
var json = {
"users":
[
{ "id": "1", "name": "USER1" },
{ "id": "2", "name": "USER2" },
{ "id": "3", "name": "USER3" }
]
}