From 06f4b34b8670d6dcebfd7b000dd2921ca778dfae Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Wed, 25 Jun 2014 00:22:50 -0400 Subject: yt, vimeo, video api --- public/assets/javascripts/ui/site/LayoutsModal.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'public/assets/javascripts/ui/site') diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 46ed634..d474aa7 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -28,7 +28,7 @@ var LayoutsIndex = View.extend({ var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({ el: ".mediaDrawer.projects", - action: "/api/projects", + action: "/api/project", events: { "click .templates span": 'toggleActive', @@ -65,7 +65,7 @@ var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({ var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({ el: ".mediaDrawer.layouts", - action: "/api/layouts", + action: "/api/layout", events: { "click .templates span": 'toggleActive', @@ -93,7 +93,7 @@ var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({ var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({ el: ".mediaDrawer.newProject", - action: "/api/layouts", + action: "/api/layout", events: { "click .templates span": 'toggleActive', -- cgit v1.2.3-70-g09d2 From 221a14315b09946db2485036bbf4a80295dc4889 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 2 Jul 2014 16:22:51 -0400 Subject: password reset / username dupe stuff from PH --- .../assets/javascripts/ui/site/PasswordForgot.js | 26 ++ public/assets/javascripts/ui/site/PasswordReset.js | 25 ++ public/assets/javascripts/ui/site/UsernameTaken.js | 21 ++ public/assets/stylesheets/app.css | 1 - server/index.js | 8 + server/lib/auth.js | 201 ------------- server/lib/auth/index.js | 331 +++++++++++++++++++++ server/lib/auth/mail.js | 67 +++++ server/lib/auth/views.js | 33 ++ server/lib/middleware.js | 1 + server/lib/schemas/User.js | 33 +- server/lib/upload.js | 4 +- server/lib/util.js | 6 +- views/controls/editor/media-editor.ejs | 30 ++ views/controls/editor/settings.ejs | 4 +- views/mail/password.html.ejs | 25 ++ views/mail/password.text.ejs | 11 + views/mail/welcome.html.ejs | 17 ++ views/mail/welcome.text.ejs | 4 + views/partials/scripts.ejs | 3 + views/partials/sign-in.ejs | 75 +++++ 21 files changed, 712 insertions(+), 214 deletions(-) create mode 100644 public/assets/javascripts/ui/site/PasswordForgot.js create mode 100644 public/assets/javascripts/ui/site/PasswordReset.js create mode 100644 public/assets/javascripts/ui/site/UsernameTaken.js delete mode 100644 server/lib/auth.js create mode 100644 server/lib/auth/index.js create mode 100644 server/lib/auth/mail.js create mode 100644 server/lib/auth/views.js create mode 100644 views/controls/editor/media-editor.ejs create mode 100644 views/mail/password.html.ejs create mode 100644 views/mail/password.text.ejs create mode 100644 views/mail/welcome.html.ejs create mode 100644 views/mail/welcome.text.ejs (limited to 'public/assets/javascripts/ui/site') diff --git a/public/assets/javascripts/ui/site/PasswordForgot.js b/public/assets/javascripts/ui/site/PasswordForgot.js new file mode 100644 index 0000000..6ac23c0 --- /dev/null +++ b/public/assets/javascripts/ui/site/PasswordForgot.js @@ -0,0 +1,26 @@ +var PasswordForgot = ModalFormView.extend({ + el: ".mediaDrawer.passwordForgot", + action: "/auth/passwordForgot", + + validate: function(){ + var errors = [] + + var email = this.$("#emailInput").val() + + if (! email.length) { + errors.push("Please enter your email address"); + } + if (email.indexOf("@") === -1) { + errors.push("Sorry, that is not a valid email address"); + } + + return errors + }, + + success: function(res){ + AlertModal.alert("Check your email, you should receive further instructions momentarily.", function(e){ + window.location.href = "/" + }) + }, + +}) diff --git a/public/assets/javascripts/ui/site/PasswordReset.js b/public/assets/javascripts/ui/site/PasswordReset.js new file mode 100644 index 0000000..77e8684 --- /dev/null +++ b/public/assets/javascripts/ui/site/PasswordReset.js @@ -0,0 +1,25 @@ +var PasswordReset = ModalFormView.extend({ + el: ".mediaDrawer.passwordReset", + action: "/auth/password", + + validate: function(){ + var errors = [] + + var pw1 = this.$("#passwordInput1").val() + var pw2 = this.$("#passwordInput2").val() + + if (! pw1.length) { + errors.push("Please enter a password"); + } + if (pw1 !== pw2) { + errors.push("Passwords don't match"); + } + + return errors + }, + + success: function(res){ + window.location.href = "/profile" + } + +}) diff --git a/public/assets/javascripts/ui/site/UsernameTaken.js b/public/assets/javascripts/ui/site/UsernameTaken.js new file mode 100644 index 0000000..fc651e3 --- /dev/null +++ b/public/assets/javascripts/ui/site/UsernameTaken.js @@ -0,0 +1,21 @@ +var UsernameTaken = ModalFormView.extend({ + el: ".mediaDrawer.usernameTaken", + action: "/auth/usernameTaken", + + validate: function(){ + var errors = [] + + var username = this.$("#usernameInput").val() + + if (! username.length) { + errors.push("Please enter a username"); + } + + return errors + }, + + success: function(res){ + window.location.href = "/profile" + } + +}) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index a2b5d8c..9c80987 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1274,7 +1274,6 @@ button:hover { form { max-width: 440px; margin: 0 auto; - } form div { float:right; diff --git a/server/index.js b/server/index.js index b008131..bb242ee 100644 --- a/server/index.js +++ b/server/index.js @@ -61,6 +61,7 @@ site.setup = function(){ app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); + app.enable('trust proxy') app.get('env') === 'development' && app.use(express.errorHandler()); // Essential middleware @@ -90,6 +91,13 @@ site.route = function () { app.get('/auth/twitter/callback', auth.loggedIn('twitter')); app.get('/auth/facebook', auth.login('facebook')); app.get('/auth/facebook/callback', auth.loggedIn('facebook')); + app.get('/auth/usernameTaken', auth.views.usernameTaken); + app.post('/auth/usernameTaken', auth.usernameFixed); + app.get('/auth/password', auth.views.resetPassword); + app.post('/auth/password', auth.resetPassword); + app.post('/auth/passwordForgot', auth.forgotPassword); + + app.get('/profile', views.profile) app.get('/profile/edit', views.profile) app.get('/profile/:name', views.profile) diff --git a/server/lib/auth.js b/server/lib/auth.js deleted file mode 100644 index 018c9ad..0000000 --- a/server/lib/auth.js +++ /dev/null @@ -1,201 +0,0 @@ -/* jshint node: true */ - -var passport = require('passport'), - FacebookStrategy = require('passport-facebook').Strategy, - TwitterStrategy = require('passport-twitter').Strategy, - LocalStrategy = require('passport-local').Strategy, - passportSocketIo = require("passport.socketio"), - cookieParser = require('express').cookieParser, - crypto = require('crypto'), - _ = require('lodash'), - util = require('./util'), - config = require('../../config.json'), - User = require('./schemas/User'); - -var auth = { - - init: function () { - passport.serializeUser(auth.serializeUser); - passport.deserializeUser(auth.deserializeUser); - - passport.use(new LocalStrategy(auth.verifyLocalUser)) - - passport.use(new TwitterStrategy({ - consumerKey: process.env.VVALLS_TWITTER_KEY || '0L5blfBIapqhpons8bCXdIoGM', - consumerSecret: process.env.VVALLS_TWITTER_SECRET || '5EKW7m7inoODqYSKbp7cadBKFp1FghBl4MBDoXNcUjKtodZfuP', - callbackURL: 'http://' + config.host + '/auth/twitter/callback' - }, auth.insertTwitterUser)); - - passport.use(new FacebookStrategy({ - clientID: process.env.VVALLS_FACEBOOK_KEY || '719828821410310', - clientSecret: process.env.VVALLS_FACEBOOK_SECRET || 'f9aba78e08f37f621eadb88b1409d48c', - callbackURL: 'http://' + config.host + '/auth/facebook/callback', - enableProof: false, - }, auth.insertFacebookUser)); - }, - - initSockets: function (io, express, SessionStore) { - io.set('authorization', passportSocketIo.authorize({ - cookieParser: cookieParser, - passport: passport, - key: 'vvalls.sid', // the name of the cookie where express/connect stores its session_id - secret: 'flibbertigibbet', // the session_secret to parse the cookie - store: SessionStore, // we NEED to use a sessionstore. no memorystore please - success: auth.socketSuccess, - fail: auth.socketFail, - })); - }, - - socketSuccess: function (data, accept) { - // console.error('successful connection to socket.io'); - accept(null, true); - }, - - socketFail: function (data, message, error, accept){ - if (error) { - throw new Error(message); - } - // console.log(data) - console.error('failed connection to socket.io:', message); - - // We use this callback to log all of our failed connections. - accept(null, false); - }, - - // technically these return the login middleware - login: function (strategy) { - return passport.authenticate(strategy); - }, - - loggedIn: function (strategy) { - return passport.authenticate(strategy, { - successReturnToOrRedirect: '/', - failureRedirect: '/login' - }); - }, - - loggedInLocal: function (req, res, next) { - passport.authenticate("local", function(err, user, info){ - if (err) { - return res.json({ error: err }); - } - if (! user) { - return info ? res.json(info) : res.redirect("/login"); - } - req.logIn(user, function(err) { - if (err) { return next(err); } - return res.json({ status: "OK" }) - }); - })(req, res, next); - }, - - logout: function (req, res) { - req.logout(); - res.redirect('/'); - }, - - serializeUser: function (user, done) { - done(null, user._id); - }, - - deserializeUser: function (id, done) { - User.findOne({ _id: id }, "_id displayName username photo isStaff", function (err, user) { - done(err, user); - }); - }, - - signup: function (req, res){ - var username = util.trim(req.body.username) - var password = req.body.password - var email = util.trim(req.body.email) - - var shasum = crypto.createHash('sha1') - shasum.update(password) - password = shasum.digest('hex'); - - User.findOne({ username: username }, "_id username", function (err, user) { - if (user) { - res.json({ error: { errors: { username: { message: "Username has been taken" } } } }) - return - } - var data = { - username: username, - displayName: username, - password: password, - email: email, - created_ip: util.ip2num(req.connection.remoteAddress), - last_ip: util.ip2num(req.connection.remoteAddress), - created_at: new Date () - } - new User(data).save(function(err, user){ - if (err || ! data) { return res.json({ error: err }) } - - req.login(user, function(){ - res.json({ status: "OK", payload: user }) - }) - }) - }) - }, - - verifyLocalUser: function (username, password, done) { - User.findOne({ username: username }, function(err, user){ - if (err) { return done(err); } - if (!user) { - return done(null, false, { error: { errors: { username: { message: 'Incorrect username.' } }}}) - } - if (! user.validPassword(password)) { - return done(null, false, { error: { errors: { password: { message: 'Incorrect password.' } }}}) - } - return done(null, user); - }); - }, - - insertTwitterUser: function (accessToken, refreshToken, profile, done) { - process.nextTick(function () { - var userData = { - twitter_id: profile.id, - username: profile.username, - displayName: profile.displayName, - photo: profile.photos[0].value, - twitterName: profile.username, - }; - - User.findOne({twitter_id: profile.id}, function(err, data){ - if (! err && data) { - return done(err, data); - } - new User(userData).save(function(err, data){ - if (err) { console.error(err) } - return done(err, data) - }) - }); - - }); - }, - - insertFacebookUser: function (accessToken, refreshToken, profile, done) { - process.nextTick(function () { - var userData = { - facebook_id: profile.id, - username: profile.username || profile.displayName.toLowerCase().replace(/ /g,'-'), - displayName: profile.displayName, - photo: "http://graph.facebook.com/" + profile.id + "/picture?type=large", - facebookUrl: profile.username ? "https://facebook.com/" + profile.username : "" - }; - - User.findOne({facebook_id: profile.id}, function(err, data){ - if (! err && data) { - return done(err, data); - } - new User(userData).save(function(err, data){ - if (err) { console.error(err) } - return done(err, data) - }) - }); - - }); - }, - -} - -module.exports = auth diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js new file mode 100644 index 0000000..99af9b5 --- /dev/null +++ b/server/lib/auth/index.js @@ -0,0 +1,331 @@ +/* jshint node: true */ + +var passport = require('passport'), + FacebookStrategy = require('passport-facebook').Strategy, + TwitterStrategy = require('passport-twitter').Strategy, + LocalStrategy = require('passport-local').Strategy, + passportSocketIo = require("passport.socketio"), + cookieParser = require('express').cookieParser, + crypto = require('crypto'), + express = require('express'), + _ = require('lodash'), + mongoose = require('mongoose'), + util = require('../util'), + config = require('../../../config.json'), + User = require('../schemas/User'); + +var auth = { + views: require('./views'), + mail: require('./mail'), + + init: function () { + passport.serializeUser(auth.serializeUser); + passport.deserializeUser(auth.deserializeUser); + + passport.use(new LocalStrategy(auth.verifyLocalUser)) + + passport.use(new TwitterStrategy({ + consumerKey: process.env.VVALLS_TWITTER_KEY || 'brI5VqBak5yrhCcxU56lj5L3v', + consumerSecret: process.env.VVALLS_TWITTER_SECRET || 'ThzaEVWUgkmfzqOs3qcrdonGzgDBjDHTVzPkfY0wFJxjUH6JWZ', + callbackURL: 'http://' + config.host + '/auth/twitter/callback' + }, auth.insertTwitterUser)); + + /* + passport.use(new FacebookStrategy({ + clientID: process.env.VVALLS_FACEBOOK_KEY || '719828821410310', + clientSecret: process.env.VVALLS_FACEBOOK_SECRET || 'f9aba78e08f37f621eadb88b1409d48c', + callbackURL: 'http://' + config.host + '/auth/facebook/callback', + enableProof: false, + }, auth.insertFacebookUser)); + */ + auth.mail.init() + }, + + initSockets: function (io, SessionStore) { + io.set('authorization', passportSocketIo.authorize({ + cookieParser: express.cookieParser, + passport: passport, + key: 'vvalls.sid', // the name of the cookie where express/connect stores its session_id + secret: 'flibbertigibbet', // the session_secret to parse the cookie + store: SessionStore, // we NEED to use a sessionstore. no memorystore please + success: auth.socketSuccess, + fail: auth.socketFail, + })); + }, + + socketSuccess: function (data, accept) { + // console.error('successful connection to socket.io'); + accept(null, true); + }, + + socketFail: function (data, message, error, accept){ + if (error) { + throw new Error(message); + } + // console.log(data) + console.error('failed connection to socket.io:', message); + + // We use this callback to log all of our failed connections. + accept(null, false); + }, + + // technically these return the login middleware + login: function (strategy) { + return passport.authenticate(strategy); + }, + + loggedIn: function (strategy) { + return function (req, res, next) { + console.log("attempting to use", strategy) + + passport.authenticate(strategy, function(err, user, info){ + if (err) { + return next(err); + } + if (! user) { + req.session.userData = info + return res.redirect('/auth/usernameTaken'); + } + if (! user.created_ip) { + user.created_ip = util.ip2num( req.ip ) + } + user.last_ip = util.ip2num( req.ip ) + user.save(function(err, data){ if (err) console.err('error setting ip for user') }) + + req.logIn(user, function(err) { + if (err) { return next(err); } + var returnTo = req.session.returnTo + delete req.session.returnTo + return res.redirect( returnTo || "/profile" ); + }); + })(req, res, next); + } + }, + + loggedInLocal: function (req, res, next) { + passport.authenticate("local", function(err, user, info){ + if (err) { + return res.json({ error: err }); + } + if (! user) { + return info ? res.json(info) : res.redirect("/login"); + } + + user.last_ip = util.ip2num( req.ip ) + user.save(function(err, data){ if (err) console.err('error setting ip for user') }) + + req.logIn(user, function(err) { + if (err) { return next(err); } + var returnTo = req.session.returnTo + delete req.session.returnTo + return res.json({ status: "OK", returnTo: returnTo || "/profile" }) + }); + })(req, res, next); + }, + + logout: function (req, res) { + req.logout(); + res.redirect('/'); + }, + + serializeUser: function (user, done) { + done(null, user._id); + }, + + deserializeUser: function (id, done) { + try { + var _id = mongoose.Types.ObjectId(id) + User.findOne({ _id: _id }, "_id displayName username photo isStaff", function (err, user) { + done(err, user); + }); + } + catch (e) { + User.findOne({ twitter_id: id }, "_id displayName username photo isStaff", function (err, user) { + done(err, user); + }); + } + }, + + signup: function (req, res){ + var username = util.trim(req.body.username) + var password = req.body.password + var email = util.trim(req.body.email) + + var shasum = crypto.createHash('sha1') + shasum.update(password) + password = shasum.digest('hex'); + + User.findByUsername(username, function (err, user) { + if (user) { + res.json({ error: { errors: { username: { message: "Username has been taken" } } } }) + return + } + + User.findByEmail(email, function (err, user) { + if (user) { + res.json({ error: { errors: { username: { message: "Email has already been used" } } } }) + return + } + var data = { + username: username, + displayName: username, + password: password, + email: email, + created_ip: util.ip2num( req.ip ), + last_ip: util.ip2num( req.ip ), + created_at: new Date () + } + new User(data).save(function(err, user){ + if (err || ! data) { return res.json({ error: err }) } + req.login(user, function(){ + auth.mail.welcome(user, function(){ + res.json({ status: "OK", payload: user }) + }) + }) + }) + }) + }) + }, + + verifyLocalUser: function (username, password, done) { + User.findByUsername(username, function(err, user){ + if (err) { return done(err); } + if (! user) { + return done(null, false, { error: { errors: { username: { message: 'No such username.' } }}}) + } + if (! user.validPassword(password)) { + return done(null, false, { error: { errors: { password: { message: 'Incorrect password.' } }}}) + } + return done(null, user); + }); + }, + + insertTwitterUser: function (accessToken, refreshToken, profile, done) { + process.nextTick(function () { + var userData = { + twitter_id: profile.id, + username: profile.username, + displayName: profile.displayName, + photo: profile.photos[0].value, + twitterName: profile.username, + }; + User.findOne({twitter_id: profile.id}, function(err, data){ + if (! err && data) { + return done(err, data); + } + User.findByUsername(profile.username, function(err, data){ + if (data) { + return done(null, false, userData) + } + new User(userData).save(function(err, data){ + if (err) { + console.error(err) + } + return done(err, data) + }) + }) + }); + + }); + }, + + insertFacebookUser: function (accessToken, refreshToken, profile, done) { + process.nextTick(function () { + var userData = { + facebook_id: profile.id, + username: profile.username || profile.displayName.toLowerCase().replace(/ /g,'-'), + displayName: profile.displayName, + photo: "http://graph.facebook.com/" + profile.id + "/picture?type=large", + facebookUrl: profile.username ? "https://facebook.com/" + profile.username : "" + }; + + User.findOne({twitter_id: profile.id}, function(err, data){ + if (! err && data) { + return done(err, data); + } + User.findByUsername(profile.username, function(err, data){ + if (data) { + return done(null, false, userData) + } + new User(userData).save(function(err, data){ + if (err) { + console.error(err) + } + return done(err, data) + }) + }) + }); + + }); + }, + + usernameFixed: function (req, res) { + + var userData = req.session.userData + if (! userData) { + return res.redirect("/") + } + if (req.isAuthenticated()) { + delete req.session.userData + return res.redirect("/") + } + + var username = util.sanitize(req.body.username) + + User.findByUsername(username, function(err, doc){ + if (err || doc) { + res.json({ error: { errors: { username: { message: "Username has been taken" } } } }) + return + } + userData.username = username + + new User(userData).save(function(err, user){ + req.logIn(user, function(err) { + if (err) { return res.json(err); } + var returnTo = req.session.returnTo + delete req.session.returnTo + return res.json({ status: "OK", returnTo: returnTo || "/profile" }) + }); + }) + }) + }, + + forgotPassword: function (req, res) { + User.findByEmail(req.body.email, function(err, user){ + if (err || ! user) { + res.json({ error: { errors: { email: { message: "That email address was not found." } } } }) + return + } + User.resetPasswordNonce(user, function(err){ + auth.mail.forgotPassword(user, function(){ + res.json({ success: 'OK' }) + }) + }) + }) + }, + + resetPassword: function (req, res) { + var password = req.body.password + + var shasum = crypto.createHash('sha1') + shasum.update(password) + password = shasum.digest('hex'); + + User.findOne({ passwordNonce: req.body.nonce }, function (err, user){ + if (err || ! user) { + res.json({ error: { errors: { email: { message: "That reset token has already been used." } } } }) + return + } + user.password = password + user.passwordNonce = "" + user.save(function(){ + req.login(user, function(){ + res.json({ status: "OK", payload: user }) + }) + }) + }) + }, + +} + +module.exports = auth diff --git a/server/lib/auth/mail.js b/server/lib/auth/mail.js new file mode 100644 index 0000000..a4abccd --- /dev/null +++ b/server/lib/auth/mail.js @@ -0,0 +1,67 @@ + +var email = require("emailjs"), + ejs = require("ejs"), + fs = require("fs"), + util = require("../util"); + +var mail = { + + from: 'Vvalls ', + templates: {}, + + init: function(){ + var names = ["welcome","password"].forEach(function(name){ + mail.templates[name] = {}; + var types = ["text","html"].forEach(function(type){ + fs.readFile("views/mail/" + name + "." + type + ".ejs", function(err, data){ + mail.templates[name][type] = ejs.compile(data.toString()) + }) + }) + }) + }, + + connect: function(){ + var server = email.server.connect({ + user: process.env.OKFOCUS_EMAIL_USERNAME, + password: process.env.OKFOCUS_EMAIL_PASSWORD, + host: "smtp.sendgrid.net", + ssl: true + }) + return server + }, + + send: function(msg, cb){ + var server = mail.connect() + server.send(msg, cb) + }, + + welcome: function(user, cb){ + var message = { + text: mail.templates.welcome.text(user), + from: mail.from, + to: user.email, + subject: "Welcome to Vvalls", + attachment: [ + { data: mail.templates.welcome.html(user), alternative: true }, + ] + }; + mail.send(message, cb) + console.log("sent welcome email to", user.email) + }, + + forgotPassword: function(user, cb){ + var message = { + text: mail.templates.password.text(user), + from: mail.from, + to: user.email, + subject: "Recover your password", + attachment: [ + { data: mail.templates.password.html(user), alternative: true }, + ] + } + mail.send(message, cb) + console.log("sent password email to", user.email) + }, +} + +module.exports = mail diff --git a/server/lib/auth/views.js b/server/lib/auth/views.js new file mode 100644 index 0000000..591b06a --- /dev/null +++ b/server/lib/auth/views.js @@ -0,0 +1,33 @@ + +var util = require('../util'), + User = require("../schemas/User"); + + +var views = {} + +views.usernameTaken = function (req, res) { + var userData = req.session.userData + if (! userData) { + return res.redirect("/") + } + if (req.isAuthenticated()) { + delete req.session.userData + return res.redirect("/") + } + res.render("modal", { opt: { username: util.sanitize(userData.username) } }) +} + +views.resetPassword = function (req, res) { + var nonce = util.sanitize(req.query.nonce) + if (! nonce.length) { + return res.redirect("/") + } + User.findOne({ passwordNonce: nonce }, function (err, user){ + if (err || ! user) { + return res.redirect("/") + } + res.render("reset-password", { username: user.username, nonce: user.passwordNonce }) + }) +} + +module.exports = views diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 0bc3f7a..aec54ad 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -39,6 +39,7 @@ var middleware = { res.locals.user = req.user || {} res.locals.config = config res.locals.profile = null + res.locals.opt = {} next() }, diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 77e2e02..b64f8fc 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -41,10 +41,8 @@ var UserSchema = new mongoose.Schema({ }, "{PATH} is not an acceptable name"] }, email: { type: String, default: "" }, - emailVerified: { - type: Boolean, - default: false, - }, + emailVerified: { type: Boolean, default: false, }, + emailOptout: { type: Boolean, default: false, }, password: { type: String, validate: [function (val) { @@ -52,6 +50,11 @@ var UserSchema = new mongoose.Schema({ return true }, "{PATH} is not an acceptable password"] }, + passwordNonce: { + type: String, + default: "", + }, + location: { type: String, default: "" }, photo: { type: String, default: "" }, bio: { type: String, default: "" }, @@ -72,6 +75,26 @@ UserSchema.methods.validPassword = function (pw) { shasum.update(pw) return this.password === shasum.digest('hex'); } - +UserSchema.statics.findByUsername = function (username, cb) { + this.findOne({ username: new RegExp("^" + username + "$", "i") }, cb) +} +UserSchema.statics.findByEmail = function (email, cb) { + email = util.escapeRegExp(email) + this.findOne({ email: new RegExp("^" + email + "$", "i") }, cb) +} +UserSchema.statics.findByIP = function (ip, cb) { + ip = util.ip2num(ip) + this.findOne({ $or: [{ created_ip: ip }, { last_ip: ip }] }, cb) +} +UserSchema.statics.resetPasswordNonce = function(user, cb){ + crypto.pseudoRandomBytes(256, function (err, buf){ + var shasum = crypto.createHash('sha1') + shasum.update(buf) + user.passwordNonce = shasum.digest('hex') + user.save(function(err, doc){ + cb() + }) + }) +} module.exports = exports = mongoose.model('user', UserSchema); exports.schema = UserSchema; diff --git a/server/lib/upload.js b/server/lib/upload.js index 0f6c624..e206f7c 100644 --- a/server/lib/upload.js +++ b/server/lib/upload.js @@ -60,7 +60,9 @@ module.exports.put = function (key, file, opt) { }, function(err, s3res) { if (err || s3res.statusCode !== 200) { console.error(err); - s3res.resume() + if (s3res && s3res.resume) { + s3res.resume() + } return; } diff --git a/server/lib/util.js b/server/lib/util.js index aaa8274..6604abe 100644 --- a/server/lib/util.js +++ b/server/lib/util.js @@ -16,18 +16,18 @@ util.trim = function (s){ return (s || "").replace(whitespaceHead,"").replace(wh util.slugify = function (s){ return (s || "").toLowerCase().replace(whitespace,"-").replace(nonAlphanumerics, '-').replace(consecutiveDashes,"-") } - util.sanitize = function (s){ return (s || "").replace(entities, "") } - util.capitalize = function (s) { return (s || "").split(" ").map(util.capitalizeWord).join(" "); } - util.capitalizeWord = function (s) { return s.charAt(0).toUpperCase() + s.slice(1); } +util.escapeRegExp: function (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} util.cleanQuery = function (query) { diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs new file mode 100644 index 0000000..93405fc --- /dev/null +++ b/views/controls/editor/media-editor.ejs @@ -0,0 +1,30 @@ +
+ + + +
+ +
+ +
+ +
+ +
+
+ + + + +
+
+ +
+ +
+ +
diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index a7d6213..867d5f3 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -16,9 +16,7 @@
-
- -
+
diff --git a/views/mail/password.html.ejs b/views/mail/password.html.ejs new file mode 100644 index 0000000..f266488 --- /dev/null +++ b/views/mail/password.html.ejs @@ -0,0 +1,25 @@ + + + +

+ Hey there, +

+ +

+ We received a request to reset the password associated with this email address. +

+ +

+ Click the link below to make a new password: +

+ +

+ http://vvalls.com/auth/password?nonce=[[- passwordNonce ]] +

+ +

+ If this was requested in error, please disregard this message. +

+ + + diff --git a/views/mail/password.text.ejs b/views/mail/password.text.ejs new file mode 100644 index 0000000..67e4b60 --- /dev/null +++ b/views/mail/password.text.ejs @@ -0,0 +1,11 @@ + +Hey there, + +We received a request to reset the password associated with this email address. + +Click the link below to make a new password: + +http://vvalls.com/auth/password?nonce=[[- passwordNonce ]] + +If this was requested in error, please disregard this message. + diff --git a/views/mail/welcome.html.ejs b/views/mail/welcome.html.ejs new file mode 100644 index 0000000..8b7194b --- /dev/null +++ b/views/mail/welcome.html.ejs @@ -0,0 +1,17 @@ + + + +

+ +

+ +

+ Welcome to Vvalls, [[- username ]] +

+ +

+ www.vvalls.com +

+ + + diff --git a/views/mail/welcome.text.ejs b/views/mail/welcome.text.ejs new file mode 100644 index 0000000..cab9c15 --- /dev/null +++ b/views/mail/welcome.text.ejs @@ -0,0 +1,4 @@ + +Welcome to Vvalls, [[- username ]] + +http://www.posthang.com diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 80be29f..9f0c2f2 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -65,6 +65,9 @@ + + + diff --git a/views/partials/sign-in.ejs b/views/partials/sign-in.ejs index 3341aec..11b930f 100644 --- a/views/partials/sign-in.ejs +++ b/views/partials/sign-in.ejs @@ -74,4 +74,79 @@
+
+
+
+
  • + Forgot your password? Enter the email address you used to sign up + and we can reset it for you. +
  • +
  • + +
    + +
    +
  • +
  • + +
  • +
    +
    There was a problem with your submission:
    +
    +
    +
    +
    +
    + +
    +
    +
    + + Please reset your password. +

    +
  • + +
    + +
    +
  • +
  • + +
    + +
    +
  • +
  • + +
  • +
    +
    +
    +
    +
    +
    + +
    +
    +
    + We're sorry, the username [[- username ]] is already being used. +

    + Please choose another username. +

    +
  • + +
    + +
    +
  • +
  • + +
  • +
    +
    +
    +
    +
    +
    + [[ } ]] -- cgit v1.2.3-70-g09d2 From 544ee1236d188f1d24654817481abcf8d078facd Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 2 Jul 2014 17:37:13 -0400 Subject: password reset email; also sends email --- package.json | 3 ++- .../assets/javascripts/mx/primitives/mx.youtube.js | 2 +- public/assets/javascripts/ui/_router.js | 21 +++++++++++++++++++++ public/assets/javascripts/ui/site/PasswordForgot.js | 2 +- public/assets/javascripts/ui/site/PasswordReset.js | 6 ++++++ public/assets/javascripts/ui/site/UsernameTaken.js | 6 ++++++ public/assets/stylesheets/app.css | 4 +++- server/index.js | 4 ++-- server/lib/auth/views.js | 2 +- server/lib/util.js | 2 +- views/modal.ejs | 1 + views/partials/sign-in.ejs | 12 ++++++++---- 12 files changed, 53 insertions(+), 12 deletions(-) (limited to 'public/assets/javascripts/ui/site') diff --git a/package.json b/package.json index 95af2ab..ca45bff 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "html-entities": "~1.0.10", "multer": "~0.1.0", "body-parser": "1.3.0", - "marked": "~0.3.2" + "marked": "~0.3.2", + "emailjs": "~0.3.6" }, "devDependencies": { "grunt": "~0.4.1", diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js index 3662d7b..b1d3dfb 100644 --- a/public/assets/javascripts/mx/primitives/mx.youtube.js +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -120,5 +120,5 @@ MX.Youtube = MX.Object3D.extend({ }) window.onYouTubePlayerAPIReady = function(){ - console.log("youtube ready") + // console.log("youtube ready") } diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 6d41d5b..fdeafd5 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -5,6 +5,7 @@ var SiteRouter = Router.extend({ events: { "click [data-role='show-signup-modal']": 'signup', "click [data-role='show-signin-modal']": 'signin', + "click [data-role='forgot-password']": 'passwordForgot', "click [data-role='new-project-modal']": 'newProject', "click [data-role='edit-project-modal']": 'editProject', "click [data-role='edit-profile-modal']": 'editProfile', @@ -18,6 +19,11 @@ var SiteRouter = Router.extend({ routes: { "/login": 'signin', "/signup": 'signup', + + "/auth/usernameTaken": 'usernameTaken', + "/auth/password": 'passwordReset', + "/auth/forgotPassword": 'passwordForgot', + "/profile": 'profile', "/profile/edit": 'editProfile', "/about/:name/edit": 'editDocument', @@ -40,6 +46,7 @@ var SiteRouter = Router.extend({ this.newProjectModal = new NewProjectModal() this.editProjectModal = new EditProjectModal() this.editProfileModal = new EditProfileModal() + this.passwordForgotModal = new PasswordForgot() this.documentModal = new DocumentModal() this.route() @@ -122,6 +129,20 @@ var SiteRouter = Router.extend({ this.signInModal.load() }, + usernameTaken: function(e){ + this.usernameTakenModal = new UsernameTaken () + this.usernameTakenModal.load() + }, + passwordForgot: function(e){ + e && e.preventDefault() + window.history.pushState(null, document.title, "/auth/forgotPassword") + this.passwordForgotModal.load() + }, + passwordReset: function(e){ + this.passwordResetModal = new PasswordReset () + this.passwordResetModal.load() + }, + profile: function(e){ var classes = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', diff --git a/public/assets/javascripts/ui/site/PasswordForgot.js b/public/assets/javascripts/ui/site/PasswordForgot.js index 6ac23c0..ecbfc07 100644 --- a/public/assets/javascripts/ui/site/PasswordForgot.js +++ b/public/assets/javascripts/ui/site/PasswordForgot.js @@ -1,6 +1,6 @@ var PasswordForgot = ModalFormView.extend({ el: ".mediaDrawer.passwordForgot", - action: "/auth/passwordForgot", + action: "/auth/forgotPassword", validate: function(){ var errors = [] diff --git a/public/assets/javascripts/ui/site/PasswordReset.js b/public/assets/javascripts/ui/site/PasswordReset.js index 77e8684..9b87d37 100644 --- a/public/assets/javascripts/ui/site/PasswordReset.js +++ b/public/assets/javascripts/ui/site/PasswordReset.js @@ -2,6 +2,12 @@ var PasswordReset = ModalFormView.extend({ el: ".mediaDrawer.passwordReset", action: "/auth/password", + load: function(){ + var opt = JSON.parse( $("#opt").html() ) + this.$("[name=nonce]").val( opt.nonce ) + this.__super__.load.call(this) + }, + validate: function(){ var errors = [] diff --git a/public/assets/javascripts/ui/site/UsernameTaken.js b/public/assets/javascripts/ui/site/UsernameTaken.js index fc651e3..fc9f50a 100644 --- a/public/assets/javascripts/ui/site/UsernameTaken.js +++ b/public/assets/javascripts/ui/site/UsernameTaken.js @@ -2,6 +2,12 @@ var UsernameTaken = ModalFormView.extend({ el: ".mediaDrawer.usernameTaken", action: "/auth/usernameTaken", + load: function(){ + var opt = JSON.parse( $("#opt").html() ) + this.$("#usernameThatIsTaken").html( opt.username ) + this.__super__.load.call(this) + }, + validate: function(){ var errors = [] diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 9c80987..937e5c4 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -729,8 +729,10 @@ h5 { -webkit-transform:translateY(0%); transform:translateY(0%); } +.mediaDrawer.table, .mediaDrawer.error, .mediaDrawer.signin, .mediaDrawer.signup, -.mediaDrawer.alert, .mediaDrawer.confirm, .mediaDrawer.error, +.mediaDrawer.alert, .mediaDrawer.confirm, +.mediaDrawer.passwordForgot, .mediaDrawer.passwordReset, .mediaDrawer.usernameTaken, .mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject { display:table; } diff --git a/server/index.js b/server/index.js index 4b628e4..1db7e04 100644 --- a/server/index.js +++ b/server/index.js @@ -92,8 +92,8 @@ site.route = function () { app.post('/auth/usernameTaken', auth.usernameFixed); app.get('/auth/password', auth.views.resetPassword); app.post('/auth/password', auth.resetPassword); - app.post('/auth/passwordForgot', auth.forgotPassword); - + app.get('/auth/forgotPassword', views.modal); + app.post('/auth/forgotPassword', auth.forgotPassword); app.get('/profile', views.profile) app.get('/profile/edit', views.profile) diff --git a/server/lib/auth/views.js b/server/lib/auth/views.js index 591b06a..cd31248 100644 --- a/server/lib/auth/views.js +++ b/server/lib/auth/views.js @@ -26,7 +26,7 @@ views.resetPassword = function (req, res) { if (err || ! user) { return res.redirect("/") } - res.render("reset-password", { username: user.username, nonce: user.passwordNonce }) + res.render("modal", { opt: { username: user.username, nonce: user.passwordNonce } }) }) } diff --git a/server/lib/util.js b/server/lib/util.js index 6604abe..87e2d54 100644 --- a/server/lib/util.js +++ b/server/lib/util.js @@ -25,7 +25,7 @@ util.capitalize = function (s) { util.capitalizeWord = function (s) { return s.charAt(0).toUpperCase() + s.slice(1); } -util.escapeRegExp: function (s) { +util.escapeRegExp = function (s) { return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") } diff --git a/views/modal.ejs b/views/modal.ejs index 4550aff..6ed3fa1 100644 --- a/views/modal.ejs +++ b/views/modal.ejs @@ -19,5 +19,6 @@ [[ include partials/scripts ]] + diff --git a/views/partials/sign-in.ejs b/views/partials/sign-in.ejs index 11b930f..3f05fff 100644 --- a/views/partials/sign-in.ejs +++ b/views/partials/sign-in.ejs @@ -27,7 +27,8 @@


    - Make a new account + Make a new account
    + Forgot your password? @@ -74,9 +75,11 @@ -
    +
    + X
    +
  • Forgot your password? Enter the email address you used to sign up and we can reset it for you. @@ -98,9 +101,10 @@
  • -
    +
    + Please reset your password.

    @@ -129,7 +133,7 @@
    - We're sorry, the username [[- username ]] is already being used. + We're sorry, the username is already being used.

    Please choose another username.

    -- cgit v1.2.3-70-g09d2 From b19511eb75c6490ddc97ea59d82615ce4d9e0e91 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 10 Jul 2014 17:15:54 -0400 Subject: use view iframe on profile, spins on hover --- .../assets/javascripts/mx/primitives/mx.youtube.js | 3 +-- public/assets/javascripts/ui/_router.js | 7 ++---- .../assets/javascripts/ui/editor/EditorSettings.js | 2 +- public/assets/javascripts/ui/reader/ReaderView.js | 29 ++++++++++++++++++++++ public/assets/javascripts/ui/site/ProfileView.js | 29 ++++++++++++++++++++++ views/partials/scripts.ejs | 1 + 6 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 public/assets/javascripts/ui/site/ProfileView.js (limited to 'public/assets/javascripts/ui/site') diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js index 9925c22..118623b 100644 --- a/public/assets/javascripts/mx/primitives/mx.youtube.js +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -41,7 +41,6 @@ MX.Youtube = MX.Object3D.extend({ defer: function (uid){ if (! YT || ! YT.loaded) { setTimeout(function(){ - console.log("hwat") this.defer(uid) }.bind(this), 300) } @@ -127,5 +126,5 @@ MX.Youtube = MX.Object3D.extend({ }) window.onYouTubePlayerAPIReady = function(){ - console.log("youtube ready") + // console.log("youtube api ready") } diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index ce18b2a..b3e868a 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -49,6 +49,7 @@ var SiteRouter = Router.extend({ this.editProfileModal = new EditProfileModal() this.passwordForgotModal = new PasswordForgot() this.documentModal = new DocumentModal() + this.profileView = new ProfileView() this.route() @@ -155,11 +156,7 @@ var SiteRouter = Router.extend({ }, profile: function(e){ - var classes = ['one', 'two', 'three', 'four', - 'five', 'six', 'seven', 'eight', - 'nine', 'ten', 'eleven', 'twelve', - 'thirteen']; - $(".bio").addClass(choice(classes)); + this.profileView.load() }, editProfile: function(e){ diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index 35bcbe0..1d68b1b 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -32,7 +32,7 @@ var EditorSettings = FormView.extend({ data.startPosition && scene.camera.move(data.startPosition) if (! data.isNew) { - console.log(data) + // console.log(data) this.$id.val( data._id ) this.$name.val( data.name ) diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js index 860cc04..e86856c 100644 --- a/public/assets/javascripts/ui/reader/ReaderView.js +++ b/public/assets/javascripts/ui/reader/ReaderView.js @@ -26,6 +26,35 @@ var ReaderView = View.extend({ data.startPosition && scene.camera.move(data.startPosition) editor.permissions.clear() + + // + + var base = this + + $(window).on('message', function(event){ + if (event.origin !== window.location.origin) { + return + } + var message = event.originalEvent.data + switch (message) { + case "spin-on": + base.spinning = true + break + case "spin-off": + base.spinning = false + break + } + }) + + requestAnimationFrame(this.spin.bind(this)) + }, + + spinning: false, + spin: function(){ + requestAnimationFrame(this.spin.bind(this)) + if (this.spinning) { + scene.camera.rotationY -= 1/180 + } } }) diff --git a/public/assets/javascripts/ui/site/ProfileView.js b/public/assets/javascripts/ui/site/ProfileView.js new file mode 100644 index 0000000..41f04ef --- /dev/null +++ b/public/assets/javascripts/ui/site/ProfileView.js @@ -0,0 +1,29 @@ + +var ProfileView = View.extend({ + + initialize: function(){ + }, + + load: function(){ + var classes = ['one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', + 'nine', 'ten', 'eleven', 'twelve', + 'thirteen']; + $(".bio").addClass(choice(classes)); + + $("td.border").each(function(){ + var iframe = $(this).find("iframe").get('0') + if (! iframe) return + console.log(iframe) + $(this).on({ + mouseenter: function(e){ + iframe.contentWindow.postMessage("spin-on", window.location.origin) + }, + mouseleave: function(e){ + iframe.contentWindow.postMessage("spin-off", window.location.origin) + } + }) + }) + } + +}) diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 9f0c2f2..6dd4480 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -72,6 +72,7 @@ + -- cgit v1.2.3-70-g09d2 From bce442242f167b70be1f7b24190f9e59d3c24e37 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 10 Jul 2014 18:21:06 -0400 Subject: media editor --- public/assets/javascripts/ui/reader/ReaderView.js | 2 +- public/assets/javascripts/ui/site/ProfileView.js | 7 ++-- views/controls/editor/media-editor.ejs | 43 ++++++++++++++++------- views/controls/editor/settings.ejs | 2 +- views/controls/editor/video-toolbar.ejs | 7 ---- views/controls/reader/about-media.ejs | 16 +++++++++ 6 files changed, 51 insertions(+), 26 deletions(-) delete mode 100644 views/controls/editor/video-toolbar.ejs create mode 100644 views/controls/reader/about-media.ejs (limited to 'public/assets/javascripts/ui/site') diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js index e86856c..add1ea1 100644 --- a/public/assets/javascripts/ui/reader/ReaderView.js +++ b/public/assets/javascripts/ui/reader/ReaderView.js @@ -32,7 +32,7 @@ var ReaderView = View.extend({ var base = this $(window).on('message', function(event){ - if (event.origin !== window.location.origin) { + if (event.originalEvent.origin !== window.location.origin) { return } var message = event.originalEvent.data diff --git a/public/assets/javascripts/ui/site/ProfileView.js b/public/assets/javascripts/ui/site/ProfileView.js index 41f04ef..8661bcd 100644 --- a/public/assets/javascripts/ui/site/ProfileView.js +++ b/public/assets/javascripts/ui/site/ProfileView.js @@ -1,20 +1,19 @@ var ProfileView = View.extend({ - initialize: function(){ + initialize: function() { }, - load: function(){ + load: function() { var classes = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen']; $(".bio").addClass(choice(classes)); - $("td.border").each(function(){ + $("td.border").each(function() { var iframe = $(this).find("iframe").get('0') if (! iframe) return - console.log(iframe) $(this).on({ mouseenter: function(e){ iframe.contentWindow.postMessage("spin-on", window.location.origin) diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs index 93405fc..95aabb5 100644 --- a/views/controls/editor/media-editor.ejs +++ b/views/controls/editor/media-editor.ejs @@ -3,28 +3,45 @@
    - +
    + +
    + + + + + + + + Autoplay + Loop + Mute + Initial Still +
    -
    -
    - - - - -
    +
    + Dimensions + Width + Height +
    - + +
    + Delete +
    diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index 867d5f3..6f46be3 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -10,7 +10,7 @@
    - +
    diff --git a/views/controls/editor/video-toolbar.ejs b/views/controls/editor/video-toolbar.ejs deleted file mode 100644 index d4364a2..0000000 --- a/views/controls/editor/video-toolbar.ejs +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/views/controls/reader/about-media.ejs b/views/controls/reader/about-media.ejs new file mode 100644 index 0000000..c6365ad --- /dev/null +++ b/views/controls/reader/about-media.ejs @@ -0,0 +1,16 @@ +
    + +
    +
    +
    +
    + +
    + + + + + +
    + +
    -- cgit v1.2.3-70-g09d2 From 9825b711480eb5b6022ce6b56b8a6914c5f43e52 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 14 Jul 2014 13:05:57 -0400 Subject: pick initial frame --- .../assets/javascripts/mx/primitives/mx.video.js | 12 ++++-- .../assets/javascripts/mx/primitives/mx.vimeo.js | 43 ++++++++++++++++++---- .../assets/javascripts/mx/primitives/mx.youtube.js | 21 ++++++++--- .../javascripts/rectangles/engine/scenery/move.js | 6 +-- public/assets/javascripts/ui/_router.js | 12 +++--- .../javascripts/ui/builder/BuilderSettings.js | 4 +- .../assets/javascripts/ui/builder/BuilderView.js | 2 +- .../assets/javascripts/ui/editor/EditorSettings.js | 4 +- public/assets/javascripts/ui/editor/EditorView.js | 4 +- public/assets/javascripts/ui/editor/MediaEditor.js | 17 ++++++--- public/assets/javascripts/ui/editor/MediaUpload.js | 8 ++-- public/assets/javascripts/ui/editor/MediaViewer.js | 4 +- public/assets/javascripts/ui/lib/FormView.js | 4 +- public/assets/javascripts/ui/reader/ReaderView.js | 2 +- public/assets/javascripts/ui/site/DocumentModal.js | 4 +- .../assets/javascripts/ui/site/EditProfileModal.js | 4 +- .../assets/javascripts/ui/site/EditProjectModal.js | 4 +- public/assets/javascripts/ui/site/LayoutsModal.js | 6 +-- public/assets/stylesheets/app.css | 10 ++--- views/controls/editor/media-editor.ejs | 2 +- 20 files changed, 111 insertions(+), 62 deletions(-) (limited to 'public/assets/javascripts/ui/site') diff --git a/public/assets/javascripts/mx/primitives/mx.video.js b/public/assets/javascripts/mx/primitives/mx.video.js index b1b9f6b..f92fe9f 100644 --- a/public/assets/javascripts/mx/primitives/mx.video.js +++ b/public/assets/javascripts/mx/primitives/mx.video.js @@ -28,8 +28,8 @@ MX.Video = MX.Object3D.extend({ this.paused = true this.player = document.createElement('video') - this.player.addEventListener("loadedmetadata", $.proxy(this.ready, this)) - this.player.addEventListener("error", $.proxy(this.error, this)) + this.player.addEventListener("loadedmetadata", this.ready.bind(this)) + this.player.addEventListener("error", this.error.bind(this)) this.player.width = this.width this.player.height = this.height this.player.src = this.media.url @@ -62,7 +62,10 @@ MX.Video = MX.Object3D.extend({ }, seek: function(n){ - this.player.currentTime = n + if (n < 1) { + n = n * this.duration() + } + this.player.currentTime = n }, duration: function(){ @@ -71,6 +74,9 @@ MX.Video = MX.Object3D.extend({ finished: function(){ console.log("video finished") + if (this.media.bound) { + $(".playButton").removeClass('playing') + } }, diff --git a/public/assets/javascripts/mx/primitives/mx.vimeo.js b/public/assets/javascripts/mx/primitives/mx.vimeo.js index e558bc3..5a373ff 100644 --- a/public/assets/javascripts/mx/primitives/mx.vimeo.js +++ b/public/assets/javascripts/mx/primitives/mx.vimeo.js @@ -26,30 +26,34 @@ MX.Vimeo = MX.Object3D.extend({ load: function (ops) { var uid = 'player-' + Uid () - var preload = document.createElement("div") + var preload = document.createElement("iframe") preload.id = uid + preload.setAttribute("src", "//player.vimeo.com/video/" + this.media.token + "?api=1&badge=0&controls=0branding=0&byline=0&player_id=" + uid) preload.style.backgroundImage = "url(" + this.media.thumbnail + ")" preload.style.width = this.media.width + "px" preload.style.height = this.media.height + "px" + preload.style.border = "0" preload.style.pointerEvents = "none" preload.className = "preload" this.el.appendChild(preload) - this.player = $f(preload) - this.player.addEvent('ready', $.proxy(this.ready, this)) + + this.player.addEvent('ready', this.ready.bind(this)) }, ready: function(){ console.log("vimeo ready") // wait until ready before binding events. other events: play, pause - this.player.addEvent('finish', $.proxy(this.finished, this)) + this.player.addEvent('play', this.onPlay.bind(this)) + this.player.addEvent('pause', this.onPause.bind(this)) + this.player.addEvent('finish', this.finished.bind(this)) // so annoying that this is async!! - this.player.api('getDuration', $.proxy(function(n){ + this.player.api('getDuration', function(n){ console.log("vimeo duration", n) this.player.duration = n - }, this)) + }.bind(this)) }, @@ -68,14 +72,39 @@ MX.Vimeo = MX.Object3D.extend({ }, seek: function(n){ - this.player.api('seekTo', n) + if (n < 1) { + n = n * this.duration() + } + this.player.api('seekTo', max(0, n-1)) + if (this.paused) { + this.paused = false + this.play() + setTimeout(function(){ + this.pause() + }.bind(this), 1000) + } }, duration: function(){ return this.player.duration }, + onPlay: function(){ + if (this.paused) { + this.pause() + } + }, + + onPause: function(){ + if (! this.paused) { + this.play() + } + }, + finished: function(){ + if (this.media.bound) { + $(".playButton").removeClass('playing') + } } }) diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js index cc0ec0a..a31a24d 100644 --- a/public/assets/javascripts/mx/primitives/mx.youtube.js +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -56,9 +56,9 @@ MX.Youtube = MX.Object3D.extend({ width: this.width, height: this.height, events: { - onReady: $.proxy(this.ready, this), - onError: $.proxy(this.error, this), - onStateChange: $.proxy(this.statechange, this), + onReady: this.ready.bind(this), + onError: this.error.bind(this), + onStateChange: this.statechange.bind(this), }, playerVars: { autohide: 1, @@ -93,10 +93,11 @@ MX.Youtube = MX.Object3D.extend({ this.finished() break case 1: // play - this.paused = false + if (this.paused) { + this.pause() + } break case 2: // pause - this.paused = true break case 3: // buffering break @@ -106,15 +107,20 @@ MX.Youtube = MX.Object3D.extend({ }, play: function(){ + this.paused = false this.player.playVideo() }, pause: function(){ + this.paused = true this.player.pauseVideo() }, seek: function(n, allowSeekAhead){ - allowSeekAhead = typeof allowSeekAhead == "boolean" ? allowSeekAhead : true + if (n < 1) { + n = n * this.duration() + } + allowSeekAhead = typeof allowSeekAhead == "boolean" ? allowSeekAhead : true this.player.seekTo(n, true) // set to false if seeking manually }, @@ -124,6 +130,9 @@ MX.Youtube = MX.Object3D.extend({ finished: function(){ console.log("youtube finished") + if (this.media.bound) { + $(".playButton").removeClass('playing') + } } }) diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index aa7ddd1..6229162 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -27,10 +27,8 @@ Scenery.move = function(base){ return } - if (editor.permissions.pick) { - // load the modal - app.router.editorView.mediaEditor.pick(base) - } + // load the modal + app.router.editorView.mediaEditor.pick(base) if (! (editor.permissions.move || editor.permissions.resize) ) { e.clickAccepted = false diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index b3e868a..886b8be 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -189,13 +189,13 @@ var SiteRouter = Router.extend({ var name = e ? $(e.currentTarget).data("name") : name - confirmModal.confirm("Are you sure you want to delete " + name + "?", $.proxy(function(){ - this.documentModal.destroy(name, $.proxy(function(){ - AlertModal.alert("Document deleted!", $.proxy(function(){ + confirmModal.confirm("Are you sure you want to delete " + name + "?", function(){ + this.documentModal.destroy(name, function(){ + AlertModal.alert("Document deleted!", function(){ window.location.href = "/about" - }, this)) - }, this)) - }, this)) + }.bind(this)) + }.bind(this)) + }.bind(this)) // this.documentModal.destroy(name) }, diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index 9fcd55f..6006868 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -57,7 +57,7 @@ var BuilderSettings = FormView.extend({ destroy: function(){ var msg = "Are you sure you want to delete the layout " + sanitize(this.$name.val()) + "?" - ConfirmModal.confirm(msg, $.proxy(function(){ + ConfirmModal.confirm(msg, function(){ $.ajax({ url: this.destroyAction, type: "delete", @@ -66,7 +66,7 @@ var BuilderSettings = FormView.extend({ window.location.href = "/layout" } }) - }, this)) + }.bind(this)) }, toggle: function(){ diff --git a/public/assets/javascripts/ui/builder/BuilderView.js b/public/assets/javascripts/ui/builder/BuilderView.js index b42d3e7..a83bf43 100644 --- a/public/assets/javascripts/ui/builder/BuilderView.js +++ b/public/assets/javascripts/ui/builder/BuilderView.js @@ -20,7 +20,7 @@ var BuilderView = View.extend({ name = sanitize(name) - $.get(this.action + name, $.proxy(this.ready, this)) + $.get(this.action + name, this.ready.bind(this)) }, ready: function(data){ diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index 1d68b1b..887c894 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -65,7 +65,7 @@ var EditorSettings = FormView.extend({ destroy: function(){ var msg = "Are you sure you want to delete the project " + sanitize(this.$name.val()) + "?" - ConfirmModal.confirm(msg, $.proxy(function(){ + ConfirmModal.confirm(msg, function(){ $.ajax({ url: this.destroyAction, type: "delete", @@ -74,7 +74,7 @@ var EditorSettings = FormView.extend({ window.location.href = "/project" } }) - }, this)) + }.bind(this)) }, toggle: function(){ diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 017e241..322637e 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -20,12 +20,12 @@ var EditorView = View.extend({ load: function(name){ name = sanitize(name) - $.get(this.projectAction + name, $.proxy(this.ready, this)) + $.get(this.projectAction + name, this.ready.bind(this)) }, loadLayout: function(layout){ layout = sanitize(layout) - $.get(this.layoutAction + layout, $.proxy(this.readyLayout, this)) + $.get(this.layoutAction + layout, this.readyLayout.bind(this)) }, ready: function(data){ diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index 47a938b..29ec9e5 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -3,7 +3,8 @@ var MediaEditor = FormView.extend({ el: "#mediaEditor", events: { - "click .play": "togglePlaying", + "click .playButton": "togglePlaying", + "change [name=keyframe]": "seek", }, initialize: function(opt){ @@ -20,7 +21,7 @@ var MediaEditor = FormView.extend({ this.$units = this.$("[name=units]") // video fields - this.$playButton = this.$(".play") + this.$playButton = this.$(".playButton") this.$loop = this.$("[name=loop]") this.$mute = this.$("[name=mute]") this.$keyframe = this.$("[name=keyframe]") @@ -39,7 +40,7 @@ var MediaEditor = FormView.extend({ if (this.scenery) { this.unbind() } - + this.bind(scenery) this.$el.addClass("active") @@ -71,17 +72,23 @@ var MediaEditor = FormView.extend({ this.$mute this.$keyframe */ - - break } + + }, + + seek: function(){ + var n = parseFloat( this.$keyframe.val() ) + this.scenery.seek(n) }, bind: function(scenery){ this.scenery = scenery + this.scenery.media.bound = true }, unbind: function(){ + this.scenery.media.bound = false this.scenery = null }, diff --git a/public/assets/javascripts/ui/editor/MediaUpload.js b/public/assets/javascripts/ui/editor/MediaUpload.js index b7fea07..86bf767 100644 --- a/public/assets/javascripts/ui/editor/MediaUpload.js +++ b/public/assets/javascripts/ui/editor/MediaUpload.js @@ -39,7 +39,7 @@ var MediaUpload = View.extend({ var url = this.$url.val() this.$url.val("") - Parser.parse(url, $.proxy(function(media){ + Parser.parse(url, function(media){ if (! media) { alert("Not a valid image/video link") return @@ -53,8 +53,8 @@ var MediaUpload = View.extend({ url: this.createAction, data: media, }) - request.done($.proxy(this.add, this)) - }, this)) + request.done(this.add.bind(this)) + }.bind(this)) }, handleFileSelect: function(e) { @@ -109,7 +109,7 @@ var MediaUpload = View.extend({ processData: false, contentType: false, }) - request.done($.proxy(this.add, this)) + request.done(this.add.bind(this)) }, add: function(media){ diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index 88c3b18..264ed7c 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -40,12 +40,12 @@ var MediaViewer = ModalView.extend({ }, load: function(){ - $.get("/api/media/user", $.proxy(this.populate, this)) + $.get("/api/media/user", this.populate.bind(this)) }, populate: function(data){ this.loaded = true - data && data.forEach($.proxy(this.add, this)) + data && data.forEach(this.add.bind(this)) this.__super__.show.call(this) }, diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index 0106ce0..219952d 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -26,9 +26,9 @@ var FormView = View.extend({ this.$errorList.append('
    ' + errors[i] + '
    '); } this.$errors.css("opacity", 1.0); - setTimeout($.proxy(function(){ + setTimeout(function(){ this.$errors.show().css("opacity", 1.0); - }, this), 200) + }.bind(this), 200) } }, diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js index add1ea1..bbdd437 100644 --- a/public/assets/javascripts/ui/reader/ReaderView.js +++ b/public/assets/javascripts/ui/reader/ReaderView.js @@ -15,7 +15,7 @@ var ReaderView = View.extend({ $(".logo,.topLinks,#editorView").hide() } name = sanitize(name) - $.get(this.projectAction + name, $.proxy(this.ready, this)) + $.get(this.projectAction + name, this.ready.bind(this)) }, ready: function(data){ diff --git a/public/assets/javascripts/ui/site/DocumentModal.js b/public/assets/javascripts/ui/site/DocumentModal.js index 6f16169..067977d 100644 --- a/public/assets/javascripts/ui/site/DocumentModal.js +++ b/public/assets/javascripts/ui/site/DocumentModal.js @@ -20,7 +20,7 @@ var DocumentModal = ModalFormView.extend({ this.action = this.updateAction - $.get("/api/docs", { name: name }, $.proxy(function(data){ + $.get("/api/docs", { name: name }, function(data){ if (data.isNew) { this.action = this.createAction } @@ -31,7 +31,7 @@ var DocumentModal = ModalFormView.extend({ this.$("[name='new_name']").val(name) this.show() - }, this)) + }.bind(this)) }, success: function(res){ diff --git a/public/assets/javascripts/ui/site/EditProfileModal.js b/public/assets/javascripts/ui/site/EditProfileModal.js index 6b89ad8..b023923 100644 --- a/public/assets/javascripts/ui/site/EditProfileModal.js +++ b/public/assets/javascripts/ui/site/EditProfileModal.js @@ -6,7 +6,7 @@ var EditProfileModal = ModalFormView.extend({ load: function(){ this.reset() - $.get("/api/profile", $.proxy(function(data){ + $.get("/api/profile", function(data){ console.log(data) for (var i in data) { @@ -23,7 +23,7 @@ var EditProfileModal = ModalFormView.extend({ } this.show() - }, this)) + }.bind(this)) }, validate: function(){ diff --git a/public/assets/javascripts/ui/site/EditProjectModal.js b/public/assets/javascripts/ui/site/EditProjectModal.js index 356d8b7..20baa54 100644 --- a/public/assets/javascripts/ui/site/EditProjectModal.js +++ b/public/assets/javascripts/ui/site/EditProjectModal.js @@ -31,7 +31,7 @@ var EditProjectModal = ModalView.extend({ var fields = this.$form.serializeArray() var request = $.post(this.action, $.param(fields)); - request.done($.proxy(function (response) { + request.done(function (response) { if (response.error) { this.$errors.show(); for (var key in response.error.errors) { @@ -42,7 +42,7 @@ var EditProjectModal = ModalView.extend({ else { window.location.href = "/profile" } - }, this)); + }.bind(this)); } }) diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index d474aa7..3b9e6cd 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -8,18 +8,18 @@ var LayoutsIndex = View.extend({ load: function(type){ this.$templates.children("span").remove() - $.get(this.action, $.proxy(this.populate, this)) + $.get(this.action, this.populate.bind(this)) }, populate: function(data){ - data.forEach($.proxy(function(room){ + data.forEach(function(room){ var $span = $("") // $span.html(JSON.stringify(room)) $span.data("slug", room.slug) $span.css("background-image", "url(" + room.photo + ")") this.$templates.append($span) - }, this)) + }.bind(this)) this.show() } diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 4296223..500f444 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1220,23 +1220,23 @@ input[type="range"]::-webkit-slider-thumb { padding-right: 5px; } -.setting .play { +.setting .playButton { color: white; background: black; border-radius: 50px; padding: 6px 7px 5px; cursor: pointer; } -.setting .play .icon-play { +.setting .playButton .icon-play { display: inline; } -.setting .play.playing .icon-play { +.setting .playButton.playing .icon-play { display: none; } -.setting .play .icon-pause { +.setting .playButton .icon-pause { display: none; } -.setting .play.playing .icon-pause { +.setting .playButton.playing .icon-pause { display: inline; } diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs index 12ab2b4..46b8a42 100644 --- a/views/controls/editor/media-editor.ejs +++ b/views/controls/editor/media-editor.ejs @@ -11,7 +11,7 @@
    - + -- cgit v1.2.3-70-g09d2 From e17d458b644fddccd522d0475f531b487c4d95ef Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 16 Jul 2014 15:29:10 -0400 Subject: some bugfixes.. info window for builder --- .../assets/javascripts/mx/primitives/mx.video.js | 2 +- .../assets/javascripts/mx/primitives/mx.vimeo.js | 10 ++++++- .../assets/javascripts/mx/primitives/mx.youtube.js | 2 +- .../javascripts/rectangles/engine/rooms/builder.js | 4 +-- .../javascripts/rectangles/engine/rooms/clipper.js | 7 +++-- .../rectangles/engine/scenery/types/video.js | 3 ++ public/assets/javascripts/ui/_router.js | 1 - public/assets/javascripts/ui/reader/ReaderView.js | 3 ++ public/assets/javascripts/ui/site/LayoutsModal.js | 7 +++++ public/assets/stylesheets/app.css | 25 +++++++++++++++- views/builder.ejs | 3 +- views/controls/builder/info.ejs | 35 ++++++++++++++++++++++ views/controls/editor/media-editor.ejs | 4 +-- views/partials/sign-in.ejs | 4 +-- views/projects/layouts-modal.ejs | 8 +++++ views/projects/list-projects.ejs | 2 +- 16 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 views/controls/builder/info.ejs (limited to 'public/assets/javascripts/ui/site') diff --git a/public/assets/javascripts/mx/primitives/mx.video.js b/public/assets/javascripts/mx/primitives/mx.video.js index 7f91e34..b28204d 100644 --- a/public/assets/javascripts/mx/primitives/mx.video.js +++ b/public/assets/javascripts/mx/primitives/mx.video.js @@ -20,7 +20,7 @@ MX.Video = MX.Object3D.extend({ this.backface && this.el.classList.add("backface-visible") this.el.classList.add("video") this.paused = !! this.media.autoplay - this.muted = !! this.media.mute + this.muted = app.muted || !! this.media.mute this.load() }, diff --git a/public/assets/javascripts/mx/primitives/mx.vimeo.js b/public/assets/javascripts/mx/primitives/mx.vimeo.js index 0301e64..7a5327e 100644 --- a/public/assets/javascripts/mx/primitives/mx.vimeo.js +++ b/public/assets/javascripts/mx/primitives/mx.vimeo.js @@ -20,7 +20,7 @@ MX.Vimeo = MX.Object3D.extend({ this.backface && this.el.classList.add("backface-visible") this.el.classList.add("video") this.paused = !! this.media.autoplay - this.muted = !! this.media.mute + this.muted = app.muted || !! this.media.mute this.load() }, @@ -82,6 +82,14 @@ MX.Vimeo = MX.Object3D.extend({ }, seek: function(n){ + // defer seek until we have duration + if (! this.duration()) { + setTimeout(function(){ + this.seek(n) + }.bind(this), 300) + return + } + if (n < 1) { n = n * this.duration() } diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js index 8c11da6..47d5507 100644 --- a/public/assets/javascripts/mx/primitives/mx.youtube.js +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -20,7 +20,7 @@ MX.Youtube = MX.Object3D.extend({ this.backface && this.el.classList.add("backface-visible") this.el.classList.add("video") this.paused = !! this.media.autoplay - this.muted = !! this.media.mute + this.muted = app.muted || !! this.media.mute this.load() }, diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index e6625ec..49e55dc 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -20,8 +20,8 @@ Rooms.builder = new function(){ } } function build (){ - Rooms.regions.forEach(function(room){ - build_walls(room).forEach(function(el){ + Rooms.regions.forEach(function(region){ + build_walls(region).forEach(function(el){ els.push(el) scene.add(el) }) diff --git a/public/assets/javascripts/rectangles/engine/rooms/clipper.js b/public/assets/javascripts/rectangles/engine/rooms/clipper.js index eb467cd..e2bb894 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/clipper.js +++ b/public/assets/javascripts/rectangles/engine/rooms/clipper.js @@ -20,12 +20,15 @@ Rooms.clipper = new function(){ // Given a set of overlapping rooms, clip any intersections, then cull any duplicate polygons base.solve_rects = function(){ - if (Rooms.count() == 0) return + if (Rooms.count() == 0) { + Rooms.regions = regions = [] + return + } base.reset_rects() base.clip_rects() base.cull_rects() - + Rooms.regions = sort_rects_by_position(regions) } diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/video.js b/public/assets/javascripts/rectangles/engine/scenery/types/video.js index 8cd5e6b..d3e2e76 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/video.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/video.js @@ -25,6 +25,9 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ this.mxType = MX.Youtube break } + if (app.muted) { + this.media.mute = true + } this.mx = new this.mxType({ media: this.media, scale: this.scale, diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index b59d838..d070d55 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -160,7 +160,6 @@ var SiteRouter = Router.extend({ profile: function(e){ this.profileView.load() }, - editProfile: function(e){ e && e.preventDefault() window.history.pushState(null, document.title, "/profile/edit") diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js index a2c2983..9d38daa 100644 --- a/public/assets/javascripts/ui/reader/ReaderView.js +++ b/public/assets/javascripts/ui/reader/ReaderView.js @@ -15,6 +15,9 @@ var ReaderView = View.extend({ if (window.location.search.indexOf("noui") !== -1) { $(".logo,.topLinks,#editorView").hide() } + if (window.location.search.indexOf("mute") !== -1) { + app.muted = true + } name = sanitize(name) $.get(this.projectAction + name, this.ready.bind(this)) }, diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 3b9e6cd..4948b0e 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -3,6 +3,8 @@ var LayoutsIndex = View.extend({ initialize: function(){ this.$templates = this.$(".templates") + this.$noTemplates = this.$(".no-templates") + this.$form = this.$("form") }, load: function(type){ @@ -12,6 +14,11 @@ var LayoutsIndex = View.extend({ }, populate: function(data){ + if (! data.length) { + this.$templates.hide() + this.$form.hide() + this.$noTemplates.show() + } data.forEach(function(room){ var $span = $("") // $span.html(JSON.stringify(room)) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 2583284..2e3358a 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -469,6 +469,9 @@ iframe.embed { .templates { } +.no-templates { + display: none; +} .templates span{ background-position: center; @@ -1130,6 +1133,11 @@ input[type="range"]::-webkit-slider-thumb { cursor:pointer; } +.settings.info { + right: auto; + left: 10px; +} + .settings { padding: 20px; bottom: 20px; @@ -1228,8 +1236,23 @@ input[type="range"]::-webkit-slider-thumb { } .setting label { + font-size: 12px; + font-weight: 300; padding-right: 5px; } +.setting.number label { + width: 50px; + display: inline-block; + float: left; + position: relative; + top: 5px; +} +.setting.number input[type=text] { + width: 150px; +} +.setting.number.twoline label { + top: 0px; +} .playButton,.muteButton { color: white; @@ -1485,7 +1508,7 @@ form li textarea { background:lightgreen; } */ -.box b.info { +.box b.signin-tagline { display: inline-block; width: 100%; margin-bottom: 18px; diff --git a/views/builder.ejs b/views/builder.ejs index 61e84c3..afb8c66 100644 --- a/views/builder.ejs +++ b/views/builder.ejs @@ -12,6 +12,7 @@ [[ include partials/header ]]
    + [[ include controls/builder/info ]] [[ include controls/builder/toolbar ]] [[ include controls/builder/settings ]]
    @@ -20,7 +21,6 @@
    - --> + -->
    diff --git a/views/controls/builder/info.ejs b/views/controls/builder/info.ejs new file mode 100644 index 0000000..af0a76d --- /dev/null +++ b/views/controls/builder/info.ejs @@ -0,0 +1,35 @@ +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + + +
    + +
    diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs index 65db3ce..5db1fb2 100644 --- a/views/controls/editor/media-editor.ejs +++ b/views/controls/editor/media-editor.ejs @@ -29,9 +29,9 @@
    - Initial Still +
    - +
    diff --git a/views/partials/sign-in.ejs b/views/partials/sign-in.ejs index 3f05fff..8268b2a 100644 --- a/views/partials/sign-in.ejs +++ b/views/partials/sign-in.ejs @@ -6,7 +6,7 @@ - – or the ol' fashion way – +
  • @@ -39,7 +39,7 @@ - – or the ol' fashion way – +
  • diff --git a/views/projects/layouts-modal.ejs b/views/projects/layouts-modal.ejs index 75b2641..97f1e61 100644 --- a/views/projects/layouts-modal.ejs +++ b/views/projects/layouts-modal.ejs @@ -5,6 +5,9 @@

    Edit Room Layouts

    +
    + There are no room layouts available. Please create a new one. +
    @@ -18,6 +21,8 @@

    Your Projects

    +
    +
    @@ -31,6 +36,9 @@

    Choose Room Template

    +
    + There are no room layouts available. Please create a new one. +
    diff --git a/views/projects/list-projects.ejs b/views/projects/list-projects.ejs index 42387ba..2c12af0 100644 --- a/views/projects/list-projects.ejs +++ b/views/projects/list-projects.ejs @@ -6,7 +6,7 @@ [[ projects.forEach(function(project, i) { ]] - + [[ if (profile._id == project.user_id) { ]]
    edit
    [[ } ]] -- cgit v1.2.3-70-g09d2