Action button push-notification not working | Node | sw-push - node.js

I've created a web app using MEAN stack and integrated push message notification for certain events. But how do I add link/s in the notification so the user can click and gets redirected to site on browser
here's a specimen I send
const notificationPayload = JSON.stringify({
notification: {
title: "Hello",
body: "World,
icon: <icon link>,
vibrate: [100, 50],
data: {
dateOfArrival: Date.now(),
primaryKey: 1
},
actions: [{
action: "explore",
title: "Checkout",
icon: <icon link>,
click_action: "https://www.google.com", // not working
url: "https://www.google.com" // not working
}]
}
});
Resultant is good, and checkout button is clickable... but no reaction

Okay, firstly, NotificationAction object is only allowed to have 3 keys:
action
title
icon
So Naturally, click_action & url will just be ignored.
Coming to your question on how to handle actions, you need to write handlers for each action in the array based on the NotificationAction.action key in your service worker. A detailed guide can de found here.
example:
self.registration.showNotification("New mail from Alice", {
actions: [
{
action: 'archive',
title: 'Archive'
}
]
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
if (event.action === 'archive') {
// Archive action was clicked
archiveEmail();
} else {
// Main body of notification was clicked
clients.openWindow('/inbox');
}
}, false);
References:
NotificationAction
NotificationEvent.action
Notification API
Displaying a notification - Web Fundamentals
Notification behaviour

I'll setup the precise answer, that resolved my case with ngsw-worker:
this was the notification that I was sending, with it, you can send data in the data attribute:
notification: {
title: "hello world,
body: "you have a notification",
icon: <user dp url>,
vibrate: [100, 50],
data: {
dateOfArrival: Date.now(),
primaryKey: 1,
url: <user's profile URL> // data to be used
},
actions: [{
action: "explore",
title: "Checkout",
icon: '... some address ... jolly-roger.png',
},
{
action: 'close',
title: 'Close'
}
]
}
Now, open ngsw-worker.js. It's usually in root folder of dist (for production ready rip), or in node_modules\#angular\service-worker\ngsw-worker.js
here, goto line that handles clicks on notification (:1932: in my case)
this.scope.addEventListener('notificationclick', (event) =>
and you can add your code here regarding the ULR to open. example:
this.scope.addEventListener('notificationclick', (event) => {
try {
clients.openWindow("http://localhost:3000/#/"+event.data.url);
} catch (e) {
clients.openWindow("http://localhost:3000/#/");
}
this.onClick(event)
});
alternatively, if you are handling it within angular itself, you can use redefine the function after injecting swPush in constructor:
this._swPush.notificationClicks.subscribe( event => {
console.log("event = ", event);
});
Rest related articles are present in Salvio's answer below.

Related

Firebase Cloud Messaging notification model

I've implemented the Firebase Cloud Messaging using the firebase_messaging plugin in my flutter app, but there is something I don't understand.
I have this payload in the function to send push notifications on message created:
var payload = {
notification: {
title: 'Nuevo mensaje!',
body: `${sender} te ha dejado mensaje ${fecha}`,
icon: 'https://*************.es/wp-content/uploads/2019/11/**************.png',
click_action: 'FLUTTER_NOTIFICATION_CLICK'
},
};
Everything worked fine till I tried to get the title and the body this way:
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
showDialog(
context: context,
builder: (context) => AlertDialog(
content: ListTile(
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']),
),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
They were null, so I looked on the message and saw that I receive it like this:
{gcm.message_id: dsadsadasd, google.c.sender.id: dasdsaddcwfewf3,
google.c.a.e: 1, aps: {alert: {title:Nuevo mensaje!, body: Ronaldo
te ha dejado mensaje: 7 3 2020 15:00}, category:
FLUTTER_NOTIFICATION_CLICK}}
So changing the way I decode the message like:
content: ListTile(
title: Text(message['aps']['alert']['title']),
subtitle: Text(message['aps']['alert']['body']),
),
everything works fine, but I wonder why I send "notification: {title:}" but receive aps: {alert: {title:}}. The tutorial I followed seems to receive it normally with the "notification" key. What's going on here? What am I missing? The code works, but I feel like I didn't implemented it the right way.
EDIT: I just tested it on Android and there it decodes the way it was supposed to do:
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']
So now I handle it like Platform.isAndroid ? message : message ;
But I want to know whats going on.
Not sure if it is the reason for your issue but in my cloud functions (should be the same in the app) the payload structure I use has the click_action k:v pair in the data section:
const payload = {
notification: {
title_loc_key: "notification_title_string",
body_loc_key: "notification_message_favoriting_string",
badge: "1",
sound: "default",
},
data: {
click_action: "FLUTTER_NOTIFICATION_CLICK",
rcpntId: recipientId,
sndrId: senderId,
}
};
I think that you need to be putting the data that you want to process with your alert dialogue in the data block. The notification block is about what appears in the device status bar. You will also need the data block for onResume and onLaunch responses to notifications.

API error occurred: invalid_arguments when opening a modal in slack

I am trying to open a modal in my slack app
I am trying to follow the official github page on the modal section but I ma getting an error
(node:20175) UnhandledPromiseRejectionWarning: Error: An API error occurred: invalid_arguments
at Object.platformErrorFromResult (/node_modules/#slack/web-api/src/errors.ts:94:5)
at WebClient.apiCall (/node_modules/#slack/web-api/src/WebClient.ts:159:13)
at process.internalTickCallback (internal/process/next_tick.js:77:7)
I can successfully receive and start processing interactive actions sent by slack (on my slack app I have registered a Interactive Components > action with appropriate callback id)
I then try to open a modal while processing this interactive action and it crashes
# In my app I build the message adapter
const slackInteractions = createMessageAdapter(process.env.SLACK_SIGNING_SECRET)
slackInteractions.action({ callbackId: CALLBACK_IDS.MY_CALLBACK_ID }, myHandler)
# which is then mounted as an express middleware, no problem so far
# the handler supposed to open a modal
import { WebClient } from '#slack/web-api';
export default (payload, respond) => {
try {
console.info('Slack payload for my callback', payload);
const trigger_id = payload.trigger_id;
const web = new WebClient(process.env.SLACK_OAUTH_ACCESS_TOKEN)
const openModalPayload = {
trigger_id,
view: {
type: 'modal',
callback_id: 'view_identifier',
title: {
type: 'plain_text',
text: 'Modal title'
},
blocks: [
{
type: 'input',
label: {
type: 'plain_text',
text: 'Input label'
},
element: {
type: 'plain_text_input',
action_id: 'value_indentifier'
}
}
]
}
};
console.log(openModalPayload)
web.views.open(openModalPayload) # <<- this async call seems to be crashing
I opened an issue and the documentation was fixed, basically it's not possible to have a view with inputs without a submit button in the view payload
submit: {
type: 'plain_text',
text: 'Submit'
},

Send data from bot to client in DirectLine WebChat - NodeJS Botframework

I added bot to an HTML page on our intranet using the following code:
<link href="https://cdn.botframework.com/botframework-webchat/latest/botchat.css" rel="stylesheet" />
<style>
#bot{
height: 600px;
}
</style>
<div>
<div id="bot" />
</div>
<script src="https://cdn.botframework.com/botframework-webchat/latest/botchat.js"></script>
<script>
var user = {
id: 'user-id',
name: 'user name'
};
var botConnection = new BotChat.DirectLine({
token: '[token]',
user: user
});
BotChat.App({
user: user,
botConnection: botConnection,
bot: { id: 'test', name: 'test' }
}, document.getElementById("bot"));
botConnection
.postActivity({
from: user,
name: 'WelcomeDialog',
type: 'event',
value: ''
})
.subscribe(function (id) {
console.log('"trigger requestWelcomeDialog" sent');
});
</script>
Now, I need to send data back to this client, to be executed on that HTML page, since the page exists within the context of our intranet (internal servers), so I want to have the intent return from LUIS and directed to specific dialog, then send the required entity value from this dialog to the client to be executed there, then send the result back to the server so I can display a formatted message to the user.
So basically, I would need to have 2-way communication between the client (added to my intranet) and the bot itself (the nodejs app hosted in azure)
Update:
I implemented the backchannel in my bot, so now the code looks like this:
jQuery(function () {
//get user name from the system
var userid = _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
var requestHeaders = { "accept": "application/json;odata=verbose" };
$.ajax({
url: requestUri,
contentType: "application/json;odata=verbose",
headers: requestHeaders,
success: onSuccess,
error: onError
});
function onSuccess(data, request) {
var loginName = data.d.Title;
var user = {
id: userid,
name: loginName
};
var botConnection = new BotChat.DirectLine({
token: '[token]',
user: user
});
let FindPerson = function (personName) {
let msg = `You asked for ${personName}`
botConnection
.postActivity({ type: "event", value: msg, from: { id: "me" }, name: "FindPersonResultFound" })
.subscribe(id => console.log("success"));
}
BotChat.App({
user: user,
botConnection: botConnection,
bot: { id: 'TestBot', name: 'test bot' }
}, document.getElementById("bot"));
botConnection
.postActivity({
from: user,
name: 'WelcomeDialog',
type: 'event',
value: ''
})
.subscribe(function (id) {
console.log('"trigger requestWelcomeDialog" sent');
});
botConnection.activity$
.filter(activity => activity.type === "event" && activity.name === "FindPerson")
.subscribe(activity => FindPerson(activity.value))
}
function onError(error) {
alert("error");
}
})
My server side code looks like this:
bot.on('event', function (message) {
if (message.name == 'WelcomeDialog') {
bot.beginDialog(message.address, message.name);
}
if (message.name === "FindPersonResultFound") {
bot.beginDialog(message.address, message.name, message.value)
}
});
However, if I send a message that's related to any dialog, it gets repeated as if the sender is me:
According to your output, I assumpt that your bot application would contain a default root dialog / which will return any thing you input.
If so, you can try to change beginDialog to replaceDialog in your bot event register functions, to clear the previous dialog stack.
Also, you could provide more code about your bot application, so that we can have a deeper looking over.

Trigger Bot with Drag & drop SharePoint Online

I want to be able to trigger my bot who's on my SharePoint online Site by Droping a local file to him.
I created a WebPart to use this bot on the site, and putting the embed code give by Azure.
But when i drop a file in the bot, it open the document in a new tab showing me the content.
I would like to start the conversation while drop a file like this :
Start of bot conversation by putting a file
I'd imagine some solution by using a drop zone on the iframe which contain the bot, but it's not working.
I visit some site who can help but i don't really know how to implement this : Bot in WebChat, DirectLine API, Send Activity to the bot
This GitHub could also be usefull.
You'll need to handle the ondragover and ondrop events (cancelling the default behavior) and post the activity manually:
html:
<div id="bot" ondrop="drop_handler(event);" ondragover="dragover_handler(event);" />
Javascript:
const dl = new BotChat.DirectLine({
secret: 'YourDLSecret',
webSocket: false
});
BotChat.App({
botConnection: dl,
user: { id: 'userid' },
bot: { id: 'botid' },
resize: 'detect'
}, document.getElementById("bot"));
function dragover_handler(ev) {
console.log("dragOver");
ev.preventDefault();
}
function drop_handler(ev) {
console.log("Drop");
ev.preventDefault();
ev.stopPropagation();
var files = [];
for (var i = 0; i < ev.dataTransfer.items.length; i++) {
// If dropped items aren't files, reject them
if (ev.dataTransfer.items[i].kind === 'file') {
var file = ev.dataTransfer.items[i].getAsFile();
files.push({
contentType: file.type,
contentUrl: window.URL.createObjectURL(file),
name: file.name
});
}
}
dl.postActivity({
from: { id: 'userid' },
type: 'message',
attachments: files
})
.subscribe(function (id) {
console.log('files sent');
});
}

Pushpad is not able to send notifcation from node.js app

I have written the code shown below to send the push notification:
const pushpad = require('pushpad');
require('dotenv').config();
const axios = require('axios');
const project = new pushpad.Pushpad({
authToken: process.env.PUSH_PAD_AUTH_TOKEN,
projectId: process.env.PUSH_PAD_PROJECT_ID
});
console.log('called pushpad');
let notification = new pushpad.Notification({
project: project,
body: 'Hello world!',
title: 'Website Name',
targetUrl: 'http://example.com',
iconUrl: 'http://example.com/assets/icon.png',
imageUrl: 'http://example.com/assets/image.png',
ttl: 604800,
requireInteraction: true,
customData: '123',
actions: [
{
title: 'My Button 1',
targetUrl: 'http://example.com/button-link',
icon: 'http://example.com/assets/button-icon.png',
action: 'myActionName'
}
],
starred: true,
sendAt: new Date(Date.UTC(2016, 7 - 1, 25, 10, 9)),
customMetrics: ['examples', 'another_metric']
});
// deliver to everyone
notification.broadcast(function (err, result) {
console.log("error is " + err);
});
module.exports = notification;
but somehow, as soon as I run this code, it gives me error Unprocessable Entity . So how to solve this error ?
Probably you have entered some wrong parameters. For example customMetrics must be defined in your project settings before using them.
Try the same code with a simple notification:
let notification = new pushpad.Notification({
project: project,
body: 'Hello world!'
});

Resources