");
+ $input.on("blur.tt", function($e) {
+ var active, isActive, hasActive;
+ active = document.activeElement;
+ isActive = $menu.is(active);
+ hasActive = $menu.has(active).length > 0;
+ if (_.isMsie() && (isActive || hasActive)) {
+ $e.preventDefault();
+ $e.stopImmediatePropagation();
+ _.defer(function() {
+ $input.focus();
+ });
+ }
+ });
+ $menu.on("mousedown.tt", function($e) {
+ $e.preventDefault();
+ });
+ },
+ _onSelectableClicked: function onSelectableClicked(type, $el) {
+ this.select($el);
+ },
+ _onDatasetCleared: function onDatasetCleared() {
+ this._updateHint();
+ },
+ _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
+ this._updateHint();
+ this.eventBus.trigger("render", suggestions, async, dataset);
+ },
+ _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
+ this.eventBus.trigger("asyncrequest", query, dataset);
+ },
+ _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
+ this.eventBus.trigger("asynccancel", query, dataset);
+ },
+ _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
+ this.eventBus.trigger("asyncreceive", query, dataset);
+ },
+ _onFocused: function onFocused() {
+ this._minLengthMet() && this.menu.update(this.input.getQuery());
+ },
+ _onBlurred: function onBlurred() {
+ if (this.input.hasQueryChangedSinceLastFocus()) {
+ this.eventBus.trigger("change", this.input.getQuery());
+ }
+ },
+ _onEnterKeyed: function onEnterKeyed(type, $e) {
+ var $selectable;
+ if ($selectable = this.menu.getActiveSelectable()) {
+ this.select($selectable) && $e.preventDefault();
+ }
+ },
+ _onTabKeyed: function onTabKeyed(type, $e) {
+ var $selectable;
+ if ($selectable = this.menu.getActiveSelectable()) {
+ this.select($selectable) && $e.preventDefault();
+ } else if ($selectable = this.menu.getTopSelectable()) {
+ this.autocomplete($selectable) && $e.preventDefault();
+ }
+ },
+ _onEscKeyed: function onEscKeyed() {
+ this.close();
+ },
+ _onUpKeyed: function onUpKeyed() {
+ this.moveCursor(-1);
+ },
+ _onDownKeyed: function onDownKeyed() {
+ this.moveCursor(+1);
+ },
+ _onLeftKeyed: function onLeftKeyed() {
+ if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
+ this.autocomplete(this.menu.getTopSelectable());
+ }
+ },
+ _onRightKeyed: function onRightKeyed() {
+ if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
+ this.autocomplete(this.menu.getTopSelectable());
+ }
+ },
+ _onQueryChanged: function onQueryChanged(e, query) {
+ this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
+ },
+ _onWhitespaceChanged: function onWhitespaceChanged() {
+ this._updateHint();
+ },
+ _onLangDirChanged: function onLangDirChanged(e, dir) {
+ if (this.dir !== dir) {
+ this.dir = dir;
+ this.menu.setLanguageDirection(dir);
+ }
+ },
+ _openIfActive: function openIfActive() {
+ this.isActive() && this.open();
+ },
+ _minLengthMet: function minLengthMet(query) {
+ query = _.isString(query) ? query : this.input.getQuery() || "";
+ return query.length >= this.minLength;
+ },
+ _updateHint: function updateHint() {
+ var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
+ $selectable = this.menu.getTopSelectable();
+ data = this.menu.getSelectableData($selectable);
+ val = this.input.getInputValue();
+ if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
+ query = Input.normalizeQuery(val);
+ escapedQuery = _.escapeRegExChars(query);
+ frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
+ match = frontMatchRegEx.exec(data.val);
+ match && this.input.setHint(val + match[1]);
+ } else {
+ this.input.clearHint();
+ }
+ },
+ isEnabled: function isEnabled() {
+ return this.enabled;
+ },
+ enable: function enable() {
+ this.enabled = true;
+ },
+ disable: function disable() {
+ this.enabled = false;
+ },
+ isActive: function isActive() {
+ return this.active;
+ },
+ activate: function activate() {
+ if (this.isActive()) {
+ return true;
+ } else if (!this.isEnabled() || this.eventBus.before("active")) {
+ return false;
+ } else {
+ this.active = true;
+ this.eventBus.trigger("active");
+ return true;
+ }
+ },
+ deactivate: function deactivate() {
+ if (!this.isActive()) {
+ return true;
+ } else if (this.eventBus.before("idle")) {
+ return false;
+ } else {
+ this.active = false;
+ this.close();
+ this.eventBus.trigger("idle");
+ return true;
+ }
+ },
+ isOpen: function isOpen() {
+ return this.menu.isOpen();
+ },
+ open: function open() {
+ if (!this.isOpen() && !this.eventBus.before("open")) {
+ this.menu.open();
+ this._updateHint();
+ this.eventBus.trigger("open");
+ }
+ return this.isOpen();
+ },
+ close: function close() {
+ if (this.isOpen() && !this.eventBus.before("close")) {
+ this.menu.close();
+ this.input.clearHint();
+ this.input.resetInputValue();
+ this.eventBus.trigger("close");
+ }
+ return !this.isOpen();
+ },
+ setVal: function setVal(val) {
+ this.input.setQuery(_.toStr(val));
+ },
+ getVal: function getVal() {
+ return this.input.getQuery();
+ },
+ select: function select($selectable) {
+ var data = this.menu.getSelectableData($selectable);
+ if (data && !this.eventBus.before("select", data.obj)) {
+ this.input.setQuery(data.val, true);
+ this.eventBus.trigger("select", data.obj);
+ this.close();
+ return true;
+ }
+ return false;
+ },
+ autocomplete: function autocomplete($selectable) {
+ var query, data, isValid;
+ query = this.input.getQuery();
+ data = this.menu.getSelectableData($selectable);
+ isValid = data && query !== data.val;
+ if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
+ this.input.setQuery(data.val);
+ this.eventBus.trigger("autocomplete", data.obj);
+ return true;
+ }
+ return false;
+ },
+ moveCursor: function moveCursor(delta) {
+ var query, $candidate, data, payload, cancelMove;
+ query = this.input.getQuery();
+ $candidate = this.menu.selectableRelativeToCursor(delta);
+ data = this.menu.getSelectableData($candidate);
+ payload = data ? data.obj : null;
+ cancelMove = this._minLengthMet() && this.menu.update(query);
+ if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
+ this.menu.setCursor($candidate);
+ if (data) {
+ this.input.setInputValue(data.val);
+ } else {
+ this.input.resetInputValue();
+ this._updateHint();
+ }
+ this.eventBus.trigger("cursorchange", payload);
+ return true;
+ }
+ return false;
+ },
+ destroy: function destroy() {
+ this.input.destroy();
+ this.menu.destroy();
+ }
+ });
+ return Typeahead;
+ function c(ctx) {
+ var methods = [].slice.call(arguments, 1);
+ return function() {
+ var args = [].slice.call(arguments);
+ _.each(methods, function(method) {
+ return ctx[method].apply(ctx, args);
+ });
+ };
+ }
+ }();
+ (function() {
+ "use strict";
+ var old, keys, methods;
+ old = $.fn.typeahead;
+ keys = {
+ www: "tt-www",
+ attrs: "tt-attrs",
+ typeahead: "tt-typeahead"
+ };
+ methods = {
+ initialize: function initialize(o, datasets) {
+ var www;
+ datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
+ o = o || {};
+ www = WWW(o.classNames);
+ return this.each(attach);
+ function attach() {
+ var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
+ _.each(datasets, function(d) {
+ d.highlight = !!o.highlight;
+ });
+ $input = $(this);
+ $wrapper = $(www.html.wrapper);
+ $hint = $elOrNull(o.hint);
+ $menu = $elOrNull(o.menu);
+ defaultHint = o.hint !== false && !$hint;
+ defaultMenu = o.menu !== false && !$menu;
+ defaultHint && ($hint = buildHintFromInput($input, www));
+ defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
+ $hint && $hint.val("");
+ $input = prepInput($input, www);
+ if (defaultHint || defaultMenu) {
+ $wrapper.css(www.css.wrapper);
+ $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
+ $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
+ }
+ MenuConstructor = defaultMenu ? DefaultMenu : Menu;
+ eventBus = new EventBus({
+ el: $input
+ });
+ input = new Input({
+ hint: $hint,
+ input: $input
+ }, www);
+ menu = new MenuConstructor({
+ node: $menu,
+ datasets: datasets
+ }, www);
+ typeahead = new Typeahead({
+ input: input,
+ menu: menu,
+ eventBus: eventBus,
+ minLength: o.minLength
+ }, www);
+ $input.data(keys.www, www);
+ $input.data(keys.typeahead, typeahead);
+ }
+ },
+ isEnabled: function isEnabled() {
+ var enabled;
+ ttEach(this.first(), function(t) {
+ enabled = t.isEnabled();
+ });
+ return enabled;
+ },
+ enable: function enable() {
+ ttEach(this, function(t) {
+ t.enable();
+ });
+ return this;
+ },
+ disable: function disable() {
+ ttEach(this, function(t) {
+ t.disable();
+ });
+ return this;
+ },
+ isActive: function isActive() {
+ var active;
+ ttEach(this.first(), function(t) {
+ active = t.isActive();
+ });
+ return active;
+ },
+ activate: function activate() {
+ ttEach(this, function(t) {
+ t.activate();
+ });
+ return this;
+ },
+ deactivate: function deactivate() {
+ ttEach(this, function(t) {
+ t.deactivate();
+ });
+ return this;
+ },
+ isOpen: function isOpen() {
+ var open;
+ ttEach(this.first(), function(t) {
+ open = t.isOpen();
+ });
+ return open;
+ },
+ open: function open() {
+ ttEach(this, function(t) {
+ t.open();
+ });
+ return this;
+ },
+ close: function close() {
+ ttEach(this, function(t) {
+ t.close();
+ });
+ return this;
+ },
+ select: function select(el) {
+ var success = false, $el = $(el);
+ ttEach(this.first(), function(t) {
+ success = t.select($el);
+ });
+ return success;
+ },
+ autocomplete: function autocomplete(el) {
+ var success = false, $el = $(el);
+ ttEach(this.first(), function(t) {
+ success = t.autocomplete($el);
+ });
+ return success;
+ },
+ moveCursor: function moveCursoe(delta) {
+ var success = false;
+ ttEach(this.first(), function(t) {
+ success = t.moveCursor(delta);
+ });
+ return success;
+ },
+ val: function val(newVal) {
+ var query;
+ if (!arguments.length) {
+ ttEach(this.first(), function(t) {
+ query = t.getVal();
+ });
+ return query;
+ } else {
+ ttEach(this, function(t) {
+ t.setVal(newVal);
+ });
+ return this;
+ }
+ },
+ destroy: function destroy() {
+ ttEach(this, function(typeahead, $input) {
+ revert($input);
+ typeahead.destroy();
+ });
+ return this;
+ }
+ };
+ $.fn.typeahead = function(method) {
+ if (methods[method]) {
+ return methods[method].apply(this, [].slice.call(arguments, 1));
+ } else {
+ return methods.initialize.apply(this, arguments);
+ }
+ };
+ $.fn.typeahead.noConflict = function noConflict() {
+ $.fn.typeahead = old;
+ return this;
+ };
+ function ttEach($els, fn) {
+ $els.each(function() {
+ var $input = $(this), typeahead;
+ (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
+ });
+ }
+ function buildHintFromInput($input, www) {
+ return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
+ autocomplete: "off",
+ spellcheck: "false",
+ tabindex: -1
+ });
+ }
+ function prepInput($input, www) {
+ $input.data(keys.attrs, {
+ dir: $input.attr("dir"),
+ autocomplete: $input.attr("autocomplete"),
+ spellcheck: $input.attr("spellcheck"),
+ style: $input.attr("style")
+ });
+ $input.addClass(www.classes.input).attr({
+ autocomplete: "off",
+ spellcheck: false
+ });
+ try {
+ !$input.attr("dir") && $input.attr("dir", "auto");
+ } catch (e) {}
+ return $input;
+ }
+ function getBackgroundStyles($el) {
+ return {
+ backgroundAttachment: $el.css("background-attachment"),
+ backgroundClip: $el.css("background-clip"),
+ backgroundColor: $el.css("background-color"),
+ backgroundImage: $el.css("background-image"),
+ backgroundOrigin: $el.css("background-origin"),
+ backgroundPosition: $el.css("background-position"),
+ backgroundRepeat: $el.css("background-repeat"),
+ backgroundSize: $el.css("background-size")
+ };
+ }
+ function revert($input) {
+ var www, $wrapper;
+ www = $input.data(keys.www);
+ $wrapper = $input.parent().filter(www.selectors.wrapper);
+ _.each($input.data(keys.attrs), function(val, key) {
+ _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
+ });
+ $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
+ if ($wrapper.length) {
+ $input.detach().insertAfter($wrapper);
+ $wrapper.remove();
+ }
+ }
+ function $elOrNull(obj) {
+ var isValid, $el;
+ isValid = _.isJQuery(obj) || _.isElement(obj);
+ $el = isValid ? $(obj).first() : [];
+ return $el.length ? $el : null;
+ }
+ })();
+});
diff --git a/imports/api/ads/ads.js b/imports/api/ads/ads.js
new file mode 100644
index 0000000..2cda6f0
--- /dev/null
+++ b/imports/api/ads/ads.js
@@ -0,0 +1,11 @@
+import { Mongo } from 'meteor/mongo';
+
+const Ads = new Mongo.Collection('ads');
+
+export default Ads;
+
+Ads.allow({
+ insert: () => true,
+ update: () => true,
+ remove: () => true,
+});
diff --git a/imports/api/ads/methods.js b/imports/api/ads/methods.js
new file mode 100644
index 0000000..2d94e8a
--- /dev/null
+++ b/imports/api/ads/methods.js
@@ -0,0 +1,19 @@
+/*import { Meteor } from 'meteor/meteor';*/
+import Ads from './ads';
+
+/*
+Meteor.methods({
+ 'Ads.insert': function (message, imageId, imageURL) {
+ const post = {
+ user: Meteor.user(),
+ createdAt: new Date(),
+ image: imageId,
+ imageurl: imageURL,
+ message,
+ likes: [],
+ comments: [],
+ };
+
+ Ads.insert(post);
+ },
+});*/
diff --git a/imports/api/ads/server/publications.js b/imports/api/ads/server/publications.js
new file mode 100644
index 0000000..2cd599f
--- /dev/null
+++ b/imports/api/ads/server/publications.js
@@ -0,0 +1,6 @@
+import { Meteor } from 'meteor/meteor';
+import Ads from '../ads';
+
+Meteor.publish('Ads.list', function() {
+ return Ads.find({}, {});
+});
diff --git a/imports/api/images/images.js b/imports/api/images/images.js
new file mode 100644
index 0000000..9d0a29e
--- /dev/null
+++ b/imports/api/images/images.js
@@ -0,0 +1,30 @@
+import { Meteor } from 'meteor/meteor';
+import { FilesCollection } from 'meteor/ostrio:files';
+
+const Images = new FilesCollection({
+ debug: true,
+ collectionName: 'Images',
+ allowClientCode: false,
+ storagePath: () => {
+ return `${Meteor.absolutePath}/uploads`;
+ },
+ onBeforeUpload: (file) => {
+ if (file.size > 10485760) {
+ return 'Please upload image, with size equal or less than 10MB.';
+ }
+
+ if (!/png|jpg|jpeg/i.test(file.extension)) {
+ return `${file.extension}'s files are not allowed for upload.`;
+ }
+
+ return true;
+ },
+});
+
+export default Images;
+
+/* Images.allow({
+ insert: () => true,
+ update: () => true,
+ remove: () => true,
+});*/
diff --git a/imports/api/images/methods.js b/imports/api/images/methods.js
new file mode 100644
index 0000000..76a6f97
--- /dev/null
+++ b/imports/api/images/methods.js
@@ -0,0 +1,17 @@
+import { Meteor } from 'meteor/meteor';
+import Images from './images';
+
+Meteor.methods({
+ 'Images.changeAvatar': function changeAvatar(imageId) {
+ if (imageId) {
+ const image = Images.findOne({ _id: imageId });
+ if (image !== undefined) {
+ Meteor.users.update(Meteor.userId(), {
+ $set: {
+ 'profile.avatar': image.link(),
+ },
+ });
+ }
+ }
+ },
+});
diff --git a/imports/api/images/server/publications.js b/imports/api/images/server/publications.js
new file mode 100644
index 0000000..ccdca4a
--- /dev/null
+++ b/imports/api/images/server/publications.js
@@ -0,0 +1,8 @@
+import { Meteor } from 'meteor/meteor';
+import Images from '../images';
+
+Meteor.publish('Images.all', function() {
+ return Images.find({
+ userId: this.userId,
+ }).cursor;
+});
diff --git a/imports/api/posts/methods.js b/imports/api/posts/methods.js
new file mode 100644
index 0000000..92aeaac
--- /dev/null
+++ b/imports/api/posts/methods.js
@@ -0,0 +1,24 @@
+import { Meteor } from 'meteor/meteor';
+import Posts from './posts';
+
+Meteor.methods({
+ 'Posts.insert': function postsInsert(message, imageURL) {
+ const post = {
+ user: Meteor.user(),
+ createdAt: new Date(),
+ imageurl: imageURL,
+ message,
+ likes: [],
+ comments: [],
+ };
+
+ Posts.insert(post);
+ },
+ 'Posts.like': function postsInsert(postId) {
+ Posts.update(postId, {
+ $addToSet: {
+ likes: Meteor.userId(),
+ },
+ });
+ },
+});
diff --git a/imports/api/posts/posts.js b/imports/api/posts/posts.js
new file mode 100644
index 0000000..ef62824
--- /dev/null
+++ b/imports/api/posts/posts.js
@@ -0,0 +1,11 @@
+import { Mongo } from 'meteor/mongo';
+
+const Posts = new Mongo.Collection('posts');
+
+export default Posts;
+
+Posts.allow({
+ insert: () => true,
+ update: () => true,
+ remove: () => true,
+});
diff --git a/imports/api/posts/server/publications.js b/imports/api/posts/server/publications.js
new file mode 100644
index 0000000..a98b3a3
--- /dev/null
+++ b/imports/api/posts/server/publications.js
@@ -0,0 +1,6 @@
+import { Meteor } from 'meteor/meteor';
+import Posts from '../posts';
+
+Meteor.publish('Posts.list', function() {
+ return Posts.find({}, { sort: { createdAt: -1 } });
+});
diff --git a/imports/api/users/methods.js b/imports/api/users/methods.js
new file mode 100644
index 0000000..d73bba7
--- /dev/null
+++ b/imports/api/users/methods.js
@@ -0,0 +1,48 @@
+import { Meteor } from 'meteor/meteor';
+
+Meteor.methods({
+ 'Users.changeEmail': function changeEmail(email) {
+ if (email) {
+ Meteor.users.update(Meteor.userId(), {
+ $set: {
+ 'emails.0.address': email,
+ },
+ });
+ }
+ },
+ 'Users.getDataById': function getDataById(userId) {
+ if (userId) {
+ return Meteor.users.find(
+ {
+ _id: userId,
+ },
+ {
+ fields:
+ {
+ 'profile.firstname': 1,
+ 'profile.lastname': 1,
+ 'profile.fullname': 1,
+ },
+ },
+ ).fetch();
+ }
+
+ return null;
+ },
+});
+
+// getDataById, alternate method to get post user full name using Meteor methods
+// use it in client like this:
+//
+// getUserDataById(userId) {
+// Meteor.call('Users.getDataById', userId, (error, result) => {
+// if (error) {
+// console.log('Error:', error);
+// } else {
+// this.setState({ fullName: result[0].profile.fullname });
+// }
+// });
+//
+// return this.state.fullName;
+// }
+
diff --git a/imports/api/users/server/publications.js b/imports/api/users/server/publications.js
new file mode 100644
index 0000000..6c9cd9a
--- /dev/null
+++ b/imports/api/users/server/publications.js
@@ -0,0 +1,18 @@
+import { Meteor } from 'meteor/meteor';
+
+Meteor.publish('Users.User', (searchField, data) => {
+ return Meteor.users.find(
+ {
+ [searchField]: data,
+ },
+ {
+ fields:
+ {
+ 'profile.firstname': 1,
+ 'profile.lastname': 1,
+ 'profile.fullname': 1,
+ 'profile.avatar': 1,
+ },
+ },
+ );
+});
diff --git a/imports/startup/client/index.js b/imports/startup/client/index.js
new file mode 100644
index 0000000..b0b0f47
--- /dev/null
+++ b/imports/startup/client/index.js
@@ -0,0 +1 @@
+import './routes.js';
diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js
new file mode 100644
index 0000000..a72e607
--- /dev/null
+++ b/imports/startup/client/routes.js
@@ -0,0 +1,54 @@
+import { Meteor } from 'meteor/meteor';
+import React from 'react';
+import { render } from 'react-dom';
+import { Router, Route, browserHistory, IndexRoute } from 'react-router';
+import HomeLayout from '../../ui/layouts/HomeLayout';
+import Layout from '../../ui/layouts/Layout';
+import Sidebar from '../../ui/components/Sidebar';
+import Main from '../../ui/components/Main';
+import Profile from '../../ui/components/Profile';
+import UserHome from '../../ui/components/UserHome';
+import NotFound from '../../ui/pages/NotFound';
+
+const authenticate = (nextState, replace) => {
+ if (!Meteor.loggingIn() && !Meteor.userId()) {
+ replace({
+ pathname: '/',
+ state: { nextPathname: nextState.location.pathname },
+ });
+ }
+};
+
+const checkUser = (nextState, replace) => {
+ if (Meteor.userId()) {
+ replace({
+ pathname: '/dashboard',
+ state: { nextPathname: nextState.location.pathname },
+ });
+ }
+};
+
+const signout = () => {
+ Meteor.logout(() => {
+ browserHistory.push('/');
+ });
+};
+
+Meteor.startup(() => {
+ render(
+
+ {/* Public Routes */}
+
+
+ {/* Private Routes */}
+
+
+
+
+
+
+
+ ,
+ document.getElementById('react-root'),
+ );
+});
diff --git a/imports/startup/server/accounts/email-templates.js b/imports/startup/server/accounts/email-templates.js
new file mode 100644
index 0000000..8fd8f5c
--- /dev/null
+++ b/imports/startup/server/accounts/email-templates.js
@@ -0,0 +1,25 @@
+import { Accounts } from 'meteor/accounts-base';
+
+const name = 'Application Name';
+const email = '
';
+const from = `${name} ${email}`;
+const emailTemplates = Accounts.emailTemplates;
+
+emailTemplates.siteName = name;
+emailTemplates.from = from;
+
+emailTemplates.resetPassword = {
+ subject() {
+ return `[${name}] Reset Your Password`;
+ },
+ text(user, url) {
+ const userEmail = user.emails[0].address;
+ const urlWithoutHash = url.replace('#/', '');
+
+ return `A password reset has been requested for the account related to this
+ address (${userEmail}). To reset the password, visit the following link:
+ \n\n${urlWithoutHash}\n\n If you did not request this reset, please ignore
+ this email. If you feel something is wrong, please contact our support team:
+ ${email}.`;
+ },
+};
diff --git a/imports/startup/server/api.js b/imports/startup/server/api.js
new file mode 100644
index 0000000..21ce15b
--- /dev/null
+++ b/imports/startup/server/api.js
@@ -0,0 +1,8 @@
+import '../../api/ads/methods.js';
+import '../../api/ads/server/publications.js';
+import '../../api/images/methods.js';
+import '../../api/images/server/publications.js';
+import '../../api/posts/methods.js';
+import '../../api/posts/server/publications.js';
+import '../../api/users/methods.js';
+import '../../api/users/server/publications.js';
diff --git a/imports/startup/server/browser-policy.js b/imports/startup/server/browser-policy.js
new file mode 100644
index 0000000..8b97e3b
--- /dev/null
+++ b/imports/startup/server/browser-policy.js
@@ -0,0 +1,3 @@
+import { BrowserPolicy } from 'meteor/browser-policy-common';
+// e.g., BrowserPolicy.content.allowOriginForAll( 's3.amazonaws.com' );
+BrowserPolicy.content.allowFontOrigin("data:");
diff --git a/imports/startup/server/fixtures.js b/imports/startup/server/fixtures.js
new file mode 100644
index 0000000..57713fe
--- /dev/null
+++ b/imports/startup/server/fixtures.js
@@ -0,0 +1,23 @@
+import { Meteor } from 'meteor/meteor';
+import { Roles } from 'meteor/alanning:roles';
+import { Accounts } from 'meteor/accounts-base';
+
+if (!Meteor.isProduction) {
+ const users = [{
+ email: 'admin@admin.com',
+ password: 'password',
+ profile: {
+ name: { first: 'Carl', last: 'Winslow' },
+ },
+ roles: ['admin'],
+ }];
+
+ users.forEach(({ email, password, profile, roles }) => {
+ const userExists = Meteor.users.findOne({ 'emails.address': email });
+
+ if (!userExists) {
+ const userId = Accounts.createUser({ email, password, profile });
+ Roles.addUsersToRoles(userId, roles);
+ }
+ });
+}
diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js
new file mode 100644
index 0000000..b432516
--- /dev/null
+++ b/imports/startup/server/index.js
@@ -0,0 +1,6 @@
+/*
+import './accounts/email-templates';
+import './browser-policy';
+import './fixtures';
+*/
+import './api';
diff --git a/client/components/ad/ad.jsx b/imports/ui/components/Ad.js
similarity index 53%
rename from client/components/ad/ad.jsx
rename to imports/ui/components/Ad.js
index b9c2595..2815aa3 100644
--- a/client/components/ad/ad.jsx
+++ b/imports/ui/components/Ad.js
@@ -1,22 +1,29 @@
-Ad = React.createClass({
- render(){
- var adImage = this.props.ad.image ? 
: '';
+import React, { Component, PropTypes } from 'react';
+
+class Ad extends Component {
+ render() {
+ const adImage = this.props.ad.imageId ? 
: '';
+
return (
-
{this.props.ad.title}
+ {this.props.ad.title}
{adImage}
-
+
{this.props.ad.text}
-
-
- )
+ );
}
-});
\ No newline at end of file
+}
+
+Ad.propTypes = {
+ ad: PropTypes.object.isRequired,
+};
+
+export default Ad;
diff --git a/imports/ui/components/Avatar.js b/imports/ui/components/Avatar.js
new file mode 100644
index 0000000..07b78be
--- /dev/null
+++ b/imports/ui/components/Avatar.js
@@ -0,0 +1,47 @@
+import React, { Component, PropTypes } from 'react';
+import { Link } from 'react-router';
+
+class Avatar extends Component {
+ render() {
+ const {
+ avatar,
+ firstName,
+ lastName,
+ className,
+ wrapLink,
+ } = this.props;
+
+ if (!avatar) {
+ return (
+
+ );
+ }
+
+ const personLink = (`/user/${firstName}${lastName}`).toLowerCase();
+ const avatarImg =
;
+
+ if (wrapLink) {
+ return (
+
+ {avatarImg}
+
+ );
+ }
+
+ return avatarImg;
+ }
+}
+
+Avatar.propTypes = {
+ avatar: PropTypes.string,
+ firstName: PropTypes.string.isRequired,
+ lastName: PropTypes.string.isRequired,
+ className: PropTypes.string,
+ wrapLink: PropTypes.bool,
+};
+
+export default Avatar;
diff --git a/imports/ui/components/FeatureList.js b/imports/ui/components/FeatureList.js
new file mode 100644
index 0000000..7c20ab5
--- /dev/null
+++ b/imports/ui/components/FeatureList.js
@@ -0,0 +1,41 @@
+import React, { Component } from 'react';
+
+class FeatureList extends Component {
+ getFeatures() {
+ const features = [
+ { _id: '1', icon: 'fa fa-imageId fa-2x', bigtext: 'See fotos and updates', littletext: 'from friends in News Feed' },
+ { _id: '2', icon: 'fa fa-share fa-2x', bigtext: 'Share what\'s new', littletext: 'in your life on your timeline' },
+ { _id: '3', icon: 'fa fa-search fa-2x', bigtext: 'Find more', littletext: 'of what you\'re looking for with Fakebook search' },
+ ];
+
+ return features.map((feature) => {
+ return (
+
+
+
+
+ {feature.bigtext}
+ {feature.littletext}
+
+
+
+ );
+ });
+ }
+
+ render() {
+ return (
+
+
+ Connect with friends and the world around you on Fakebook
+
+
+
+ );
+ }
+}
+
+export default FeatureList;
+
diff --git a/imports/ui/components/FullName.js b/imports/ui/components/FullName.js
new file mode 100644
index 0000000..6ebcfa2
--- /dev/null
+++ b/imports/ui/components/FullName.js
@@ -0,0 +1,28 @@
+import React, { Component, PropTypes } from 'react';
+import { Link } from 'react-router';
+
+class FullName extends Component {
+ render() {
+ const {
+ fullName,
+ firstName,
+ lastName,
+ className,
+ } = this.props;
+
+ const personLink = (`/user/${fullName}`).toLowerCase();
+
+ return (
+ {`${firstName} ${lastName}`}
+ );
+ }
+}
+
+FullName.propTypes = {
+ fullName: PropTypes.string.isRequired,
+ firstName: PropTypes.string.isRequired,
+ lastName: PropTypes.string.isRequired,
+ className: PropTypes.string,
+};
+
+export default FullName;
diff --git a/imports/ui/components/Header.js b/imports/ui/components/Header.js
new file mode 100644
index 0000000..7f8b665
--- /dev/null
+++ b/imports/ui/components/Header.js
@@ -0,0 +1,93 @@
+import { Meteor } from 'meteor/meteor';
+import React, { Component } from 'react';
+import { browserHistory } from 'react-router';
+
+class Header extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ message: '',
+ messageClass: 'hidden',
+ };
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ }
+
+ displayError(message) {
+ this.setState({
+ message,
+ messageClass: 'alert alert-danger message',
+ });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+
+ this.setState({
+ message: '',
+ messageClass: 'hidden',
+ });
+
+ const email = this.refs.email.value.trim();
+ const password = this.refs.password.value.trim();
+
+ Meteor.loginWithPassword(email, password, (error) => {
+ if (error) {
+ this.displayError(error.reason);
+ } else {
+ browserHistory.push('/dashboard');
+ }
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default Header;
diff --git a/imports/ui/components/Main.js b/imports/ui/components/Main.js
new file mode 100644
index 0000000..83a3790
--- /dev/null
+++ b/imports/ui/components/Main.js
@@ -0,0 +1,57 @@
+import { Meteor } from 'meteor/meteor';
+import React, { Component, PropTypes } from 'react';
+import { createContainer } from 'meteor/react-meteor-data';
+import StatusForm from './StatusForm';
+import Post from './Post';
+import Ad from './Ad';
+import Posts from '../../api/posts/posts';
+import Ads from '../../api/ads/ads';
+
+class Main extends Component {
+ render() {
+ const adobj = {
+ _id: 1,
+ text: 'My Firts Ad',
+ title: 'Some Company',
+ image: 'http://placehold.it/150x150',
+ };
+
+ const posts = this.props.posts.map((post) => {
+ return ;
+ });
+
+ return (
+
+
+
+
+
+
+ {posts}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+Main.propTypes = {
+ posts: PropTypes.array,
+ ads: PropTypes.array,
+};
+
+export default createContainer(() => {
+ Meteor.subscribe('Posts.list');
+ Meteor.subscribe('Ads.list');
+
+ return {
+ posts: Posts.find({}, { sort: { createdAt: -1 } }).fetch(),
+ ads: Ads.find({}, {}).fetch(),
+ };
+}, Main);
diff --git a/imports/ui/components/NavBar.js b/imports/ui/components/NavBar.js
new file mode 100644
index 0000000..791fc9c
--- /dev/null
+++ b/imports/ui/components/NavBar.js
@@ -0,0 +1,125 @@
+import $ from 'jquery';
+import { Meteor } from 'meteor/meteor';
+import React, { Component, PropTypes } from 'react';
+import { createContainer } from 'meteor/react-meteor-data';
+import { Link, browserHistory } from 'react-router';
+
+class NavBar extends Component {
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ }
+
+ componentDidMount() {
+ // @TODO: Check a fix for typeahead.
+ const users = Meteor.users.find({}, { fields: { profile: 1 } }).fetch();
+ const usernames = users.map((user) => {
+ return user.profile.fullname;
+ });
+
+ $('#typeahead').typeahead({
+ name: 'users',
+ local: usernames,
+ });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+
+ const user = (this.refs.searchText.value).trim();
+
+ if (user !== '') {
+ browserHistory.push(`/user/${user}`);
+ }
+ }
+
+ render() {
+ const {
+ currentUser,
+ ready,
+ } = this.props;
+
+ if (!ready) {
+ return Loading...
;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+NavBar.propTypes = {
+ currentUser: PropTypes.object,
+ ready: PropTypes.bool,
+};
+
+export default createContainer(() => {
+ const currentUser = Meteor.user();
+
+ return {
+ currentUser,
+ ready: !!currentUser,
+ };
+}, NavBar);
diff --git a/imports/ui/components/Post.js b/imports/ui/components/Post.js
new file mode 100644
index 0000000..507e1ef
--- /dev/null
+++ b/imports/ui/components/Post.js
@@ -0,0 +1,154 @@
+import { Meteor } from 'meteor/meteor';
+import React, { Component, PropTypes } from 'react';
+import { createContainer } from 'meteor/react-meteor-data';
+import Avatar from './Avatar';
+import FullName from './FullName';
+
+class Post extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ fullName: '',
+ };
+
+ this.likePost = this.likePost.bind(this);
+ this.renderLikes = this.renderLikes.bind(this);
+ }
+
+ likePost(event) {
+ event.preventDefault();
+
+ const {
+ post,
+ } = this.props;
+
+ Meteor.call('Posts.like', post._id, (error) => {
+ if (error) {
+ console.log(error);
+ }
+ });
+ }
+
+ renderLikes() {
+ const {
+ currentUser,
+ post,
+ } = this.props;
+
+ let likes = '';
+ let likeSub = 0;
+
+ if (post.likes.indexOf(currentUser._id) !== -1) {
+ likes = 'You and';
+ likeSub = 1;
+ }
+
+ switch (post.likes.length - likeSub) {
+ case 0:
+ return likeSub > 0 ? 'You like this' : '';
+ case 1:
+ return likeSub > 0 ? `${likes} 1 other person likes this` : '1 person likes this';
+ default:
+ return `${likes} ${post.likes.length - likeSub} people like this`;
+ }
+ }
+
+ render() {
+ const {
+ ready,
+ post,
+ user,
+ } = this.props;
+
+
+ if (!ready) {
+ return Loading...
;
+ }
+
+ let dimage = '';
+ if (post.imageurl) {
+ dimage = (
+
+
+

+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ made a post
+
+
An hour ago
+
+
+
+
{post.message}
+
+
+
+ {dimage}
+
+
+
+
+
+
+ {this.renderLikes()}
+
+
+ Comments List
+
+
+
+ );
+ }
+}
+
+Post.propTypes = {
+ post: PropTypes.object.isRequired,
+ currentUser: PropTypes.object,
+ user: PropTypes.object,
+ ready: PropTypes.bool,
+};
+
+export default createContainer((props) => {
+ const userhandle = Meteor.subscribe('Users.User', '_id', props.post.user._id);
+ const currentUser = Meteor.user();
+
+ let user = null;
+ if (userhandle.ready()) {
+ user = Meteor.users.findOne({ _id: props.post.user._id });
+ }
+
+ return {
+ currentUser,
+ user,
+ ready: !!currentUser && user !== null,
+ };
+}, Post);
diff --git a/imports/ui/components/Profile.js b/imports/ui/components/Profile.js
new file mode 100644
index 0000000..f700f45
--- /dev/null
+++ b/imports/ui/components/Profile.js
@@ -0,0 +1,153 @@
+import { Meteor } from 'meteor/meteor';
+import React, { Component, PropTypes } from 'react';
+import { createContainer } from 'meteor/react-meteor-data';
+import Images from '../../api/images/images';
+import Avatar from './Avatar';
+
+class Profile extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ className: 'img-circle img-responsive custom-input-file',
+ editMode: false,
+ email: '',
+ };
+
+ this.toggleEdit = this.toggleEdit.bind(this);
+ this.changeEmail = this.changeEmail.bind(this);
+ this.uploadFile = this.uploadFile.bind(this);
+ }
+
+ componentWillReceiveProps(newProps) {
+ if (newProps.ready === true) {
+ this.setState({ email: newProps.currentUser.emails[0].address });
+ }
+ }
+
+ toggleEdit() {
+ this.setState({ editMode: !this.state.editMode });
+ }
+
+ changeEmail(event) {
+ event.preventDefault();
+ const newEmail = this.refs.email.value.trim();
+
+ if (newEmail !== this.state.email) {
+ Meteor.call('Users.changeEmail', newEmail, (error) => {
+ if (error) {
+ console.log(error);
+ }
+ });
+
+ this.setState({ email: newEmail });
+ }
+
+ this.toggleEdit();
+ }
+
+ uploadFile(event) {
+ event.preventDefault();
+
+ if (event.currentTarget.files && event.currentTarget.files[0]) {
+ const file = event.currentTarget.files[0];
+
+ if (file) {
+ const upload = Images.insert({
+ file: event.currentTarget.files[0],
+ streams: 'dynamic',
+ chunkSize: 'dynamic',
+ }, false);
+
+ upload.on('end', (error, result) => {
+ if (error) {
+ console.log('Error during upload:', error);
+ this.setState({ imageId: '', fileName: '' });
+ } else {
+ Meteor.call('Images.changeAvatar', result._id, (errorAvatar) => {
+ if (errorAvatar) {
+ console.log('Error during changeAvatar:', errorAvatar);
+ } else {
+ this.setState({ className: 'img-circle img-responsive custom-input-file updated' });
+ }
+ });
+ }
+ });
+
+ upload.start();
+ }
+ }
+ }
+
+ render() {
+ const {
+ currentUser,
+ ready,
+ } = this.props;
+
+ if (!ready) {
+ return Loading...
;
+ }
+
+ const editMode = ;
+
+ const emailLink = `mailto:${currentUser.emails[0].address}`;
+ const mailBlock = this.state.editMode ? editMode : {this.state.email};
+
+ return (
+
+
+
+
{`${currentUser.profile.firstname} ${currentUser.profile.lastname}`}
+
+
+
+ | Email |
+ {mailBlock} |
+
+
+
+
+
+ );
+ }
+}
+
+Profile.propTypes = {
+ currentUser: PropTypes.object,
+ ready: PropTypes.bool,
+};
+
+export default createContainer(() => {
+ const currentUser = Meteor.user();
+
+ return {
+ currentUser,
+ ready: !!currentUser,
+ };
+}, Profile);
diff --git a/imports/ui/components/Sidebar.js b/imports/ui/components/Sidebar.js
new file mode 100644
index 0000000..87160b1
--- /dev/null
+++ b/imports/ui/components/Sidebar.js
@@ -0,0 +1,43 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router';
+
+class Sidebar extends Component {
+ getLinks() {
+ const links = [
+ { _id: '1', href: '/profile', icon: 'fa fa-user fa-2x', text: 'Profile' },
+ { _id: '2', href: '/dashboard', icon: 'fa fa-rss fa-2x', text: 'News Feed' },
+ { _id: '3', href: '/messages', icon: 'fa fa-comment fa-2x', text: 'Messages' },
+ { _id: '4', href: '/friends', icon: 'fa fa-users fa-2x', text: 'Friends' },
+ ];
+
+ return links.map((link) => {
+ return (
+
+
+
+ {link.text}
+
+
+ );
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default Sidebar;
diff --git a/imports/ui/components/SignUp.js b/imports/ui/components/SignUp.js
new file mode 100644
index 0000000..3f3e5c8
--- /dev/null
+++ b/imports/ui/components/SignUp.js
@@ -0,0 +1,118 @@
+import { Accounts } from 'meteor/accounts-base';
+import React, { Component } from 'react';
+import { browserHistory } from 'react-router';
+
+class SignUp extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ message: '',
+ messageClass: 'hidden',
+ };
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ }
+
+ displayError(message) {
+ this.setState({
+ message,
+ messageClass: 'alert alert-danger registerError',
+ });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+
+ this.setState({
+ message: '',
+ messageClass: 'hidden',
+ });
+
+ const firstname = this.refs.firstName.value.trim();
+ const lastname = this.refs.lastName.value.trim();
+ const email = this.refs.email.value.trim();
+ const password = this.refs.password.value.trim();
+
+ const user = {
+ email,
+ password,
+ profile: {
+ fullname: (`${firstname}${lastname}`).toLowerCase(),
+ firstname,
+ lastname,
+ avatar: 'http://placehold.it/150x150',
+ friends: [],
+ },
+ };
+
+ Accounts.createUser(user, (error) => {
+ if (error) {
+ this.displayError(error.reason);
+ } else {
+ browserHistory.push('/dashboard');
+ }
+ });
+ }
+
+ render() {
+ return (
+
+
+
Sign Up
+
+ It's free and allways will be
+
+
+
+
+ );
+ }
+}
+
+export default SignUp;
diff --git a/imports/ui/components/StatusForm.js b/imports/ui/components/StatusForm.js
new file mode 100644
index 0000000..a18af3c
--- /dev/null
+++ b/imports/ui/components/StatusForm.js
@@ -0,0 +1,126 @@
+import { Meteor } from 'meteor/meteor';
+import React, { Component } from 'react';
+import { createContainer } from 'meteor/react-meteor-data';
+import Images from '../../api/images/images';
+
+class StatusForm extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ imageId: '',
+ fileName: '',
+ };
+
+ this.resetFields = this.resetFields.bind(this);
+ this.submitForm = this.submitForm.bind(this);
+ this.uploadFile = this.uploadFile.bind(this);
+ }
+
+ resetFields() {
+ this.refs.sharing.value = '';
+ this.refs.sharing.focus();
+ }
+
+ submitForm(event) {
+ event.preventDefault();
+ const message = this.refs.sharing.value.trim();
+ const imageId = this.state.imageId;
+ let imageURL = '';
+
+ if (imageId) {
+ const image = Images.findOne({ _id: imageId });
+ if (image) {
+ imageURL = image.link();
+ }
+ } else {
+ imageURL = '';
+ }
+
+ Meteor.call('Posts.insert', message, imageURL, (error) => {
+ if (error) {
+ console.log(error);
+ } else {
+ this.setState({ image: '', fileName: '' });
+ this.resetFields();
+ }
+ });
+ }
+
+ uploadFile(event) {
+ event.preventDefault();
+
+ if (event.currentTarget.files && event.currentTarget.files[0]) {
+ const file = event.currentTarget.files[0];
+
+ if (file) {
+ const upload = Images.insert({
+ file: event.currentTarget.files[0],
+ streams: 'dynamic',
+ chunkSize: 'dynamic',
+ }, false);
+
+ upload.on('end', (error, result) => {
+ if (error) {
+ console.log('Error during upload:', error);
+ this.setState({ imageId: '', fileName: '' });
+ } else {
+ this.setState({ imageId: result._id, fileName: result.name });
+ }
+ });
+
+ upload.start();
+ }
+ }
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default createContainer(() => {
+ Meteor.subscribe('Images.all');
+
+ return {};
+}, StatusForm);
diff --git a/imports/ui/components/UserHome.js b/imports/ui/components/UserHome.js
new file mode 100644
index 0000000..fa5694e
--- /dev/null
+++ b/imports/ui/components/UserHome.js
@@ -0,0 +1,76 @@
+import { Meteor } from 'meteor/meteor';
+import React, { Component, PropTypes } from 'react';
+import { createContainer } from 'meteor/react-meteor-data';
+import Avatar from './Avatar';
+
+class UserHome extends Component {
+ render() {
+ const {
+ ready,
+ user,
+ } = this.props;
+
+ if (!ready && !user) {
+ return Loading...
;
+ }
+
+ let userHeader = '';
+ if (user != null && user.profile.fullname) {
+ userHeader = ;
+ } else {
+ userHeader = 'No User Found';
+ }
+
+ let userFullName = '';
+ if (user != null && user.profile) {
+ userFullName = `${user.profile.firstname} ${user.profile.lastname}`;
+ } else {
+ userFullName = 'No User Found';
+ }
+
+ return (
+
+
+
+
+
{userHeader}
+
+
+
{userFullName}
+
+
+
+
+ );
+ }
+}
+
+UserHome.propTypes = {
+ className: PropTypes.string,
+ currentUser: PropTypes.object,
+ user: PropTypes.object,
+ ready: PropTypes.bool,
+
+};
+
+export default createContainer((props) => {
+ const userhandle = Meteor.subscribe('Users.User', 'profile.fullname', props.params.fullname);
+ const currentUser = Meteor.user();
+
+ let user = null;
+ if (userhandle.ready()) {
+ user = Meteor.users.findOne({ 'profile.fullname': props.params.fullname });
+ }
+
+ return {
+ currentUser,
+ user,
+ ready: !!currentUser && user !== null,
+ };
+}, UserHome);
diff --git a/imports/ui/layouts/HomeLayout.js b/imports/ui/layouts/HomeLayout.js
new file mode 100644
index 0000000..21aae7d
--- /dev/null
+++ b/imports/ui/layouts/HomeLayout.js
@@ -0,0 +1,26 @@
+import React, { Component } from 'react';
+import SignUp from '../components/SignUp';
+import Header from '../components/Header';
+import FeatureList from '../components/FeatureList';
+
+class HomeLayout extends Component {
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default HomeLayout;
diff --git a/client/components/layouts/layout.jsx b/imports/ui/layouts/Layout.js
similarity index 53%
rename from client/components/layouts/layout.jsx
rename to imports/ui/layouts/Layout.js
index a96609e..5f348a3 100644
--- a/client/components/layouts/layout.jsx
+++ b/imports/ui/layouts/Layout.js
@@ -1,15 +1,25 @@
-Layout = React.createClass({
- render(){
+import React, { Component, PropTypes } from 'react';
+import NavBar from '../components/NavBar';
+
+class Layout extends Component {
+ render() {
return (
-
+
{this.props.sidebar}
{this.props.content}
- )
+ );
}
-});
\ No newline at end of file
+}
+
+Layout.propTypes = {
+ sidebar: PropTypes.object,
+ content: PropTypes.object,
+};
+
+export default Layout;
diff --git a/imports/ui/pages/NotFound.js b/imports/ui/pages/NotFound.js
new file mode 100644
index 0000000..fcfb874
--- /dev/null
+++ b/imports/ui/pages/NotFound.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import { Link } from 'react-router';
+
+const NotFound = () => {
+ return (
+
+
+
+
+
Oops!
+
404 Not Found
+
+ Sorry, an error has occured: Requested page not found!
+
+
+
+ Take Me Home
+
+
+ Contact Support
+
+
+
+
+
+
+ );
+};
+
+export default NotFound;
diff --git a/lib/router.jsx b/lib/router.jsx
deleted file mode 100644
index a89e7ae..0000000
--- a/lib/router.jsx
+++ /dev/null
@@ -1,73 +0,0 @@
-publicRoutes = FlowRouter.group({
- name: 'publicroute'
-});
-privateRoutes = FlowRouter.group({
- name: 'privateroute',
- triggersEnter: [function (context, redirect) {
- var route;
- if (!Meteor.userId()) {
- return FlowRouter.go('/');
- }
- }]
-});
-publicRoutes.route('/', {
- name: 'Home',
- action: function () {
- ReactLayout.render(Homelayout, {});
- }
-});
-privateRoutes.route('/dashboard', {
- name: 'Dashboardmessages.html',
- action: function () {
-
- ReactLayout.render(Layout, {
- sidebar: ,
- content:
- })
- }
-});
-privateRoutes.route('/messages', {
- name: 'Messages',
- action: function () {
- ReactLayout.render(Layout, {
- sidebar: ,
- content:
- })
- }
-});
-
-privateRoutes.route('/profile', {
- name: 'Profile',
- action: function () {
- ReactLayout.render(Layout, {
- sidebar: ,
- content:
- })
- }
-});
-publicRoutes.route('/signout', {
- name: 'Signout',
- action: function () {
- Meteor.logout(function () {
- FlowRouter.go('/');
- })
- }
-});
-publicRoutes.route('/user/:fullname', {
- name: 'UserHome',
- action: function (params) {
- ReactLayout.render(Layout, {
- sidebar: ,
- content: params.fullname ? : 'No User Found'
- })
- }
-});
-publicRoutes.route('/friends', {
- name: 'UserHome',
- action: function (params) {
- ReactLayout.render(Layout, {
- sidebar: ,
- content:
- })
- }
-});
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..cec378b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,71 @@
+{
+ "name": "fakebook",
+ "private": true,
+ "scripts": {
+ "start": "meteor run"
+ },
+ "devDependencies": {
+ "eslint": "^3.15.0",
+ "eslint-config-airbnb": "^14.1.0",
+ "eslint-plugin-import": "^2.2.0",
+ "eslint-plugin-jsx-a11y": "^4.0.0",
+ "eslint-plugin-meteor": "^4.0.1",
+ "eslint-plugin-react": "^6.10.0"
+ },
+ "eslintConfig": {
+ "parserOptions": {
+ "ecmaFeatures": {
+ "jsx": true
+ }
+ },
+ "plugins": [
+ "meteor",
+ "react"
+ ],
+ "extends": [
+ "airbnb/base",
+ "plugin:meteor/guide",
+ "plugin:react/recommended"
+ ],
+ "env": {
+ "browser": true
+ },
+ "globals": {
+ "server": false,
+ "browser": false,
+ "expect": false
+ },
+ "rules": {
+ "import/no-unresolved": 0,
+ "import/no-extraneous-dependencies": 0,
+ "import/extensions": 0,
+ "no-underscore-dangle": [
+ "error",
+ {
+ "allow": [
+ "_id",
+ "_ensureIndex",
+ "_verifyEmailToken",
+ "_resetPasswordToken",
+ "_name"
+ ]
+ }
+ ],
+ "indent": [
+ "warn",
+ 4
+ ],
+ "class-methods-use-this": 0
+ }
+ },
+ "dependencies": {
+ "babel-runtime": "^6.23.0",
+ "bcrypt": "^1.0.2",
+ "jquery": "^2.2.4",
+ "meteor-node-stubs": "^0.2.5",
+ "react": "^15.4.2",
+ "react-addons-pure-render-mixin": "^15.4.2",
+ "react-dom": "^15.4.2",
+ "react-router": "^3.0.2"
+ }
+}
diff --git a/packages.json b/packages.json
deleted file mode 100644
index 7a73a41..0000000
--- a/packages.json
+++ /dev/null
@@ -1,2 +0,0 @@
-{
-}
\ No newline at end of file
diff --git a/packages/npm-container/index.js b/packages/npm-container/index.js
deleted file mode 100644
index c3fc862..0000000
--- a/packages/npm-container/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-Meteor.npmRequire = function(moduleName) {
- var module = Npm.require(moduleName);
- return module;
-};
-
-Meteor.require = function(moduleName) {
- console.warn('Meteor.require is deprecated. Please use Meteor.npmRequire instead!');
- return Meteor.npmRequire(moduleName);
-};
\ No newline at end of file
diff --git a/packages/npm-container/package.js b/packages/npm-container/package.js
deleted file mode 100644
index 9fab3ce..0000000
--- a/packages/npm-container/package.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var path = Npm.require('path');
-var fs = Npm.require('fs');
-
-Package.describe({
- summary: 'Contains all your npm dependencies',
- version: '1.2.0',
- name: 'npm-container'
-});
-
-var packagesJsonFile = path.resolve('./packages.json');
-try {
- var fileContent = fs.readFileSync(packagesJsonFile);
- var packages = JSON.parse(fileContent.toString());
- Npm.depends(packages);
-} catch (ex) {
- console.error('ERROR: packages.json parsing error [ ' + ex.message + ' ]');
-}
-
-// Adding the app's packages.json as a used file for this package will get
-// Meteor to watch it and reload this package when it changes
-Package.onUse(function(api) {
- api.addFiles('index.js', 'server');
- if (api.addAssets) {
- api.addAssets('../../packages.json', 'server');
- } else {
- api.addFiles('../../packages.json', 'server', {
- isAsset: true
- });
- }
-});
\ No newline at end of file
diff --git a/public/images/apple-touch-icon-precomposed.png b/public/images/apple-touch-icon-precomposed.png
new file mode 100644
index 0000000..a9d8fdc
Binary files /dev/null and b/public/images/apple-touch-icon-precomposed.png differ
diff --git a/public/images/bkgrd.png b/public/images/bkgrd.png
deleted file mode 100644
index 99702d8..0000000
Binary files a/public/images/bkgrd.png and /dev/null differ
diff --git a/public/images/favicon.png b/public/images/favicon.png
new file mode 100644
index 0000000..f57b7b4
Binary files /dev/null and b/public/images/favicon.png differ
diff --git a/public/images/generic-user-profile.png b/public/images/generic-user-profile.png
new file mode 100644
index 0000000..d7b970d
Binary files /dev/null and b/public/images/generic-user-profile.png differ
diff --git a/public/typeahead.js b/public/typeahead.js
deleted file mode 100644
index 132f134..0000000
--- a/public/typeahead.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*!
- * typeahead.js 0.9.3
- * https://github.com/twitter/typeahead
- * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
- */
-
-!function(a){var b="0.9.3",c={isMsie:function(){var a=/(msie) ([\w.]+)/i.exec(navigator.userAgent);return a?parseInt(a[2],10):!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(a){return"string"==typeof a},isNumber:function(a){return"number"==typeof a},isArray:a.isArray,isFunction:a.isFunction,isObject:a.isPlainObject,isUndefined:function(a){return"undefined"==typeof a},bind:a.proxy,bindAll:function(b){var c;for(var d in b)a.isFunction(c=b[d])&&(b[d]=a.proxy(c,b))},indexOf:function(a,b){for(var c=0;c=j?(clearTimeout(e),e=null,g=i,f=a.apply(c,d)):e||(e=setTimeout(h,j)),f}},tokenizeQuery:function(b){return a.trim(b).toLowerCase().split(/[\s]+/)},tokenizeText:function(b){return a.trim(b).toLowerCase().split(/[\s\-_]+/)},getProtocol:function(){return location.protocol},noop:function(){}},d=function(){var a=/\s+/;return{on:function(b,c){var d;if(!c)return this;for(this._callbacks=this._callbacks||{},b=b.split(a);d=b.shift();)this._callbacks[d]=this._callbacks[d]||[],this._callbacks[d].push(c);return this},trigger:function(b,c){var d,e;if(!this._callbacks)return this;for(b=b.split(a);d=b.shift();)if(e=this._callbacks[d])for(var f=0;fa;a++)(b=f.key(a)).match(this.keyMatcher)&&c.push(b.replace(this.keyMatcher,""));for(a=c.length;a--;)this.remove(c[a]);return this},isExpired:function(a){var d=e(f.getItem(this._ttlKey(a)));return c.isNumber(d)&&b()>d?!0:!1}}:{get:c.noop,set:c.noop,remove:c.noop,clear:c.noop,isExpired:c.noop},c.mixin(a.prototype,g),a}(),g=function(){function a(a){c.bindAll(this),a=a||{},this.sizeLimit=a.sizeLimit||10,this.cache={},this.cachedKeysByAge=[]}return c.mixin(a.prototype,{get:function(a){return this.cache[a]},set:function(a,b){var c;this.cachedKeysByAge.length===this.sizeLimit&&(c=this.cachedKeysByAge.shift(),delete this.cache[c]),this.cache[a]=b,this.cachedKeysByAge.push(a)}}),a}(),h=function(){function b(a){c.bindAll(this),a=c.isString(a)?{url:a}:a,i=i||new g,h=c.isNumber(a.maxParallelRequests)?a.maxParallelRequests:h||6,this.url=a.url,this.wildcard=a.wildcard||"%QUERY",this.filter=a.filter,this.replace=a.replace,this.ajaxSettings={type:"get",cache:a.cache,timeout:a.timeout,dataType:a.dataType||"json",beforeSend:a.beforeSend},this._get=(/^throttle$/i.test(a.rateLimitFn)?c.throttle:c.debounce)(this._get,a.rateLimitWait||300)}function d(){j++}function e(){j--}function f(){return h>j}var h,i,j=0,k={};return c.mixin(b.prototype,{_get:function(a,b){function c(c){var e=d.filter?d.filter(c):c;b&&b(e),i.set(a,c)}var d=this;f()?this._sendRequest(a).done(c):this.onDeckRequestArgs=[].slice.call(arguments,0)},_sendRequest:function(b){function c(){e(),k[b]=null,f.onDeckRequestArgs&&(f._get.apply(f,f.onDeckRequestArgs),f.onDeckRequestArgs=null)}var f=this,g=k[b];return g||(d(),g=k[b]=a.ajax(b,this.ajaxSettings).always(c)),g},get:function(a,b){var d,e,f=this,g=encodeURIComponent(a||"");return b=b||c.noop,d=this.replace?this.replace(this.url,g):this.url.replace(this.wildcard,g),(e=i.get(d))?c.defer(function(){b(f.filter?f.filter(e):e)}):this._get(d,b),!!e}}),b}(),i=function(){function d(b){c.bindAll(this),c.isString(b.template)&&!b.engine&&a.error("no template engine specified"),b.local||b.prefetch||b.remote||a.error("one of local, prefetch, or remote is required"),this.name=b.name||c.getUniqueId(),this.limit=b.limit||5,this.minLength=b.minLength||1,this.header=b.header,this.footer=b.footer,this.valueKey=b.valueKey||"value",this.template=e(b.template,b.engine,this.valueKey),this.local=b.local,this.prefetch=b.prefetch,this.remote=b.remote,this.itemHash={},this.adjacencyList={},this.storage=b.name?new f(b.name):null}function e(a,b,d){var e,f;return c.isFunction(a)?e=a:c.isString(a)?(f=b.compile(a),e=c.bind(f.render,f)):e=function(a){return""+a[d]+"
"},e}var g={thumbprint:"thumbprint",protocol:"protocol",itemHash:"itemHash",adjacencyList:"adjacencyList"};return c.mixin(d.prototype,{_processLocalData:function(a){this._mergeProcessedData(this._processData(a))},_loadPrefetchData:function(d){function e(a){var b=d.filter?d.filter(a):a,e=m._processData(b),f=e.itemHash,h=e.adjacencyList;m.storage&&(m.storage.set(g.itemHash,f,d.ttl),m.storage.set(g.adjacencyList,h,d.ttl),m.storage.set(g.thumbprint,n,d.ttl),m.storage.set(g.protocol,c.getProtocol(),d.ttl)),m._mergeProcessedData(e)}var f,h,i,j,k,l,m=this,n=b+(d.thumbprint||"");return this.storage&&(f=this.storage.get(g.thumbprint),h=this.storage.get(g.protocol),i=this.storage.get(g.itemHash),j=this.storage.get(g.adjacencyList)),k=f!==n||h!==c.getProtocol(),d=c.isString(d)?{url:d}:d,d.ttl=c.isNumber(d.ttl)?d.ttl:864e5,i&&j&&!k?(this._mergeProcessedData({itemHash:i,adjacencyList:j}),l=a.Deferred().resolve()):l=a.getJSON(d.url).done(e),l},_transformDatum:function(a){var b=c.isString(a)?a:a[this.valueKey],d=a.tokens||c.tokenizeText(b),e={value:b,tokens:d};return c.isString(a)?(e.datum={},e.datum[this.valueKey]=a):e.datum=a,e.tokens=c.filter(e.tokens,function(a){return!c.isBlankString(a)}),e.tokens=c.map(e.tokens,function(a){return a.toLowerCase()}),e},_processData:function(a){var b=this,d={},e={};return c.each(a,function(a,f){var g=b._transformDatum(f),h=c.getUniqueId(g.value);d[h]=g,c.each(g.tokens,function(a,b){var d=b.charAt(0),f=e[d]||(e[d]=[h]);!~c.indexOf(f,h)&&f.push(h)})}),{itemHash:d,adjacencyList:e}},_mergeProcessedData:function(a){var b=this;c.mixin(this.itemHash,a.itemHash),c.each(a.adjacencyList,function(a,c){var d=b.adjacencyList[a];b.adjacencyList[a]=d?d.concat(c):c})},_getLocalSuggestions:function(a){var b,d=this,e=[],f=[],g=[];return c.each(a,function(a,b){var d=b.charAt(0);!~c.indexOf(e,d)&&e.push(d)}),c.each(e,function(a,c){var e=d.adjacencyList[c];return e?(f.push(e),(!b||e.length").css({position:"absolute",left:"-9999px",visibility:"hidden",whiteSpace:"nowrap",fontFamily:b.css("font-family"),fontSize:b.css("font-size"),fontStyle:b.css("font-style"),fontVariant:b.css("font-variant"),fontWeight:b.css("font-weight"),wordSpacing:b.css("word-spacing"),letterSpacing:b.css("letter-spacing"),textIndent:b.css("text-indent"),textRendering:b.css("text-rendering"),textTransform:b.css("text-transform")}).insertAfter(b)}function f(a,b){return a=(a||"").replace(/^\s*/g,"").replace(/\s{2,}/g," "),b=(b||"").replace(/^\s*/g,"").replace(/\s{2,}/g," "),a===b}return c.mixin(b.prototype,d,{_handleFocus:function(){this.trigger("focused")},_handleBlur:function(){this.trigger("blured")},_handleSpecialKeyEvent:function(a){var b=this.specialKeyCodeMap[a.which||a.keyCode];b&&this.trigger(b+"Keyed",a)},_compareQueryToInputValue:function(){var a=this.getInputValue(),b=f(this.query,a),c=b?this.query.length!==a.length:!1;c?this.trigger("whitespaceChanged",{value:this.query}):b||this.trigger("queryChanged",{value:this.query=a})},destroy:function(){this.$hint.off(".tt"),this.$input.off(".tt"),this.$hint=this.$input=this.$overflowHelper=null},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(a){this.query=a},getInputValue:function(){return this.$input.val()},setInputValue:function(a,b){this.$input.val(a),!b&&this._compareQueryToInputValue()},getHintValue:function(){return this.$hint.val()},setHintValue:function(a){this.$hint.val(a)},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},isOverflow:function(){return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>this.$input.width()},isCursorAtEnd:function(){var a,b=this.$input.val().length,d=this.$input[0].selectionStart;return c.isNumber(d)?d===b:document.selection?(a=document.selection.createRange(),a.moveStart("character",-b),b===a.text.length):!0}}),b}(),k=function(){function b(b){c.bindAll(this),this.isOpen=!1,this.isEmpty=!0,this.isMouseOverDropdown=!1,this.$menu=a(b.menu).on("mouseenter.tt",this._handleMouseenter).on("mouseleave.tt",this._handleMouseleave).on("click.tt",".tt-suggestion",this._handleSelection).on("mouseover.tt",".tt-suggestion",this._handleMouseover)}function e(a){return a.data("suggestion")}var f={suggestionsList:''},g={suggestionsList:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"}};return c.mixin(b.prototype,d,{_handleMouseenter:function(){this.isMouseOverDropdown=!0},_handleMouseleave:function(){this.isMouseOverDropdown=!1},_handleMouseover:function(b){var c=a(b.currentTarget);this._getSuggestions().removeClass("tt-is-under-cursor"),c.addClass("tt-is-under-cursor")},_handleSelection:function(b){var c=a(b.currentTarget);this.trigger("suggestionSelected",e(c))},_show:function(){this.$menu.css("display","block")},_hide:function(){this.$menu.hide()},_moveCursor:function(a){var b,c,d,f;if(this.isVisible()){if(b=this._getSuggestions(),c=b.filter(".tt-is-under-cursor"),c.removeClass("tt-is-under-cursor"),d=b.index(c)+a,d=(d+1)%(b.length+1)-1,-1===d)return this.trigger("cursorRemoved"),void 0;-1>d&&(d=b.length-1),f=b.eq(d).addClass("tt-is-under-cursor"),this._ensureVisibility(f),this.trigger("cursorMoved",e(f))}},_getSuggestions:function(){return this.$menu.find(".tt-suggestions > .tt-suggestion")},_ensureVisibility:function(a){var b=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),c=this.$menu.scrollTop(),d=a.position().top,e=d+a.outerHeight(!0);0>d?this.$menu.scrollTop(c+d):e>b&&this.$menu.scrollTop(c+(e-b))},destroy:function(){this.$menu.off(".tt"),this.$menu=null},isVisible:function(){return this.isOpen&&!this.isEmpty},closeUnlessMouseIsOverDropdown:function(){this.isMouseOverDropdown||this.close()},close:function(){this.isOpen&&(this.isOpen=!1,this.isMouseOverDropdown=!1,this._hide(),this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor"),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,!this.isEmpty&&this._show(),this.trigger("opened"))},setLanguageDirection:function(a){var b={left:"0",right:"auto"},c={left:"auto",right:" 0"};"ltr"===a?this.$menu.css(b):this.$menu.css(c)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getSuggestionUnderCursor:function(){var a=this._getSuggestions().filter(".tt-is-under-cursor").first();return a.length>0?e(a):null},getFirstSuggestion:function(){var a=this._getSuggestions().first();return a.length>0?e(a):null},renderSuggestions:function(b,d){var e,h,i,j,k,l="tt-dataset-"+b.name,m='%body
',n=this.$menu.find("."+l);0===n.length&&(h=a(f.suggestionsList).css(g.suggestionsList),n=a("").addClass(l).append(b.header).append(h).append(b.footer).appendTo(this.$menu)),d.length>0?(this.isEmpty=!1,this.isOpen&&this._show(),i=document.createElement("div"),j=document.createDocumentFragment(),c.each(d,function(c,d){d.dataset=b.name,e=b.template(d.datum),i.innerHTML=m.replace("%body",e),k=a(i.firstChild).css(g.suggestion).data("suggestion",d),k.children().each(function(){a(this).css(g.suggestionChild)}),j.appendChild(k[0])}),n.show().find(".tt-suggestions").html(j)):this.clearSuggestions(b.name),this.trigger("suggestionsRendered")},clearSuggestions:function(a){var b=a?this.$menu.find(".tt-dataset-"+a):this.$menu.find('[class^="tt-dataset-"]'),c=b.find(".tt-suggestions");b.hide(),c.empty(),0===this._getSuggestions().length&&(this.isEmpty=!0,this._hide())}}),b}(),l=function(){function b(a){var b,d,f;c.bindAll(this),this.$node=e(a.input),this.datasets=a.datasets,this.dir=null,this.eventBus=a.eventBus,b=this.$node.find(".tt-dropdown-menu"),d=this.$node.find(".tt-query"),f=this.$node.find(".tt-hint"),this.dropdownView=new k({menu:b}).on("suggestionSelected",this._handleSelection).on("cursorMoved",this._clearHint).on("cursorMoved",this._setInputValueToSuggestionUnderCursor).on("cursorRemoved",this._setInputValueToQuery).on("cursorRemoved",this._updateHint).on("suggestionsRendered",this._updateHint).on("opened",this._updateHint).on("closed",this._clearHint).on("opened closed",this._propagateEvent),this.inputView=new j({input:d,hint:f}).on("focused",this._openDropdown).on("blured",this._closeDropdown).on("blured",this._setInputValueToQuery).on("enterKeyed tabKeyed",this._handleSelection).on("queryChanged",this._clearHint).on("queryChanged",this._clearSuggestions).on("queryChanged",this._getSuggestions).on("whitespaceChanged",this._updateHint).on("queryChanged whitespaceChanged",this._openDropdown).on("queryChanged whitespaceChanged",this._setLanguageDirection).on("escKeyed",this._closeDropdown).on("escKeyed",this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed",this._managePreventDefault).on("upKeyed downKeyed",this._moveDropdownCursor).on("upKeyed downKeyed",this._openDropdown).on("tabKeyed leftKeyed rightKeyed",this._autocomplete)}function e(b){var c=a(g.wrapper),d=a(g.dropdown),e=a(b),f=a(g.hint);c=c.css(h.wrapper),d=d.css(h.dropdown),f.css(h.hint).css({backgroundAttachment:e.css("background-attachment"),backgroundClip:e.css("background-clip"),backgroundColor:e.css("background-color"),backgroundImage:e.css("background-image"),backgroundOrigin:e.css("background-origin"),backgroundPosition:e.css("background-position"),backgroundRepeat:e.css("background-repeat"),backgroundSize:e.css("background-size")}),e.data("ttAttrs",{dir:e.attr("dir"),autocomplete:e.attr("autocomplete"),spellcheck:e.attr("spellcheck"),style:e.attr("style")}),e.addClass("tt-query").attr({autocomplete:"off",spellcheck:!1}).css(h.query);try{!e.attr("dir")&&e.attr("dir","auto")}catch(i){}return e.wrap(c).parent().prepend(f).append(d)}function f(a){var b=a.find(".tt-query");c.each(b.data("ttAttrs"),function(a,d){c.isUndefined(d)?b.removeAttr(a):b.attr(a,d)}),b.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter(a),a.remove()}var g={wrapper:'',hint:'',dropdown:''},h={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none"},query:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"}};return c.isMsie()&&c.mixin(h.query,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),c.isMsie()&&c.isMsie()<=7&&(c.mixin(h.wrapper,{display:"inline",zoom:"1"}),c.mixin(h.query,{marginTop:"-1px"})),c.mixin(b.prototype,d,{_managePreventDefault:function(a){var b,c,d=a.data,e=!1;switch(a.type){case"tabKeyed":b=this.inputView.getHintValue(),c=this.inputView.getInputValue(),e=b&&b!==c;break;case"upKeyed":case"downKeyed":e=!d.shiftKey&&!d.ctrlKey&&!d.metaKey}e&&d.preventDefault()},_setLanguageDirection:function(){var a=this.inputView.getLanguageDirection();a!==this.dir&&(this.dir=a,this.$node.css("direction",a),this.dropdownView.setLanguageDirection(a))},_updateHint:function(){var a,b,d,e,f,g=this.dropdownView.getFirstSuggestion(),h=g?g.value:null,i=this.dropdownView.isVisible(),j=this.inputView.isOverflow();h&&i&&!j&&(a=this.inputView.getInputValue(),b=a.replace(/\s{2,}/g," ").replace(/^\s+/g,""),d=c.escapeRegExChars(b),e=new RegExp("^(?:"+d+")(.*$)","i"),f=e.exec(h),this.inputView.setHintValue(a+(f?f[1]:"")))},_clearHint:function(){this.inputView.setHintValue("")},_clearSuggestions:function(){this.dropdownView.clearSuggestions()},_setInputValueToQuery:function(){this.inputView.setInputValue(this.inputView.getQuery())},_setInputValueToSuggestionUnderCursor:function(a){var b=a.data;this.inputView.setInputValue(b.value,!0)},_openDropdown:function(){this.dropdownView.open()},_closeDropdown:function(a){this.dropdownView["blured"===a.type?"closeUnlessMouseIsOverDropdown":"close"]()},_moveDropdownCursor:function(a){var b=a.data;b.shiftKey||b.ctrlKey||b.metaKey||this.dropdownView["upKeyed"===a.type?"moveCursorUp":"moveCursorDown"]()},_handleSelection:function(a){var b="suggestionSelected"===a.type,d=b?a.data:this.dropdownView.getSuggestionUnderCursor();d&&(this.inputView.setInputValue(d.value),b?this.inputView.focus():a.data.preventDefault(),b&&c.isMsie()?c.defer(this.dropdownView.close):this.dropdownView.close(),this.eventBus.trigger("selected",d.datum,d.dataset))},_getSuggestions:function(){var a=this,b=this.inputView.getQuery();c.isBlankString(b)||c.each(this.datasets,function(c,d){d.getSuggestions(b,function(c){b===a.inputView.getQuery()&&a.dropdownView.renderSuggestions(d,c)})})},_autocomplete:function(a){var b,c,d,e,f;("rightKeyed"!==a.type&&"leftKeyed"!==a.type||(b=this.inputView.isCursorAtEnd(),c="ltr"===this.inputView.getLanguageDirection()?"leftKeyed"===a.type:"rightKeyed"===a.type,b&&!c))&&(d=this.inputView.getQuery(),e=this.inputView.getHintValue(),""!==e&&d!==e&&(f=this.dropdownView.getFirstSuggestion(),this.inputView.setInputValue(f.value),this.eventBus.trigger("autocompleted",f.datum,f.dataset)))},_propagateEvent:function(a){this.eventBus.trigger(a.type)},destroy:function(){this.inputView.destroy(),this.dropdownView.destroy(),f(this.$node),this.$node=null},setQuery:function(a){this.inputView.setQuery(a),this.inputView.setInputValue(a),this._clearHint(),this._clearSuggestions(),this._getSuggestions()}}),b}();!function(){var b,d={},f="ttView";b={initialize:function(b){function g(){var b,d=a(this),g=new e({el:d});b=c.map(h,function(a){return a.initialize()}),d.data(f,new l({input:d,eventBus:g=new e({el:d}),datasets:h})),a.when.apply(a,b).always(function(){c.defer(function(){g.trigger("initialized")})})}var h;return b=c.isArray(b)?b:[b],0===b.length&&a.error("no datasets provided"),h=c.map(b,function(a){var b=d[a.name]?d[a.name]:new i(a);return a.name&&(d[a.name]=b),b}),this.each(g)},destroy:function(){function b(){var b=a(this),c=b.data(f);c&&(c.destroy(),b.removeData(f))}return this.each(b)},setQuery:function(b){function c(){var c=a(this).data(f);c&&c.setQuery(b)}return this.each(c)}},jQuery.fn.typeahead=function(a){return b[a]?b[a].apply(this,[].slice.call(arguments,1)):b.initialize.apply(this,arguments)}}()}(window.jQuery);
-
-
-
-
-
-$('#typeahead').typeahead({
- name: 'example',
- local: [
- 'Salt Lake City',
- 'Provo',
- 'Ogden',
- 'Bountiful',
- 'Orem',
- 'Centerville',
- 'St. George',
- 'Cedar City',
- 'Hurricane',
- ]
-});
diff --git a/server/main.js b/server/main.js
new file mode 100644
index 0000000..a88fcc8
--- /dev/null
+++ b/server/main.js
@@ -0,0 +1 @@
+import '../imports/startup/server';
diff --git a/server/publications/ads.js b/server/publications/ads.js
deleted file mode 100644
index b49b18c..0000000
--- a/server/publications/ads.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.publish('adlist',function(){
- return DBAds.find();
-});
\ No newline at end of file
diff --git a/server/publications/comments.js b/server/publications/comments.js
deleted file mode 100644
index 2f55aff..0000000
--- a/server/publications/comments.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.publish('comments',function(postid){
- return Comments.find({post:postid},{sort:{createdOn:-1}});
-});
\ No newline at end of file
diff --git a/server/publications/images.js b/server/publications/images.js
deleted file mode 100644
index 2e8bb67..0000000
--- a/server/publications/images.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.publish('imagelist',function(){
- return Images.find();
-});
\ No newline at end of file
diff --git a/server/publications/messages.js b/server/publications/messages.js
deleted file mode 100644
index 424d1ca..0000000
--- a/server/publications/messages.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.publish('messageList',function(){
- return DBMessage.find();
-});
\ No newline at end of file
diff --git a/server/publications/posts.js b/server/publications/posts.js
deleted file mode 100644
index 2d41fa4..0000000
--- a/server/publications/posts.js
+++ /dev/null
@@ -1,4 +0,0 @@
-Meteor.publish('postlist',function(friends,limit){
- return Posts.find({'user._id': { $in: friends }},
- {sort:{createdAt:-1},limit:limit});
-});
\ No newline at end of file
diff --git a/server/publications/users.js b/server/publications/users.js
deleted file mode 100644
index 10b744e..0000000
--- a/server/publications/users.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Meteor.publish('userlist',function(){
- return Meteor.users.find({},{fields:{profile:1,emails:1,_id:1}});
-});
\ No newline at end of file
diff --git a/server/server.js b/server/server.js
deleted file mode 100644
index b084e29..0000000
--- a/server/server.js
+++ /dev/null
@@ -1,108 +0,0 @@
-Meteor.startup(function () {
- if (DBFeature.find().fetch().length === 0) {
- var features = [
- {
- icon: "fa fa-image fa-2x",
- bigtext: "See photos and updates",
- littletext: 'from friends in News Feed'
- },
- {
- icon: "fa fa-share fa-2x",
- bigtext: "Share what\'s new",
- littletext: 'in your life on your Timeline'
- },
- {
- icon: "fa fa-search fa-2x",
- bigtext: "Find more",
- littletext: 'of what you\'re looking for with Fakebook search'
- }
- ];
-
- _.each(features, function (featureData) {
- DBFeature.insert(featureData);
- });
- }
- if (DBAds.find().fetch().length === 0) {
- DBAds.insert({title: 'First Advertisement', text: 'This is on sale now.'});
- }
- Meteor.methods({
- 'Posts.insert': function (message, imageurl) {
- var post = {
- user: Meteor.user(),
- createdAt: new Date(),
- imageurl: imageurl,
- message: message,
- likes: [],
- comments: []
- };
- Posts.insert(post);
- },
- 'Post.remove':function(id){
- Posts.remove(id);
- },
- 'changeEmail':function(email){
- Meteor.users.update(this.userId,{$set:{'emails.0.address':email}});
- },
- 'addComment': function (message, post) {
- var user = this.userId;
- var date = new Date();
- var comment = {message: message, post: post._id, user: user, createdOn: date};
- Comments.insert(comment)
- },
- 'changeAvatar': function (user, fileid) {
- var file = 'http://placehold.it/150x150';
- if (fileid) {
- file = Images.findOne({_id: fileid});
- }
- var data = file._id;
-
- Meteor.users.update(this.userId, {$set: {'profile.avatar': data}});
- },
- 'sendMessage':function(person,subject,message){
- var to = Meteor.users.findOne({_id: person});
- var from = Meteor.users.findOne({_id: this.userId});
- var msg = {
- to:to,
- fromuser:from._id,
- title:subject,
- message:message,
- createdOn:new Date()
- };
- console.log(msg);
- if (person == this.userId) {
- throw new Meteor.Error("You can not send yourself a message.")
- }
- DBMessage.insert(msg);
- },
- 'askFriend': function (friendid, message) {
-
- var from = Meteor.users.findOne({_id: this.userId});
- var to = Meteor.users.findOne({_id: friendid});
- var message = {
- to: to,
- fromuser: from._id,
- title: from.profile.firstname + ' ' + from.profile.lastname + ' wants to be your friend.',
- message: message
- };
- console.log(friendid, this.userId);
- if (friendid == this.userId) {
- throw new Meteor.Error("You can not friend yourself.")
- }
- DBMessage.insert(message);
- },
- 'confirmFriend': function (message) {
- console.log(message.to._id, message.fromuser);
- Meteor.users.update(message.to._id, {$addToSet: {'profile.friends': message.fromuser}});
- Meteor.users.update(message.fromuser, {$addToSet: {'profile.friends': message.to._id}});
- DBMessage.remove(message._id);
- },
- 'removeFriend': function (userid, friendid) {
-
- },
- 'likePost': function (userid, postid) {
- console.log(userid, postid);
- Posts.update(postid, {$addToSet: {likes: this.userId}});
- }
-
- })
-});
diff --git a/uploads/.gitkeep b/uploads/.gitkeep
new file mode 100644
index 0000000..e69de29