with
presented by
Realtime, multi-user experiences
Fibers, the Event Loop and Meteor
source: node-fibers
meteor add bootstrap
meteor add handlebars
meteor add jquery
meteor add underscore
meteor add service-configuration
meteor add accounts-github
meteor remove insecure
npm install --global meteorite
no longer needed!
Meteor 9.x includes a new Meteor package system (featuring Isobuild, Meteor Package Server)
meteor add <packagename>
meteor publish
meteor search <query>
if (Meteor.isServer) {
...
}
if (Meteor.isClient) {
...
}
Showcase = new Meteor.Collection("showcase");
if (Meteor.isServer) {
Meteor.publish("showcase-items", function () {
return Showcase.find(); // share everything in the showcase
});
}
if (Meteor.isClient) {
Meteor.subscribe("showcase-items");
}
<head>
<title>meteorshowcase</title>
</head>
<body>
{{> nav}}
{{> list}}
{{> submit}}
{{> edit}}
{{> view}}
</body>
<template name="list">
<div class="showcase">
{{#each items}}
{{> item}}
<hr/>
{{/each}}
</div>
</template>
<template name="view">
<div id='modal_view' class="modal fade in"
<div class="modal-header">
<a href="#" data-dismiss="modal" class="close pull-right;">×</a>
<h3 class="item_title">{{app_name}}</h3>
</div>
<div class="modal-body">
<div class'image_url'><a href='{{demo_url}}'><img src='{{image_url}}'/></a></div>
<div class='name'>{{app_name}}</div>
<div class='description'>{{description}}</div>
<div class='authored_by'>By: <span class='author'>{{author}}</span></div>
<div class='date'>Submitted on: {{date}}</div>
<div class='score'>Score: {{score}}</div>
<div class='source_url'>Source code: <a href='{{source_url}}'>{{source_url}}</a></div>
<p><a href="{{clone_url}}" class="shift btn btn-large btn-inverse btn-block">Run on OpenShift <b class='icon-cog'></b></a></p>
</div>
<div class="modal-footer">
{{# if currentUser }}<a href="#" $('#modal_edit').modal('show') && $('#modal_view').modal('hide');" class="edit pull-left btn btn-info">Settings <b class='icon-wrench'></b></a>{{/if}}
<a href="{{demo_url}}" onclick="console.log('Opening app...');" class="pull-right btn btn-primary">Visit <b class='icon-globe'></b></a>
<a href="#" data-dismiss="modal" onclick="$('#modal_view').modal('hide');" class="btn pull-right">Cancel <b class='icon-remove'></b></a>
</div>
</div>
</template>
Template.list.items = function () {
var nav_config = Session.get('nav_settings');
var sort_by = Session.get('sort_by');
var sort_order = {};
var filter = Session.get('filter');
if (!filter || filter == undefined){ filter = '' };
sort_order[sort_by] = nav_config[sort_by] || -1;
return Showcase.find({ name: { $regex: filter, $options: 'i'}}, {sort: sort_order}).fetch();
};
Template.nav.username = function () {
var u = Meteor.user();
return u && u.profile && u.profile.name;
};
Template.item.events({
'click a.inc': function () {
Showcase.update(Session.get("selected_item"), {$inc: {score: 5}});
},
'click a.dec': function () {
Showcase.update(Session.get("selected_item"), {$inc: {score: -5}});
},
'click a.view': function () {
$('#modal_view').modal('show');
}
});
Showcase.allow({
remove: function (userId, item) {
var username = false;
if(userId){
username = Meteor.users.findOne(userId).profile.name;
}
return (item.author == username || username == 'ryan jarvinen');
},
insert: function (userId, item) {
return (userId) ? true : false;
},
update: function (userId, item, fieldNames, modifier) {
update: function (userId, item, fieldNames, modifier) {
var username = false;
if(userId){
username = Meteor.users.findOne(userId).profile.name;
}
if(item.score > 9000){
// OVER 9000?!?!
return false;
}else if( _.isEqual(modifier, {$inc:{score: +5}})){
//allow voting by anyone
console.log('option1 - voter');
return true;
}else if( _.isEqual(modifier, {$inc:{score: -5}}) && item.score > 4 ){
//allow voting by anyone
console.log('option1 - voter');
return true;
}else if(username == 'ryan jarvinen') {
//allow updates by admins (me) :-P
console.log('option2 - admin');
return true;
}else{
//allow updates by owners
console.log('option3 - owner');
return ( username == item.author ) ? true : false;
}
}
var github_client_id = process.env.GITHUB_CLIENT || 'cc02855bd41dbfc4be72';
var github_client_secret = process.env.GITHUB_SECRET || '443ea5d64be6afada4acd946cf5b49878f4af4c8';
ServiceConfiguration.configurations.remove({
service: "github"
});
ServiceConfiguration.configurations.insert({
service: "github",
clientId: github_client_id,
secret: github_client_secret
});
to meteor.com:
meteor deploy
meteor --production
meteor bundle bundle.tar.gz
Thanks for following along! --ryanj
link to slides: