mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 18:11:40 -05:00
Merge branch 'Kestanous-herald-integration'
This commit is contained in:
commit
c46cf1cb24
13 changed files with 197 additions and 176 deletions
|
@ -46,6 +46,8 @@ jparker:crypto-core@0.1.0
|
||||||
jparker:crypto-md5@0.1.1
|
jparker:crypto-md5@0.1.1
|
||||||
jquery@1.0.0
|
jquery@1.0.0
|
||||||
json@1.0.0
|
json@1.0.0
|
||||||
|
kestanous:herald-email@0.2.1
|
||||||
|
kestanous:herald@0.6.0
|
||||||
less@1.0.9
|
less@1.0.9
|
||||||
livedata@1.0.10
|
livedata@1.0.10
|
||||||
localstorage@1.0.0
|
localstorage@1.0.0
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// Notifications - only load if user is logged in
|
|
||||||
// Not mandatory, because server won't publish anything even if we try to load.
|
|
||||||
// Remember about Deps.autorun - user can log in and log out several times
|
|
||||||
Tracker.autorun(function() {
|
|
||||||
// userId() can be changed before user(), because loading profile takes time
|
|
||||||
if(Meteor.userId()) {
|
|
||||||
Meteor.subscribe('notifications');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -3,17 +3,17 @@ Template[getTemplate('notificationItem')].helpers({
|
||||||
return moment(this.timestamp).fromNow();
|
return moment(this.timestamp).fromNow();
|
||||||
},
|
},
|
||||||
properties: function(){
|
properties: function(){
|
||||||
return this.properties;
|
return this.data;
|
||||||
},
|
},
|
||||||
notificationHTML: function(){
|
notificationHTML: function(){
|
||||||
return buildSiteNotification(this);
|
return this.message();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Template[getTemplate('notificationItem')].events({
|
Template[getTemplate('notificationItem')].events({
|
||||||
'click .action-link': function(event, instance){
|
'click .action-link': function(event, instance){
|
||||||
var notificationId=instance.data._id;
|
var notificationId=instance.data._id;
|
||||||
Notifications.update(
|
Herald.collection.update(
|
||||||
{_id: notificationId},
|
{_id: notificationId},
|
||||||
{
|
{
|
||||||
$set:{
|
$set:{
|
||||||
|
|
|
@ -3,13 +3,13 @@ Template[getTemplate('notificationsMenu')].helpers({
|
||||||
return getTemplate('notificationItem');
|
return getTemplate('notificationItem');
|
||||||
},
|
},
|
||||||
notifications: function(){
|
notifications: function(){
|
||||||
return Notifications.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}});
|
return Herald.collection.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}});
|
||||||
},
|
},
|
||||||
hasNotifications: function () {
|
hasNotifications: function () {
|
||||||
return !!Notifications.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}}).count();
|
return !!Herald.collection.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}}).count();
|
||||||
},
|
},
|
||||||
notification_count: function(){
|
notification_count: function(){
|
||||||
var notifications=Notifications.find({userId: Meteor.userId(), read: false}).fetch();
|
var notifications=Herald.collection.find({userId: Meteor.userId(), read: false}).fetch();
|
||||||
if(notifications.length==0){
|
if(notifications.length==0){
|
||||||
return i18n.t('No notifications');
|
return i18n.t('No notifications');
|
||||||
}else if(notifications.length==1){
|
}else if(notifications.length==1){
|
||||||
|
@ -19,7 +19,7 @@ Template[getTemplate('notificationsMenu')].helpers({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
notification_class: function(){
|
notification_class: function(){
|
||||||
var notifications=Notifications.find({userId: Meteor.userId(), read: false}).fetch();
|
var notifications=Herald.collection.find({userId: Meteor.userId(), read: false}).fetch();
|
||||||
if(notifications.length==0)
|
if(notifications.length==0)
|
||||||
return 'no-notifications';
|
return 'no-notifications';
|
||||||
}
|
}
|
||||||
|
|
110
packages/telescope-notifications/lib/herald.js
Normal file
110
packages/telescope-notifications/lib/herald.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
Herald.collection.deny({
|
||||||
|
update: ! can.editById,
|
||||||
|
remove: ! can.editById
|
||||||
|
});
|
||||||
|
|
||||||
|
Meteor.startup(function () {
|
||||||
|
// disable all email notifications when "emailNotifications" is set to false
|
||||||
|
if (getSetting('emailNotifications', true)) {
|
||||||
|
Herald.settings.overrides.email = false;
|
||||||
|
} else {
|
||||||
|
Herald.settings.overrides.email = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
var commentEmail = function (userToNotify) {
|
||||||
|
var notification = this;
|
||||||
|
// put in setTimeout so it doesn't hold up the rest of the method
|
||||||
|
Meteor.setTimeout(function () {
|
||||||
|
notificationEmail = buildEmailNotification(notification);
|
||||||
|
sendEmail(getEmail(userToNotify), notificationEmail.subject, notificationEmail.html);
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Herald.addCourier('newPost', {
|
||||||
|
media: {
|
||||||
|
email: {
|
||||||
|
emailRunner: function (user) {
|
||||||
|
var p = getPostProperties(this.data);
|
||||||
|
var subject = p.postAuthorName+' has created a new post: '+p.postTitle;
|
||||||
|
var html = buildEmailTemplate(getEmailTemplate('emailNewPost')(p));
|
||||||
|
sendEmail(getEmail(user), subject, html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// message: function (user) { return 'email template?' }
|
||||||
|
});
|
||||||
|
|
||||||
|
Herald.addCourier('newComment', {
|
||||||
|
media: {
|
||||||
|
onsite: {},
|
||||||
|
email: {
|
||||||
|
emailRunner: commentEmail
|
||||||
|
}
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
default: function (user) {
|
||||||
|
return Blaze.toHTML(Blaze.With(this, function(){
|
||||||
|
return Template[getTemplate('notificationNewComment')]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
profileUrl: function () {
|
||||||
|
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||||
|
if(user)
|
||||||
|
return getProfileUrl(user);
|
||||||
|
},
|
||||||
|
postCommentUrl: function () {
|
||||||
|
return '/posts/'+ this.data.post._id;
|
||||||
|
},
|
||||||
|
author: function () {
|
||||||
|
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||||
|
if(user)
|
||||||
|
return getUserName(user);
|
||||||
|
},
|
||||||
|
postTitle: function () {
|
||||||
|
return this.data.post.title;
|
||||||
|
},
|
||||||
|
url: function () {
|
||||||
|
return /comments/ + this.comment._id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Herald.addCourier('newReply', {
|
||||||
|
media: {
|
||||||
|
onsite: {},
|
||||||
|
email: {
|
||||||
|
emailRunner: commentEmail
|
||||||
|
}
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
default: function (user) {
|
||||||
|
return Blaze.toHTML(Blaze.With(this, function(){
|
||||||
|
return Template[getTemplate('notificationNewReply')]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
profileUrl: function () {
|
||||||
|
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||||
|
if(user)
|
||||||
|
return getProfileUrl(user);
|
||||||
|
},
|
||||||
|
postCommentUrl: function () {
|
||||||
|
return '/posts/'+ this.data.post._id;
|
||||||
|
},
|
||||||
|
author: function () {
|
||||||
|
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||||
|
if(user)
|
||||||
|
return getUserName(user);
|
||||||
|
},
|
||||||
|
postTitle: function () {
|
||||||
|
return this.data.post.title;
|
||||||
|
},
|
||||||
|
url: function () {
|
||||||
|
return /comments/ + this.parentComment._id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,125 +1,24 @@
|
||||||
Notifications = new Meteor.Collection('notifications');
|
|
||||||
|
|
||||||
// Notifications = new Meteor.Collection("notifications", {
|
|
||||||
// schema: new SimpleSchema({
|
|
||||||
// properties: {
|
|
||||||
// type: Object
|
|
||||||
// },
|
|
||||||
// event: {
|
|
||||||
// type: String
|
|
||||||
// },
|
|
||||||
// read: {
|
|
||||||
// type: Boolean
|
|
||||||
// },
|
|
||||||
// createdAt: {
|
|
||||||
// type: Date
|
|
||||||
// },
|
|
||||||
// userId: {
|
|
||||||
// type: "???"
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
|
|
||||||
Notifications.allow({
|
|
||||||
insert: function(userId, doc){
|
|
||||||
// new notifications can only be created via a Meteor method
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
update: can.editById,
|
|
||||||
remove: can.editById
|
|
||||||
});
|
|
||||||
|
|
||||||
createNotification = function(event, properties, userToNotify) {
|
|
||||||
// 1. Store notification in database
|
|
||||||
var notification = {
|
|
||||||
timestamp: new Date().getTime(),
|
|
||||||
userId: userToNotify._id,
|
|
||||||
event: event,
|
|
||||||
properties: properties,
|
|
||||||
read: false
|
|
||||||
};
|
|
||||||
var newNotificationId = Notifications.insert(notification);
|
|
||||||
|
|
||||||
// 2. Send notification by email (if on server)
|
|
||||||
if(Meteor.isServer && getUserSetting('notifications.replies', false, userToNotify)){
|
|
||||||
// put in setTimeout so it doesn't hold up the rest of the method
|
|
||||||
Meteor.setTimeout(function () {
|
|
||||||
notificationEmail = buildEmailNotification(notification);
|
|
||||||
sendEmail(getEmail(userToNotify), notificationEmail.subject, notificationEmail.html);
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
buildSiteNotification = function (notification) {
|
|
||||||
var event = notification.event,
|
|
||||||
comment = notification.properties.comment,
|
|
||||||
post = notification.properties.post,
|
|
||||||
userToNotify = Meteor.users.findOne(notification.userId),
|
|
||||||
template,
|
|
||||||
html;
|
|
||||||
|
|
||||||
var properties = {
|
|
||||||
profileUrl: getProfileUrlById(comment.userId),
|
|
||||||
author: comment.author,
|
|
||||||
postCommentUrl: getPostCommentUrl(post._id, comment._id),
|
|
||||||
postTitle: post.title
|
|
||||||
};
|
|
||||||
|
|
||||||
switch(event){
|
|
||||||
case 'newReply':
|
|
||||||
template = 'notificationNewReply';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'newComment':
|
|
||||||
template = 'notificationNewComment';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
html = Blaze.toHTML(Blaze.With(properties, function(){
|
|
||||||
return Template[getTemplate(template)]
|
|
||||||
}));
|
|
||||||
|
|
||||||
return html;
|
|
||||||
};
|
|
||||||
|
|
||||||
Meteor.methods({
|
|
||||||
markAllNotificationsAsRead: function() {
|
|
||||||
Notifications.update(
|
|
||||||
{userId: Meteor.userId()},
|
|
||||||
{
|
|
||||||
$set:{
|
|
||||||
read: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{multi: true}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// add new post notification callback on post submit
|
// add new post notification callback on post submit
|
||||||
postAfterSubmitMethodCallbacks.push(function (post) {
|
postAfterSubmitMethodCallbacks.push(function (post) {
|
||||||
if(Meteor.isServer && !!getSetting('emailNotifications', true)){
|
if(Meteor.isServer){
|
||||||
// we don't want emails to hold up the post submission, so we make the whole thing async with setTimeout
|
var userIds = Meteor.users.find({'profile.notifications.posts': 1}, {fields: {}}).map(function (user) {
|
||||||
Meteor.setTimeout(function () {
|
return user._id
|
||||||
newPostNotification(post, [post.userId])
|
});
|
||||||
}, 1);
|
Herald.createNotification(userIds, {courier: 'newPost', data: post})
|
||||||
}
|
}
|
||||||
return post;
|
return post;
|
||||||
});
|
});
|
||||||
|
|
||||||
// add new comment notification callback on comment submit
|
// add new comment notification callback on comment submit
|
||||||
commentAfterSubmitMethodCallbacks.push(function (comment) {
|
commentAfterSubmitMethodCallbacks.push(function (comment) {
|
||||||
if(Meteor.isServer && !!getSetting('emailNotifications', true)){
|
if(Meteor.isServer){
|
||||||
|
|
||||||
var parentCommentId = comment.parentCommentId;
|
var parentCommentId = comment.parentCommentId;
|
||||||
var user = Meteor.user();
|
var user = Meteor.user();
|
||||||
var post = Posts.findOne(comment.postId);
|
var post = Posts.findOne(comment.postId);
|
||||||
var postUser = Meteor.users.findOne(post.userId);
|
var postUser = Meteor.users.findOne(post.userId);
|
||||||
|
|
||||||
var notificationProperties = {
|
var notificationData = {
|
||||||
comment: _.pick(comment, '_id', 'userId', 'author', 'body'),
|
comment: _.pick(comment, '_id', 'userId', 'author', 'body'),
|
||||||
post: _.pick(post, '_id', 'title', 'url')
|
post: _.pick(post, '_id', 'title', 'url')
|
||||||
};
|
};
|
||||||
|
@ -129,23 +28,23 @@ commentAfterSubmitMethodCallbacks.push(function (comment) {
|
||||||
var parentComment = Comments.findOne(parentCommentId);
|
var parentComment = Comments.findOne(parentCommentId);
|
||||||
var parentUser = Meteor.users.findOne(parentComment.userId);
|
var parentUser = Meteor.users.findOne(parentComment.userId);
|
||||||
|
|
||||||
notificationProperties.parentComment = _.pick(parentComment, '_id', 'userId', 'author');
|
notificationData.parentComment = _.pick(parentComment, '_id', 'userId', 'author');
|
||||||
|
|
||||||
// reply notification
|
// reply notification
|
||||||
// do not notify users of their own actions (i.e. they're replying to themselves)
|
// do not notify users of their own actions (i.e. they're replying to themselves)
|
||||||
if(parentUser._id != user._id)
|
if(parentUser._id != user._id)
|
||||||
createNotification('newReply', notificationProperties, parentUser);
|
Herald.createNotification(parentUser._id, {courier: 'newReply', data: notificationData})
|
||||||
|
|
||||||
// comment notification
|
// comment notification
|
||||||
// if the original poster is different from the author of the parent comment, notify them too
|
// if the original poster is different from the author of the parent comment, notify them too
|
||||||
if(postUser._id != user._id && parentComment.userId != post.userId)
|
if(postUser._id != user._id && parentComment.userId != post.userId)
|
||||||
createNotification('newComment', notificationProperties, postUser);
|
Herald.createNotification(postUser._id, {courier: 'newComment', data: notificationData})
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// root comment
|
// root comment
|
||||||
// don't notify users of their own comments
|
// don't notify users of their own comments
|
||||||
if(postUser._id != user._id)
|
if(postUser._id != user._id)
|
||||||
createNotification('newComment', notificationProperties, postUser);
|
Herald.createNotification(postUser._id, {courier: 'newComment', data: notificationData})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +59,7 @@ var emailNotifications = {
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
autoform: {
|
autoform: {
|
||||||
group: 'notifications',
|
group: 'notifications',
|
||||||
instructions: 'Enable email notifications for new posts and new comments.'
|
instructions: 'Enable email notifications for new posts and new comments (requires restart).'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@ getUnsubscribeLink = function(user){
|
||||||
buildEmailNotification = function (notification) {
|
buildEmailNotification = function (notification) {
|
||||||
|
|
||||||
var subject, template;
|
var subject, template;
|
||||||
var post = notification.properties.post;
|
var post = notification.data.post;
|
||||||
var comment = notification.properties.comment;
|
var comment = notification.data.comment;
|
||||||
|
|
||||||
switch(notification.event){
|
switch(notification.courier){
|
||||||
case 'newReply':
|
case 'newReply':
|
||||||
subject = 'Someone replied to your comment on "'+post.title+'"';
|
subject = 'Someone replied to your comment on "'+post.title+'"';
|
||||||
template = 'emailNewReply';
|
template = 'emailNewReply';
|
||||||
|
@ -24,7 +24,7 @@ buildEmailNotification = function (notification) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var emailProperties = _.extend(notification.properties, {
|
var emailProperties = _.extend(notification.data, {
|
||||||
body: marked(comment.body),
|
body: marked(comment.body),
|
||||||
profileUrl: getProfileUrlById(comment.userId),
|
profileUrl: getProfileUrlById(comment.userId),
|
||||||
postCommentUrl: getPostCommentUrl(post._id, comment._id),
|
postCommentUrl: getPostCommentUrl(post._id, comment._id),
|
||||||
|
@ -42,20 +42,6 @@ buildEmailNotification = function (notification) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
newPostNotification = function(post, excludedIDs){
|
|
||||||
var excludedIDs = typeof excludedIDs == 'undefined' ? [] : excludedIDs;
|
|
||||||
var p = getPostProperties(post);
|
|
||||||
var subject = p.postAuthorName+' has created a new post: '+p.postTitle;
|
|
||||||
var html = buildEmailTemplate(getEmailTemplate('emailNewPost')(p));
|
|
||||||
|
|
||||||
// send a notification to every user according to their notifications settings
|
|
||||||
Meteor.users.find({'profile.notifications.posts': 1}).forEach(function(user) {
|
|
||||||
// don't send user a notification if their ID is in excludedIDs
|
|
||||||
if(excludedIDs.indexOf(user._id) == -1)
|
|
||||||
sendEmail(getEmail(user), subject, html);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
unsubscribeUser : function(hash){
|
unsubscribeUser : function(hash){
|
||||||
// TO-DO: currently, if you have somebody's email you can unsubscribe them
|
// TO-DO: currently, if you have somebody's email you can unsubscribe them
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
Meteor.publish('notifications', function() {
|
|
||||||
// only publish notifications belonging to the current user
|
|
||||||
if(canViewById(this.userId)){
|
|
||||||
return Notifications.find({userId:this.userId});
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
});
|
|
|
@ -10,13 +10,14 @@ Package.onUse(function (api) {
|
||||||
'telescope-lib',
|
'telescope-lib',
|
||||||
'telescope-base',
|
'telescope-base',
|
||||||
'telescope-email',
|
'telescope-email',
|
||||||
'aldeed:simple-schema'
|
'kestanous:herald@0.6.0',
|
||||||
|
'kestanous:herald-email@0.2.1'
|
||||||
], ['client', 'server']);
|
], ['client', 'server']);
|
||||||
|
|
||||||
api.use([
|
api.use([
|
||||||
|
'iron:router',
|
||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'iron:router',
|
|
||||||
'templating',
|
'templating',
|
||||||
'tracker'
|
'tracker'
|
||||||
], 'client');
|
], 'client');
|
||||||
|
@ -27,10 +28,10 @@ Package.onUse(function (api) {
|
||||||
|
|
||||||
api.add_files([
|
api.add_files([
|
||||||
'lib/notifications.js',
|
'lib/notifications.js',
|
||||||
|
'lib/herald.js'
|
||||||
], ['client', 'server']);
|
], ['client', 'server']);
|
||||||
|
|
||||||
api.add_files([
|
api.add_files([
|
||||||
'lib/client/notifications-client.js',
|
|
||||||
'lib/client/templates/notification_item.html',
|
'lib/client/templates/notification_item.html',
|
||||||
'lib/client/templates/notification_item.js',
|
'lib/client/templates/notification_item.js',
|
||||||
'lib/client/templates/notification_new_comment.html',
|
'lib/client/templates/notification_new_comment.html',
|
||||||
|
@ -42,18 +43,13 @@ Package.onUse(function (api) {
|
||||||
], ['client']);
|
], ['client']);
|
||||||
|
|
||||||
api.add_files([
|
api.add_files([
|
||||||
'lib/server/notifications-server.js',
|
'lib/server/notifications-server.js'
|
||||||
'lib/server/publication.js'
|
|
||||||
], ['server']);
|
], ['server']);
|
||||||
|
|
||||||
api.export([
|
api.export([
|
||||||
'Notifications',
|
'Herald',
|
||||||
'createNotification',
|
|
||||||
'buildSiteNotification',
|
|
||||||
'newPostNotification',
|
|
||||||
'buildEmailNotification',
|
'buildEmailNotification',
|
||||||
'getUnsubscribeLink',
|
'getUnsubscribeLink'
|
||||||
'postSubmitMethodCallbacks'
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
[
|
|
||||||
"aldeed:simple-schema",
|
|
||||||
"1.0.3"
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
"application-configuration",
|
"application-configuration",
|
||||||
"1.0.2"
|
"1.0.2"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"autoupdate",
|
||||||
|
"1.1.1"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"base64",
|
"base64",
|
||||||
"1.0.0"
|
"1.0.0"
|
||||||
|
@ -52,6 +52,10 @@
|
||||||
"ejson",
|
"ejson",
|
||||||
"1.0.3"
|
"1.0.3"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"fastclick",
|
||||||
|
"1.0.0"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"follower-livedata",
|
"follower-livedata",
|
||||||
"1.0.1"
|
"1.0.1"
|
||||||
|
@ -72,6 +76,10 @@
|
||||||
"htmljs",
|
"htmljs",
|
||||||
"1.0.1"
|
"1.0.1"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"http",
|
||||||
|
"1.0.6"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"id-map",
|
"id-map",
|
||||||
"1.0.0"
|
"1.0.0"
|
||||||
|
@ -100,6 +108,18 @@
|
||||||
"json",
|
"json",
|
||||||
"1.0.0"
|
"1.0.0"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"kestanous:herald",
|
||||||
|
"0.6.0"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"kestanous:herald-email",
|
||||||
|
"0.2.1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"livedata",
|
||||||
|
"1.0.10"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"logging",
|
"logging",
|
||||||
"1.0.3"
|
"1.0.3"
|
||||||
|
@ -108,6 +128,10 @@
|
||||||
"meteor",
|
"meteor",
|
||||||
"1.1.1"
|
"1.1.1"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"meteor-platform",
|
||||||
|
"1.1.1"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"minifiers",
|
"minifiers",
|
||||||
"1.1.0"
|
"1.1.0"
|
||||||
|
@ -116,6 +140,10 @@
|
||||||
"minimongo",
|
"minimongo",
|
||||||
"1.0.3"
|
"1.0.3"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"mobile-status-bar",
|
||||||
|
"1.0.0"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"mongo",
|
"mongo",
|
||||||
"1.0.6"
|
"1.0.6"
|
||||||
|
@ -140,6 +168,10 @@
|
||||||
"reactive-var",
|
"reactive-var",
|
||||||
"1.0.2"
|
"1.0.2"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"reload",
|
||||||
|
"1.1.0"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"retry",
|
"retry",
|
||||||
"1.0.0"
|
"1.0.0"
|
||||||
|
@ -148,6 +180,10 @@
|
||||||
"routepolicy",
|
"routepolicy",
|
||||||
"1.0.1"
|
"1.0.1"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"session",
|
||||||
|
"1.0.2"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"spacebars",
|
"spacebars",
|
||||||
"1.0.2"
|
"1.0.2"
|
||||||
|
@ -156,6 +192,10 @@
|
||||||
"spacebars-compiler",
|
"spacebars-compiler",
|
||||||
"1.0.2"
|
"1.0.2"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"standard-app-packages",
|
||||||
|
"1.0.2"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"telescope-base",
|
"telescope-base",
|
||||||
"0.0.0"
|
"0.0.0"
|
||||||
|
@ -188,6 +228,10 @@
|
||||||
"underscore",
|
"underscore",
|
||||||
"1.0.0"
|
"1.0.0"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"url",
|
||||||
|
"1.0.0"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"webapp",
|
"webapp",
|
||||||
"1.1.2"
|
"1.1.2"
|
||||||
|
|
Loading…
Add table
Reference in a new issue