How To Sort Firebase Joined Query - node.js

I'm New To firebase, i have a query
const posts = database.child('posts');
const user = database.child('user');
posts.orderByChild("id").on('child_added', snap => {
let user_id = snap.val().user_id;
let userRef = database.child('user/' + snap.val().user_id)
userRef.on('value', userSnap => {
console.log(userSnap.val().name)
let content = snap.val().content;
let date_posted = snap.val().date_posted;
let id = snap.val().id;
let title = snap.val().title;
let user_id = snap.val().user_id;
let user_Name = userSnap.val().name;
a.push({
"id": id,
"title": title,
"date_posted": date_posted,
"content": content,
"user_Name": user_Name,
"user_id": user_id
})
});
});
before entering UserRef Query, The posts are well sorted With The id,
however after the 2nd query, it's no longer sorted, How Can i make them sorted even after the 2nd query
this is the db structure
!:
i want the output to be like this
{
id: 1,
title: 'My First Post',
date_posted: '2018-05-02 19:40:02',
content: 'This is my firstpost!',
user_Name: 'Abdelrahman',
user_id: '8721da2c-0028-430f-a995-0d03c8abb393'
},
{
id: 2,
title: 'My SecondPost',
date_posted: '2018-05-02 19:41:02',
content: 'This is my Second post!',
user_Name: 'Abdelrahman',
user_id: '8721da2c-0028-430f-a995-0d03c8abb393'
},
{
id: 3,
title: 'test Title',
date_posted: '2021-01-06 08:48:01',
content: 'test Content',
user_Name: 'Abdelrahman',
user_id: '8721da2c-0028-430f-a995-0d03c8abb393'
},
{
id: 4,
title: 'test Title2',
date_posted: '2021-01-06 08:49:42',
content: 'test Content2',
user_Name: 'Abdelrahman',
user_id: '8721da2c-0028-430f-a995-0d03c8abb393'
},
{
id: 5,
title: 'test 3',
date_posted: '2021-01-06 08:54:14',
content: 'COntent 3',
user_Name: 'Abdelrahman',
user_id: '8721da2c-0028-430f-a995-0d03c8abb393'
}
but the output i see is not sorted at all

Usually you store the token as state in vuex. In your method you commit a mutation to set the token state, something like:
this.$store.commit('SET_TOKEN', res.data)
In the store you will have
state: {
token: '',
},
mutations: {
SET_TOKEN(state, payload) {
state.token = payload.token
}
This is just an example to be adjusted depending on response you get.
If you need to persist the state you should use also vuex persisted state

Related

Timeout issue with jestjs

I was using jest to write a test for a function and I keep getting hit with an exceeded timeout issue. I tried to solve this by adding a bigger number to the second parameter in my test function and also by changing my jest config settings in my package.json file but both did not work. Any help would be appreciated.
Test File
const favoriteBlog = require('../utils/list_helper').favoriteBlog
describe(("fav blog"), () => {
const listWithOneBlog = [
{
_id: "5a422a851b54a676234d17f7",
title: "React patterns",
author: "Michael Chan",
url: "https://reactpatterns.com/",
likes: 7,
__v: 0
},
{
_id: "5a422aa71b54a676234d17f8",
title: "Go To Statement Considered Harmful",
author: "Edsger W. Dijkstra",
url: "http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html",
likes: 5,
__v: 0
},
{
_id: "5a422b3a1b54a676234d17f9",
title: "Canonical string reduction",
author: "Edsger W. Dijkstra",
url: "http://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD808.html",
likes: 12,
__v: 0
},
{
_id: "5a422b891b54a676234d17fa",
title: "First class tests",
author: "Robert C. Martin",
url: "http://blog.cleancoder.com/uncle-bob/2017/05/05/TestDefinitions.htmll",
likes: 10,
__v: 0
},
{
_id: "5a422ba71b54a676234d17fb",
title: "TDD harms architecture",
author: "Robert C. Martin",
url: "http://blog.cleancoder.com/uncle-bob/2017/03/03/TDD-Harms-Architecture.html",
likes: 0,
__v: 0
},
{
_id: "5a422bc61b54a676234d17fc",
title: "Type wars",
author: "Robert C. Martin",
url: "http://blog.cleancoder.com/uncle-bob/2016/05/01/TypeWars.html",
likes: 2,
__v: 0
}
]
test("find the blog with the most likes", (blog) => {
const expected = {
title: "Canonical string reduction",
author: "Edsger W. Dijkstra",
likes: 12
}
const result = favoriteBlog(listWithOneBlog)
expect(result).toEqual(expected)
})
})
Function File
const favoriteBlog = (blog) => {
console.log("before is",blog.map(a => a.likes) )
const preArray = blog.map(a => a.likes)
console.log("Math max thing is", Math.max(...preArray))
const objArr = Math.max(...preArray)
console.log("objArr is",objArr)
const favBlog = blog.filter((x) => x.likes == objArr);
const favBlogObj = favBlog[0]
delete favBlogObj._id;
delete favBlogObj.__v;
delete favBlogObj.url;
console.log("Fav blog is now",favBlog)
return favBlogObj
}
module.exports = {
favoriteBlog
}
The test is failing because you have a blog parameter on the test callback, which Jest interprets to be a callback function which you must call to end the test. The param is not used by the test, so I think this is a mistake and should be removed. If you intend to use the callback, then just add blog() as the last statement in the test (perhaps renaming it to done which is the convention).
Completion callbacks are used for some API styles, but in most cases you don't need this parameter and can just end the test, or return a Promise if you are expecting something to end later.
test("find the blog with the most likes", (blog) => {
// ^^^^ HERE
const expected = {
title: "Canonical string reduction",
author: "Edsger W. Dijkstra",
likes: 12
}
const result = favoriteBlog(listWithOneBlog)
expect(result).toEqual(expected)
})

Unable to Intercept Bot Response in Azure Bot Framework

I want to intercept all the messages exchanged between user and bot. PFB code that I have used to intercept. I am using Bot Diaolog framework for webchat. Here the issue is I am not able to extract values from activities object which contains messages sent from bot to user.
adapter.use(async (turnContext, next) => {
// pre-processing of the current incoming activity
console.log("adapture use::turnContext::" + turnContext.activity.text);
// hook up a handler to process any outgoing activities sent during this turn
turnContext.onSendActivities(async (sendContext, activities, nextSend) => {
// pre-processing of outgoing activities
await nextSend();
console.log("adapture use::activities::POST##::" + flat.stringify(activities));
// post-processing outgoing activities
});
await next();
// post-processing of the current incoming activity
console.log(`Processing activity ${turnContext.activity.id} finishing. `);
});
To access the bot's responses, you can update the bot.js file (i.e. the file with the activity handlers defined) to something like the below.
In short, the onSendActivities() method keeps an array of the activities that have been passed in. You can cycle thru the activities pushing them into an array and then acting on a particular one. Or, react as each arrives. Further below are examples of each output.
const { ActivityHandler, MessageFactory } = require('botbuilder');
class EchoBot extends ActivityHandler {
constructor() {
super();
[...]
const transcript = [];
this.onTurn(async (context, next1) => {
let responses = {};
logActivity(transcript, cloneActivity(context.activity));
context.onSendActivities(async (ctx, activities, next2) => {
responses = await next2();
activities.forEach((a) => logActivity(transcript, cloneActivity(a)));
console.log('TRANSCRIPT ', activities);
return responses;
});
await next1();
});
}
}
const logActivity = (transcript, activity) => {
if (!activity.timestamp) {
activity.timestamp = new Date();
}
transcript.push(activity);
};
const cloneActivity = (activity) => {
return Object.assign({}, activity);
};
module.exports.EchoBot = EchoBot;
Logging the transcript array: Shows the list of activities.
[
{
type: 'conversationUpdate',
id: '1hEUP37Da8S',
timestamp: 2021-09-07T23:01:04.910Z,
serviceUrl: 'https://directline.botframework.com/',
channelId: 'directline',
from: { id: 'dl_16310556645490.nc93iu9jr1' },
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
recipient: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
membersAdded: [ [Object], [Object] ],
rawTimestamp: '2021-09-07T23:01:04.9109865Z',
callerId: 'urn:botframework:azure'
},
{
type: 'message',
text: 'Hello and welcome!',
inputHint: 'acceptingInput',
speak: 'Hello and welcome!',
channelId: 'directline',
locale: undefined,
serviceUrl: 'https://directline.botframework.com/',
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
from: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
recipient: { id: 'dl_16310556645490.nc93iu9jr1' },
timestamp: 2021-09-07T23:01:06.547Z
},
{
type: 'message',
id: '5JgOxxxxxxxxxxxxv6sw-g|0000001',
timestamp: 2021-09-07T23:01:08.704Z,
localTimestamp: 2021-09-07T23:01:08.527Z,
localTimezone: 'America/Los_Angeles',
serviceUrl: 'https://directline.botframework.com/',
channelId: 'directline',
from: { id: 'dl_16310556645490.nc93iu9jr1', name: '' },
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
recipient: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
textFormat: 'plain',
locale: 'en-US',
text: 'Hi',
entities: [ [Object] ],
channelData: {
clientActivityID: '1631055668527tzwhm47a4qd',
clientTimestamp: '2021-09-07T23:01:08.527Z'
},
rawTimestamp: '2021-09-07T23:01:08.704318Z',
rawLocalTimestamp: '2021-09-07T16:01:08.527-07:00',
callerId: 'urn:botframework:azure'
},
{
type: 'message',
text: 'Echo: Hi',
inputHint: 'acceptingInput',
speak: 'Echo: Hi',
channelId: 'directline',
locale: 'en-US',
serviceUrl: 'https://directline.botframework.com/',
conversation: { id: '5JgOxxxxxxxxxxxxv6sw-g' },
from: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
recipient: { id: 'dl_16310556645490.nc93iu9jr1', name: '' },
replyToId: '5JgOxxxxxxxxxxxxv6sw-g|0000001',
timestamp: 2021-09-07T23:01:09.147Z
}
]
Logging activities only: Shows the last item to have passed thru from either the bot or user.
[
{
type: 'message',
text: 'Echo: Hi',
inputHint: 'acceptingInput',
speak: 'Echo: Hi',
channelId: 'directline',
locale: 'en-US',
serviceUrl: 'https://directline.botframework.com/',
conversation: { id: 'AURKxxxxxxxxxJHpO-f' },
from: { id: 'somebot#QaeuoeEamLg', name: 'Some Bot' },
recipient: { id: 'dl_16310605730140.3nrm4evq6um', name: '' },
replyToId: 'AURKxxxxxxxxxJHpO-f|0000001'
}
]
Thank you Rajeesh Menoth. Posting your suggestions as an answer to help other community members.
For updating existing message we can pass NewActivityObject with the existing activity ID to the UpdateActivity method of the TurnContext Object
Below is the sample to pass new object ID
const newActivity = MessageFactory.text('The new text for the activity');
newActivity.id = activityId;
await turnContext.updateActivity(newActivity);
To update the existing card on button selection, you can use ReplyToId of incoming activity.
const message = MessageFactory.attachment(card);
message.id = context.activity.replyToId;
await context.updateActivity(message);
For Further information check Update Messages.

implement a search functionality that query MongoDB database and return all the objects which contain a user given value in node js and express

I want to implement a search functionality that would query my MongoDB database and return all the objects which contain (full/partially) the name I am searching for.
Example:
My object collection is products, and I want to see every product which contains the name I search, from the product names.
My 'Products' collection looks like this...
[ { _id: 5f79,
productName: 'Test-image12345',
price: 60,
details: 'Test product' },
{ _id: 5f7d,
productName: 'Test-image1234',
price: 60,
details: 'Test product'},
{ _id: 5fv4,
productName: 'Test',
price: 60,
details: 'Test product'},
]
Now I need to find all the products with "Test-image1234"
// search a product by name
productRoute.get('/getproduct/:name', async (req,res) => {
try {
const findname = req.params.name;
const objs = await Product.find({productName:{ $regex:'.*'+findname+'.*'} });
res.json(objs);
} catch (error) {
res.json({message: error});
}
})
Now I get the answer as follows...
[ { _id: 5f79,
productName: 'Test-image12345',
price: 60,
details: 'Test product' },
{ _id: 5f7d,
productName: 'Test-image1234',
price: 60,
details: 'Test product'}
]

Telegraf: "replyWithInvoice" isn't available for "callback_query::"

I have a callback_query when users hit on a purchase button. The callback_query is to send an invoice to the user, but it is throwing the above error.
bot.on('callback_query', (ctx) => {
let data = ctx.callbackQuery.data
if (data.includes('purchase') == true) {
return handlePurchase(ctx)
}
})
function handlePurchase(ctx) {
let data = ctx.callbackQuery.data
let itemId = data.split(':')[1]
let invoice = {
chat_id: ctx.callbackQuery.from.id,
title: "Title",
description: "Description",
payload: itemId.toString(),
provider_token: stripeToken,
start_parameter: itemId.toString(),
currency: "USD",
need_phone_number: true,
need_shipping_address: true,
photo_url: the_image_url,
prices: [{
label: "Item",
amount: 1000
}]
}
return ctx.replyWithInvoice(invoice)
}
I also attempted to use ctx.telegram.sendInvoice(invoice) instead but the bot did not send an invoice to the user, ie the bot did not respond at all.

Id of object mus be removed based on matching req.params.id

router.delete('/shopping-cart/:id', (req, res) => {
let cart = new Cart(req.session.cart);
console.log(req.params.id);
console.log(cart.generateArray());
});
console.log will output the following result (req.params.id):
5c863cc8ee0819f989acf9c3
console.log will output the following result (cart.generateArray()):
[ { item:
{ _id: '5c863cc8ee0819f989acf9c3',
imagePath: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
title: 'Gothic Video',
description: 'Absolutely stunning',
price: 10,
__v: 0 },
image: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
qty: 1,
price: 10,
id: '5c863cc8ee0819f989acf9c3' } ]
So how do I loop through all the items and check if id matches the req.params.id. If that is the case, it should remove that object and then return an updated array on the client side.
let cards = [{
item: {
_id: '5c863cc8ee0819f989acf9c3',
imagePath: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
title: 'Gothic Video',
description: 'Absolutely stunning',
price: 10,
__v: 0,
},
image: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
qty: 1,
price: 10,
id: '5c863cc8ee0819f989acf9c3',
}]
cards.forEach(element => {
delete element.id
})
console.info(cards)
I assume that is coming from cart.generateArray()?
If so, you probably should do that inside the function in question, but if you can't, then just map the results to a new array:
let result = cart.generateArray().map(item => {
const {id, ...entry} = item;
// if you want to also remove _id from the inner item, you can do the same
return entry;
});
console.log(result); // will have entries w/o id in them.
If you're looking to remove the nested item object as well, it's the smae approach, though I'll change some words to improve readability.
let result = cart.generateArray().map(cartItem => {
const {id, item, ...entry} = cartItem;
// this will remove both the id and the item keys
return entry;
});
console.log(result); // will have entries w/o id in them.

Resources