Repository: scotch-io/meteor-slack
Branch: master
Commit: 51ec9c40c336
Files: 29
Total size: 18.0 KB
Directory structure:
gitextract_8ntt3t25/
├── .meteor/
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── README.md
├── client/
│ ├── app.js
│ ├── components/
│ │ ├── channel.html
│ │ ├── footer.html
│ │ ├── header.html
│ │ ├── listings.html
│ │ ├── message.html
│ │ └── messages.html
│ ├── global.css
│ ├── head.html
│ ├── input.js
│ ├── room.html
│ ├── routes.js
│ ├── startup/
│ │ └── subscribe.js
│ └── stubs.js
├── lib/
│ └── collections/
│ ├── channels.js
│ └── messages.js
└── server/
├── accounts.js
├── mail.js
├── methods.js
├── publications.js
└── seeder.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .meteor/.finished-upgraders
================================================
# This file contains information which helps Meteor properly upgrade your
# app when you run 'meteor update'. You should check it into version control
# with your project.
notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
================================================
FILE: .meteor/.gitignore
================================================
local
================================================
FILE: .meteor/.id
================================================
# This file contains a token that is unique to your project.
# Check it into your repository along with the rest of this directory.
# It can be used for purposes such as:
# - ensuring you don't accidentally deploy one app on top of another
# - providing package authors with aggregated statistics
1yevmue1ah7sfon2yoez
================================================
FILE: .meteor/packages
================================================
# Meteor packages used by this project, one per line.
# Check this file (and the other files in this directory) into your repository.
#
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor-platform
anti:fake
dburles:factory
accounts-base
accounts-password
accounts-ui
accounts-github
email
iron:router
================================================
FILE: .meteor/platforms
================================================
server
browser
================================================
FILE: .meteor/release
================================================
METEOR@1.1.0.2
================================================
FILE: .meteor/versions
================================================
accounts-base@1.2.0
accounts-github@1.0.4
accounts-oauth@1.1.5
accounts-password@1.1.1
accounts-ui@1.1.5
accounts-ui-unstyled@1.1.7
anti:fake@0.4.1
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
dburles:factory@0.3.10
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
email@1.0.6
fastclick@1.0.3
geojson-utils@1.0.3
github@1.1.3
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
iron:controller@1.0.7
iron:core@1.0.7
iron:dynamic-template@1.0.7
iron:layout@1.0.7
iron:location@1.0.7
iron:middleware-stack@1.0.7
iron:router@1.0.7
iron:url@1.0.7
jquery@1.11.3_2
json@1.0.3
launch-screen@1.0.2
less@1.0.14
livedata@1.0.13
localstorage@1.0.3
logging@1.0.7
meteor@1.1.6
meteor-platform@1.2.2
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
npm-bcrypt@0.7.8_2
oauth@1.1.4
oauth2@1.1.3
observe-sequence@1.0.6
ordered-dict@1.0.3
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
routepolicy@1.0.5
service-configuration@1.0.4
session@1.1.0
sha@1.0.3
spacebars@1.0.6
spacebars-compiler@1.0.6
srp@1.0.3
templating@1.1.1
tracker@1.0.7
ui@1.0.6
underscore@1.0.3
url@1.0.4
webapp@1.2.0
webapp-hashing@1.0.3
================================================
FILE: README.md
================================================
# Slack Clone Built in Meteor.js
Code for the scotch.io tutorial by Daniel (danyll.com)

================================================
FILE: client/app.js
================================================
Template.messages.helpers({
messages: Messages.find({})
});
Accounts.ui.config({
passwordSignupFields: 'USERNAME_AND_EMAIL'
});
Template.registerHelper('currentChannel', function () {
return Session.get('channel');
});
Template.registerHelper("timestampToTime", function (timestamp) {
var date = new Date(timestamp);
var hours = date.getHours();
var minutes = "0" + date.getMinutes();
var seconds = "0" + date.getSeconds();
return hours + ':' + minutes.substr(minutes.length-2) + ':' + seconds.substr(seconds.length-2);
});
Template.registerHelper("usernameFromId", function (userId) {
var user = Meteor.users.findOne({_id: userId});
if (typeof user === "undefined") {
return "Anonymous";
}
if (typeof user.services.github !== "undefined") {
return user.services.github.username;
}
return user.username;
});
Template.listings.helpers({
channels: function () {
return Channels.find();
}
});
Template.channel.helpers({
active: function () {
if (Session.get('channel') === this.name) {
return "active";
} else {
return "";
}
}
});
================================================
FILE: client/components/channel.html
================================================
0
#
{{name}}
================================================
FILE: client/components/footer.html
================================================
================================================
FILE: client/components/header.html
================================================
================================================
FILE: client/components/listings.html
================================================
{{#each channels}}
{{> channel name=name}}
{{/each}}
This demo is not created by, affiliated with, or supported by Slack Technologies, Inc.
================================================
FILE: client/components/message.html
================================================
================================================
FILE: client/components/messages.html
================================================
{{#if Template.subscriptionsReady}}
{{#each messages}}
{{> message text=text timestamp=timestamp user=user }}
{{/each}}
{{else}}
Loading…
{{/if}}
================================================
FILE: client/global.css
================================================
/* line 5, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-size: 100%;
vertical-align: baseline;
}
/* line 22, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html {
line-height: 1;
}
/* line 24, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
ol, ul {
list-style: none;
}
/* line 26, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
table {
border-collapse: collapse;
border-spacing: 0;
}
/* line 28, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
/* line 30, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q, blockquote {
quotes: none;
}
/* line 103, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none;
}
/* line 32, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
a img {
border: none;
}
/* line 116, ../../../../../../var/lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
display: block;
}
/* line 6, ../tests/sass/_layout.scss */
* {
box-sizing: border-box;
}
/* line 10, ../tests/sass/_layout.scss */
html {
position: relative;
height: 100%;
font-size: 16px;
font-family: 'Lato', sans-serif;
}
/* line 16, ../tests/sass/_layout.scss */
body {
height: 100%;
width: 100%;
margin: 0;
padding-top: 53px;
padding-bottom: 64px;
}
/* line 23, ../tests/sass/_layout.scss */
.header {
position: fixed;
top: 0;
left: 0;
height: 53px;
width: 100%;
}
/* line 31, ../tests/sass/_layout.scss */
.main {
height: 100%;
}
/* line 35, ../tests/sass/_layout.scss */
.footer {
position: absolute;
left: 0;
bottom: 0;
height: 64px;
width: 100%;
}
/* line 1, ../tests/sass/components/_header.scss */
.team-menu {
position: relative;
width: 220px;
height: 53px;
line-height: 53px;
font-weight: 900;
padding: 0 1rem;
color: #ffffff;
background: #3e313c;
border-bottom: 2px solid #372c36;
float: left;
cursor: pointer;
}
/* line 19, ../tests/sass/components/_header.scss */
.channel-menu_name {
display: inline-block;
padding: 0 .5rem 0 1.5rem;
color: #555459;
font-size: 1.4rem;
font-weight: 900;
line-height: 53px;
cursor: pointer;
}
/* line 29, ../tests/sass/components/_header.scss */
.channel-menu_prefix {
color: #9e9ea6;
padding-right: .1rem;
font-weight: 500;
}
/* line 1, ../tests/sass/components/_main.scss */
.listings {
height: 100%;
width: 220px;
float: left;
color: #ab9ba9;
background-color: #4d394b;
overflow-y: auto;
overflow-x: hidden;
}
/* line 11, ../tests/sass/components/_main.scss */
.message-history {
margin-left: 220px;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
padding: 0 18px 1rem 1.5rem;
}
/* line 4, ../tests/sass/components/_listings.scss */
.listings_channels {
margin: 1rem 0 2rem;
}
/* line 8, ../tests/sass/components/_listings.scss */
.listings_header {
text-align: left;
font-size: .8rem;
line-height: 1.25rem;
margin: 0 1rem .1rem;
text-transform: uppercase;
font-weight: 700;
color: #ab9ba9;
width: 165px;
position: relative;
}
/* line 20, ../tests/sass/components/_listings.scss */
.channel_list {
list-style-type: none;
text-align: left;
color: #ab9ba9;
}
/* line 26, ../tests/sass/components/_listings.scss */
.channel {
height: 24px;
line-height: 24px;
-moz-border-radius-topright: 0.25rem;
-webkit-border-top-right-radius: 0.25rem;
border-top-right-radius: 0.25rem;
-moz-border-radius-bottomright: 0.25rem;
-webkit-border-bottom-right-radius: 0.25rem;
border-bottom-right-radius: 0.25rem;
margin-right: 17px;
color: #ffffff;
padding-left: 1rem;
}
/* line 35, ../tests/sass/components/_listings.scss */
.unread {
color: #ffffff;
background: #eb4d5c;
border-radius: 9px;
padding: 2px 9px;
font-size: .8rem;
line-height: 14px;
font-weight: 700;
vertical-align: baseline;
white-space: nowrap;
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
float: right;
margin-right: 3px;
margin-top: 3px;
}
/* line 51, ../tests/sass/components/_listings.scss */
.channel.active {
background: #4c9689;
}
/* line 55, ../tests/sass/components/_listings.scss */
.channel_prefix {
color: #b2d5c9;
}
/* line 59, ../tests/sass/components/_listings.scss */
.disclaimer {
font-size: 0.8rem;
padding-left: 1rem;
margin-right: 17px;
}
/* line 4, ../tests/sass/components/_message.scss */
.message {
position: relative;
margin-top: .5rem;
padding: .25rem 2rem .1rem 3rem;
min-height: 36px;
}
/* line 11, ../tests/sass/components/_message.scss */
.message_profile-pic {
position: absolute;
left: 0;
display: block;
-moz-border-radius: 0.2rem;
-webkit-border-radius: 0.2rem;
border-radius: 0.2rem;
width: 36px;
height: 36px;
background-image: url("http://i.imgur.com/LikUNLc.png");
background-size: cover;
}
/* line 22, ../tests/sass/components/_message.scss */
.message_username {
font-weight: 900;
padding-right: .25rem;
color: #3d3c40 !important;
margin-left: 0;
font-style: normal;
text-decoration: none;
}
/* line 31, ../tests/sass/components/_message.scss */
.message_timestamp {
text-align: left;
display: inline;
position: relative;
top: 0;
left: 0;
color: #babbbf;
font-size: 12px;
line-height: 1.2rem;
width: 36px;
margin-right: 0;
margin-left: 0;
}
/* line 45, ../tests/sass/components/_message.scss */
.message_content {
color: #8b898f;
font-style: italic;
display: block;
min-height: 1rem;
}
/* line 4, ../tests/sass/components/_user-menu.scss */
.user-menu {
float: left;
width: 220px;
height: 100%;
cursor: pointer;
background: #3e313c;
border-top: 2px solid #372c36;
padding: 7px 0 9px 8px;
height: 4rem;
position: fixed;
bottom: 0;
left: 0;
}
/* line 18, ../tests/sass/components/_user-menu.scss */
.user-menu_profile-pic {
display: inline-block;
float: left;
-moz-border-radius: 0.2rem;
-webkit-border-radius: 0.2rem;
border-radius: 0.2rem;
width: 48px;
height: 48px;
background-image: url("http://i.imgur.com/LikUNLc.png");
background-size: cover;
margin-right: 8px;
}
/* line 29, ../tests/sass/components/_user-menu.scss */
.user-menu_username {
display: block;
color: #ffffff;
font-weight: 900;
line-height: 1.5rem;
margin-top: .2rem;
max-width: 120px;
}
/* line 38, ../tests/sass/components/_user-menu.scss */
.connection_icon {
width: 12px;
height: 12px;
}
/* line 43, ../tests/sass/components/_user-menu.scss */
.connection_status {
color: #ab9ba9;
}
/* line 1, ../tests/sass/components/_input-box.scss */
.input-box {
height: 100%;
margin-left: 220px;
}
/* line 6, ../tests/sass/components/_input-box.scss */
.input-box_text {
font-size: .95rem;
width: 90%;
margin-left: 2%;
margin-bottom: auto;
line-height: 1.2rem;
border: 2px solid #e0e0e0;
-moz-border-radius: 0.2rem;
-webkit-border-radius: 0.2rem;
border-radius: 0.2rem;
-moz-background-clip: padding-box;
-webkit-background-clip: padding-box;
background-clip: padding-box;
color: #3d3c40;
-webkit-appearance: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
outline: 0;
bottom: 0;
min-height: 41px !important;
padding: 9px 5px 9px 8px;
}
.channel_name {
text-decoration: none;
color: inherit;
}
================================================
FILE: client/head.html
================================================
================================================
FILE: client/input.js
================================================
Template.footer.events({
'keypress input': function(e) {
var inputVal = $('.input-box_text').val();
if(!!inputVal) {
var charCode = (typeof e.which == "number") ? e.which : e.keyCode;
if (charCode == 13) {
e.stopPropagation();
Meteor.call('newMessage', {
text: $('.input-box_text').val(),
channel: Session.get('channel')
});
$('.input-box_text').val("");
return false;
}
}
}
});
================================================
FILE: client/room.html
================================================
{{> header}}
{{> loginButtons}}
{{> listings}}
{{> yield}}
{{> footer}}
================================================
FILE: client/routes.js
================================================
Router.configure({
layoutTemplate: 'app'
});
Router.route('/:channel', function () {
Session.set('channel', this.params.channel);
this.render('messages');
});
Router.route('/', function () {
this.redirect('/general');
});
================================================
FILE: client/startup/subscribe.js
================================================
Meteor.subscribe('channels');
Meteor.subscribe('allUsernames');
Template.messages.onCreated(function() {
var self = this;
self.autorun(function() {
self.subscribe('messages', Session.get('channel'), function () {
self.autorun(function() {
Messages.find({channel: Session.get('channel')}).count();
Meteor.setTimeout(function () {
$('.message-history').scrollTop(Number.MAX_VALUE);
}, 100);
});
});
});
});
================================================
FILE: client/stubs.js
================================================
Meteor.methods({
newMessage: function (message) {
message.timestamp = Date.now();
message.user = Meteor.userId();
Messages.insert(message);
}
})
================================================
FILE: lib/collections/channels.js
================================================
Channels = new Mongo.Collection("channels");
================================================
FILE: lib/collections/messages.js
================================================
Messages = new Mongo.Collection("messages");
================================================
FILE: server/accounts.js
================================================
Accounts.config({
sendVerificationEmail: true
});
================================================
FILE: server/mail.js
================================================
Meteor.startup(function () {
smtp = {
username: 'dan@danyll.com',
password: 'y3Z8TQxpxCiYsJJsCwyV0A',
server: 'smtp.mandrillapp.com',
port: 587
};
process.env.MAIL_URL = 'smtp://' + encodeURIComponent(smtp.username) + ':' + encodeURIComponent(smtp.password) + '@' + encodeURIComponent(smtp.server) + ':' + smtp.port;
});
================================================
FILE: server/methods.js
================================================
Meteor.methods({
newMessage: function (message) {
message.timestamp = Date.now();
message.user = Meteor.userId();
Messages.insert(message);
}
})
================================================
FILE: server/publications.js
================================================
Meteor.publish('messages', function (channel) {
return Messages.find({channel: channel});
});
Meteor.publish('channels', function () {
return Channels.find();
});
Meteor.publish("allUsernames", function () {
return Meteor.users.find({}, {fields: {
"username": 1,
"services.github.username": 1
}});
});
================================================
FILE: server/seeder.js
================================================
Meteor.startup(function() {
Meteor.users.remove({});
Accounts.createUser({
username: "scotchio",
email: "scotch@example.com",
password: "dummypassword"
});
Factory.define('message', Messages, {
text: function() {
return Fake.sentence();
},
user: Meteor.users.findOne()._id,
timestamp: Date.now(),
channel: 'general'
});
// Add this if you want to remove all messages before seeding
Messages.remove({});
if (Messages.find({}).count() === 0) {
_(10).times(function(n) {
Factory.create('message');
});
}
Channels.remove({});
Channels.insert({
name: "general"
});
Channels.insert({
name: "random"
});
});