I have reproduced my case with this jsbin http://emberjs.jsbin.com/xeninaceze/edit?js,output
Github API allows me to get the list of events by author:
API Link - api.github.com/users/:user/events
I can access to the commit message filtering the events “PushEvent”, and it s perfectly fine because i cam stream my latest commit message.
var gitactivitiesPromise = function() {
return new Ember.RSVP.Promise(function (resolve) {
Ember.$.ajax(eventsAct, {
success: function(events) {
var result = [];
events.filter(function(event) {
return event.type == 'PushEvent';
}).forEach(function(item){
item.payload.commits.map(function(commit){
result.push(store.createRecord('commit', {
message: commit.message,
}));
});
});
resolve(result);
},
error: function(reason) {
reject(reason);
}
});
});
};
The problem is that i want to stream beside the msg also his own url link. html_url
I need to know how i can tackle it? since the commit url links are not in the in the API Link
api.github.com/users/:user/events
But they are in the following api
api.github.com/repos/:user/repo/commits/branch
This makes bit more complicate to access to the latest commits url link html_url
This is a good example of what i am trying to do
http://zmoazeni.github.io/gitspective/#
It streams in the push events the latest commits message with links
It seems to me that all the relevant data is already there:
{
"id": "3414229549",
"type": "PushEvent",
"actor": {
...
"login": "paulirish"
},
"repo": {
...
"name": "GoogleChrome/devtools-docs"
},
"payload": {
...
"commits": [
{
...
"message": "fish shell. really liking it.",
"sha": "1f9740c9dd07f166cb4b92ad053b17dbc014145b"
},
...
You can access the author URL as actor and the repository as repo. With this it's easy to construct the relevant links:
...
.forEach(function(item) {
var repoUrl = 'https://github.com/' + item.repo.name;
var authorUrl = 'https://github.com/' + item.actor.login;
item.payload.commits.map(function(commit) {
result.push(store.createRecord('commit', {
authorUrl: authorUrl,
repositoryUrl: repoUrl,
commitUrl: repoUrl + '/commit/' + commit.sha,
message: commit.message
}));
});
})
...
Updated JSBin: http://emberjs.jsbin.com/feyedujulu/1/edit?js,output
Related
I am having problems to implement notifications using firebase. The click event does not work. I am using the HTTP 1 version sending the bearer token.
{
"message": {
"token": "8888****usertoken****8888",
"notification": {
"title": "Background Message Title",
"body": "Background message body"
},
"webpush": {
"fcm_options": {
"link": "https://dummypage.com"
}
}
}
}
I have also tried click_action, action, and many other variations that just did not work.
I am using version 8.0.0
According to the documentation found on this link https://firebase.google.com/docs/cloud-messaging/js/send-multiple, I should be able to implement it using fcm_options.
I tried a workaround implementing messaging.onBackgroundMessage, but when I implement this method and use self.registration.showNotification, the notification is displayed twice. one triggered by the browse and the other by this code.
Registering self.addEventListener('notificationclick' only seems to work when I implement onBackgroundMessage.
I followed the documentation, but it is driving me crazy.
This is my service worker code:
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-messaging.js');
var firebaseConfig = {
apiKey: "xxxxxx",
authDomain: "xxxxxxxx.firebaseapp.com",
databaseURL: "https://xxxxxx.firebaseio.com",
projectId: "xxx-xxx",
storageBucket: "xxx-xxx.appspot.com",
messagingSenderId: "222222222",
appId: "1:2222:web:22222"
};
console.log("fire base messaging")
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
console.log("onBackgroundMessage", payload)
var dataFromServer = payload.notification;
var notificationTitle = dataFromServer.title;
var notificationOptions = {
body: dataFromServer.body,
image: dataFromServer.image,
data: {
url: "https://google.com"
}
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
////Code for adding event on click of notification
self.addEventListener('notificationclick', function (event) {
console.log("notificationclick", event)
var urlToRedirect = event.notification.data.url;
event.notification.close();
event.waitUntil(self.clients.openWindow(urlToRedirect));
});
Turns out I was passing an entire URL to webpush.fcm_options.link = "https://google.com", all I had to do was to pass only the relative path like webpush.fcm_options.link = "/mypage".
So the request to send would be like this:
{
"message": {
"token": "8888****usertoken****8888",
"notification": {
"title": "Background Message Title",
"body": "Background message body"
},
"webpush": {
"fcm_options": {
"link": "/mypage"
}
}
}
}
I don't see in the docs say it is only the relative path. It even states that HTTPS is required. I spent a few hours on this one, I hope it helps somebody else.
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#WebpushFcmOptions
I was having the same issue. I added a notificationclick event handler. You can use the data param in the notification event to open a new tab or focus an already opened one.
The code you already have is fine, now adding the listener looks like this:
// messaging.onBackgroundMessage(...);
function handleClick (event) {
event.notification.close();
// Open the url you set on notification.data
clients.openWindow(event.notification.data.url)
}
self.addEventListener('notificationclick', handleClick);
This resources might be helpful
similar question on SO
showNotification
notificationclick
Notifications are working using legacy API but unfortunately clicking the notification still does nothing. This is my code for sending the notification.
var notification = {
'title': title,
'body': body,
'icon': 'hourglass.png',
'click_action': router.resolve(route).href
}
var payload = {
'notification': notification,
// 'webpush': {
// 'fcm_options': {
// 'link': '/' + router.resolve(route).href
// }
// }
}
if(registrationIds.length == 1) {
payload['to'] = registrationIds[0]
} else if( registrationIds.length > 1){
payload['registration_ids'] = registrationIds
}
return new Promise((resolve, reject) => {
if (registrationIds.length) {
fetch('https://fcm.googleapis.com/fcm/send', {
'method': 'POST',
'headers': {
'Authorization': 'key=' + key,
'Content-Type': 'application/json'
},
'body': JSON.stringify(payload)
}).then(function(response) {
resolve(true)
}).catch(function(error) {
console.error('sendNotification error', error);
reject(false)
})
}
else {
console.log('This timer has no registered clients.')
reject(false)
}
})
Edit: I think most of my confusion stemmed from finding examples with the V1 API and mixing them up with the legacy API. I needed click_action instead of the fcm_options.link in the payload. I updated my code and is now working as intended.
I need to use DBus to change the v4 IP address of a network interface, and/or set it to use DHCP from a nodejs based service.
I've spent more than an afternoon trying to use dbus-network-manager to this end. I think I'm close, but no cigar yet.
Here's my client code, it's close to minimal despite its length, sorry.
// convenience logging method.
function pretty(obj) {return JSON.stringify(obj,null,2)};
// connect to NetworkManager via DBus
const NetWorkManager = require('dbus-network-manager').connect()
.then(nm => {
// Get a device inventory.
nm.GetDevices()
.then (devices => {
// filter out the Ethernet device to try to change its address
devices.forEach(dev => {
console.log (dev.objectPath);
dev.getProperties()
.then(props => {
// this is where we filter out non-Ethernet interfaces.
if (props.DeviceType == nm.fromEnum(nm.enums.DeviceType, 'Ethernet')) {
// get the ActiveConnection so we can get at the interface config
nm.ActiveConnection.connect(props.ActiveConnection)
.then(ac => {
//console.log(ac);
return ac.getProperties();
})
.then (acProps => {
//console.log ('ActiveConnection: ' + pretty(acProps));
// get our connection which should let us change the interface settings.
return nm.Connection.connect(acProps.Connection);
})
.then (conn => {
// get the settings, so we can use the object
// as a template to adjust & send back to NM.
conn.GetSettings()
.then (settings => {
// log the settings we read, overwrite what seems sensible
console.log('original: ' + pretty(settings.ipv4));
settings.ipv4['address-data'] = [
{
"address": "192.168.1.200",
"prefix": 24
}
];
// 192.168.1.200, 24, 192.168.1.254 in network order.
settings.ipv4.addresses = [3355551936,24,4261521600];
settings.ipv4.method = 'static';
// this should do the trick (but it doesn't), 2 = write to memory
conn.Update2(settings,2);
console.log ('updated: ' + pretty(settings.ipv4));
// these event handlers are never triggered
conn.on('Updated', () => {
console.log ('settings were updated');
});
conn.on('PropertiesChanged', res => {
console.log ('Properties changed: ', pretty(res));
});
});
});
} else {
console.log ('skipping: ' + props.Interface +
', which is of type: ' + nm.toEnum(nm.enums.DeviceType, props.DeviceType)
)
}
});
});
});
})
.catch (err => {
console.log ('Problem: ' + err);
})
And here's what it logs...
skipping: lo, which is of type: Generic
skipping: docker0, which is of type: Bridge
original: {
"method": "auto",
"dns": [],
"dns-search": [],
"addresses": [],
"routes": [],
"address-data": [],
"route-data": []
}
updated: {
"method": "static",
"dns": [],
"dns-search": [],
"addresses": [
3355551936,
24,
4261521600
],
"routes": [],
"address-data": [
{
"address": "192.168.1.200",
"prefix": 24
}
],
"route-data": []
}
NetworkManager is version 1.10.6-2ubuntu
Ubuntu is version 18.04.1 LTS
Nodejs is version 8.9.1
DBus is version 1.12.2-1ubuntu1
Thanks in advance!
I am not useing NPM dbus manager but ran into a similar problem.
After updating the settings object i also had to Reapply the device so it would read these changes. I was also able to use the command nmcli connection up id eth0 to reload the interface settings.
Example:
conn.Update2(new_settings,2);
dev.Reapply({},0,0)
I'm really confused at this point with losing data and can't figure out why. So I write a service to send GPS info from a device to an endpoint.
I'm using pm2 to launch my processes but the problem is this service sometimes don't send the info to the endpoint, and the device is sending data. The solution until now was restarting the instance in pm2. But this sometimes is not viable because I create a crontab to restart the GPS instance in pm2 every 45 minutes but it happens to lose information in a time window < 45 min this will not work...
I can't figure this out. Why I lose the data and restarting everything is okay? I saw a post in stack overflow about lost data in node.js process when the child sends the data to the parent and I read about 2 possible causes:
The child is not reading the GPS data info quickly enough in time to make a post and send info.
The child needs to make a JSON.stringify of the content sent to parent and parent needs to make a JSON.parse of the info received.
Here's my code:
var child_process = require("child_process");
var argv = require('minimist')(process.argv.slice(2));
//ex: nsGPSService.js -d 1111-11-11-111
var deviceId = argv.d;
var processDevices = [];
function runParent() {
setTimeout(function() {
return Database.Devices.getDevices().then(function(devices) {
return new Promise(function(resolve, reject) {
async.each(devices, function(device, callback) {
var result = _.filter(processDevices, { "id": device.id });
if (result.length == 0) {
var process = child_process.fork(__dirname + '/nsGPSService.js', ["-d", device.id]);
processDevices.push({ "process": process, "id": device.id });
process.on('message', function(data) {
//receber mensagens do filho
if (data.reason == "deleted") {
//child end process and alerts parent to remove from the list
var index = _.findIndex(processDevices, { "id": data.deviceId });
processDevices.splice(index, 1);
}
});
process.on('exit', function(code) {});
process.on("uncaughtException", function(error) {
process.exit(1);
});
}
callback();
}, function(error) {
error ? reject(error) : resolve();
});
}).then(function() {
runParent()
}).catch(function(error) {
runParent()
});
});
}, 5000);
}
if (!deviceId) {
return runParent();
}
function runChild(id) {
setTimeout(function() {
return Database.Devices.getDeviceById(id).then(function(device) {
if (!device) {
proccess.send({
"deviceId": id,
"reason": "deleted"
});
process.exit();
return;
}
return Controllers.Gps.getRadioInfo('gps', 'info', {}, device).then(function(data) {
return Controllers.Gps.sendDeviceInfo(data, device);
}).then(function() {
return runChild(id);
}).catch(function(e) {
return runChild(id);
});
});
}, 5000);
}
I really need to figure this out because I never know when I need to restart the service because I'm not getting info when in reality I'm receiving...
Which solution is really viable in my scenario and anyone can figure this problem?
I currently have a database with 2 objects:
Role
Permission
ONE Role can have MANY permissions. I currently have my Role adapter setup as:
export default DS.RESTAdapter.extend(DataAdapterMixin, {
namespace: 'v1',
host: ENV.APP.API_HOST,
authorizer: 'authorizer:application',
pathForType: function(type) {
return 'staff/roles';
}
});
By default, when a Permission is added to a Role, it generates this request:
Request:
PUT /v1/staff/roles/1
Body:
{
"name": "name_of_role"
"permissions": [
{
"id": "3",
"name": "name_of_permission"
},
...
]
}
I'd like to customize my adapter to produce a request that looks like this instead:
Request:
PUT /v1/staff/roles/1/permissions/3
Body:
<None>
Can someone please tell me how I can go about doing this? Updating the server api to accommodate Ember JS is unfortunately not an option.
UPDATE:
Based on Ryan's response, here's a (I'll call it messy) workaround that did the trick for me.
Open to suggestions for making this more elegant:
export default DS.RESTAdapter.extend(DataAdapterMixin, {
namespace: 'v1',
host: ENV.APP.API_HOST,
authorizer: 'authorizer:application',
pathForType: function(type) {
return 'staff/roles';
},
updateRecord: function(embestore, type, snapshot) {
var roleID = snapshot.id;
var permissionID = snapshot.adapterOptions.permissionID;
var url = ENV.APP.API_HOST + "/v1/staff/roles/" + roleID + "/permissions/" + permissionID;
return new Ember.RSVP.Promise(function(resolve, reject){
Ember.$.ajax({
type: 'PUT',
url: url,
headers: {'Authorization': 'OAUTH_TOKEN'},
dataType: 'json',
}).then(function(data) {
Ember.run(null, resolve, data);
}, function(jqXHR) {
jqXHR.then = null; // tame jQuery's ill mannered promises
Ember.run(null, reject, jqXHR);
});
});
},
});
I can't find it in the Ember documentation but there is a universal ajax method attached to adapter that you can override.
So in my adapter to fit our auth scheme I've done this:
export default DS.RESTAdapter.extend({
host: ENV.host,
ajax: function(url, method, hash){
if(hash){
if(hash.data !== undefined && hash.data !== null){
hash.data.sessionId = this.getSessionId();
}
}else {
hash = {
data: {}
};
hash.data.sessionId = this.getSessionId();
}
return this._super(url, method, hash);
},
getSessionId: function(){
return window.sessionStorage.getItem('sessionId') || {};
}
}
This attaches the sessionId to every ajax call to the server made though out the entire application.
Changing it to modify your url based on the hash arguments passed in shouldn't be an issue.
My version of ember is 2.3.2 but I'm on the latest stable(2.5.2) version of ember-data and this is still working great in case you are worried about the age of that blog post I found.
I am trying to make sing post page a route where it does a several things using iron:router
Uses the template postPage
Subscribes to publication of singlePost, userStatus (shows status and info of Author of single post page'), comments .
Grabs Comments documents that has field of postId : this.params._id
Increments Comments List by Session.get('commentLimit')
Here is the code I currently have.
Router.js
Router.route('/posts/:_id', {
name: 'postPage',
subscriptions: function() {
return [
Meteor.subscribe('singlePost', this.params._id),
Meteor.subscribe('userStatus'),
Meteor.subscribe('comments', {
limit: Number(Session.get('commentLimit'))
})
];
},
data: function() {
return Posts.findOne({_id:this.params._id});
},
});
Publications.js
Meteor.publish('singlePost', function(id) {
check(id, String);
return Posts.find(id);
});
Meteor.publish('comments', function(options) {
check(options, {
limit: Number
});
return Comments.find({}, options);
});
Template.postPage.onCreated
Template.onCreated( function () {
Session.set('commentLimit', 4);
});
Template.postPage.helpers
Template.postPage.helpers({
comments: function () {
var commentCursor = Number(Session.get('commentLimit'));
return Comments.find({postId: this._id}, {limit: commentCursor});
},
});
Template.postPage.events
Template.postPage.events({
'click a.load-more-comments': function (event) {
event.preventDefault();
Session.set('commentLimit', Number(Session.get('commentLimit')) + 4)
}
});
Everything works fine, but I found one thing to be inconsistent.
Here is the problem I am having...
User goes into single post page and adds comment (everything works fine).
User goes into a different single post page and adds comment (everything works fine).
Here is where the problem begins
The user at any time, goes into another route that is not the single post page.
User goes back into single post page
The comments are not showing.
New comments will be added into DB but still wont show
This problem only goes away when meteor reset or manual deletion of all comments in MongoDB is performed.
Is there a better way that I can code my routing and related code to stop this weird behavior from happening?
Or even if there is a better practice.
Your publish is publishing comments without any postId filter.
Your helper, filters by postId. Maybe the 4 comments that get published are the ones that do not belong to the current post that is open?
Could you try updating, your subscription to
Meteor.subscribe('comments', {
postId: this.params._id
}, {
limit: Number(Session.get('commentLimit'))
})
and your publication to
Meteor.publish('comments', function(filter, options) {
check(filter, {
postId: String
});
check(options, {
limit: Number
});
return Comments.find(filter, options);
});
so that only the same posts' comments are published?
I have figured it out. I have updated the following codes.
So far it is not showing weird behavior...
Publications.js
Meteor.publish('comments', function(postId, limit) {
check(postId, String);
check(limit, Number);
return Comments.find({postId:postId}, {limit:limit});
});
Router.js
Router.route('/posts/:_id', {
name: 'postPage',
subscriptions: function () {
return [
Meteor.subscribe('singlePost', this.params._id),
Meteor.subscribe('userStatus'),
Meteor.subscribe('comments', this.params._id, Number(Session.get('commentLimit')))
];
},
data: function() {
return Posts.findOne({_id:this.params._id});
},
});