From 099dfd16940c62e931bf01e7f62b7a45f2b8c654 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 13:12:27 -0400 Subject: collaborators api --- server/lib/api/collaborator.js | 85 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 server/lib/api/collaborator.js (limited to 'server/lib/api/collaborator.js') diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js new file mode 100644 index 0000000..4b55f09 --- /dev/null +++ b/server/lib/api/collaborator.js @@ -0,0 +1,85 @@ +/* jshint node: true */ + +var _ = require('lodash'), + util = require('../util'), + upload = require('../upload'), + config = require('../../../config.json'), + Collaborator = require('../schemas/Collaborator'), + Project = require('../schemas/Project'); + +var collaborator = { + + join: function(req, res){ + var nonce = req.query.nonce + if (! nonce || ! nonce.length) { return res.json({ error: "invalid invite code" }) } + Collaborator.findOne({ nonce: nonce }, function(err, collaborator){ + if (err || ! collaborator) { return res.json({ error: "can't find collaborator" }) } + collaborator.user_id = req.user.user_id + collaborator.nonce = "" + collaborator.save(function(err, collaborator){ + Project.findOne({ _id: collaborator.project_id }, function(err, project){ + if (err || ! project) { return res.json({ error: err }) } + res.redirect("/project/" + project.slug + "/edit") + }) + }) + }) + }, + + // + + index: function(req, res){ + if (! req.project) { + return res.json({ error: "can't find project" }) + } + if (req.project.user_id !== req.user._id) { return res.json({ error: "insufficient permission" }) } + Collaborator.find({ project_id: req.project._id }, function(err, collaborators){ + var user_ids = _.pluck(collaborators, "user_id").filter(function(id){ return !! id }) + User.find({ _id: user_ids }, "username displayName photo", function(err, users){ + if (! user_ids) { + return res.json(collaborators) + } + var userIndex = _.indexBy(users, '_id') + collaborators = collaborators.map(function(collaborator){ + var obj = collaborator.toObject() + obj.user = userIndex[ obj.user_id ] + return obj + }) + res.json(collaborators) + }) + }) + }, + + create: function(req, res){ + if (! req.project) { + return res.json({ error: "can't find project" }) + } + var data = util.cleanQuery(req.body) + delete data.user_id + + data.project_id = req.project._id + + Collaborator.makeNonce(function(nonce){ + data.nonce = nonce + new Collaborator(data).save(function(err, collaborator){ + if (err || ! collaborator) { return res.json({ error: err }) } + auth.mail.forgotPassword(req.project, req.user, collaborator, function(){ + res.json(collaborator) + }) + }) + }) + }, + + destroy: function(req, res){ + if (! req.project) { + return res.json({ error: "can't find project" }) + } + if (req.project.user_id !== req.user._id) { + return res.json({ error: "insufficient permission" }) + } + Collaborator.remove({ _id: _id }, function(err){ + res.json({ status: "OK" }) + }) + } +} + +module.exports = collaborator -- cgit v1.2.3-70-g09d2 From 124a698130f39992a1b47dcc8f32ef30c61a00eb Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 14:24:45 -0400 Subject: stub in collaborator ui --- .../assets/javascripts/ui/editor/Collaborators.js | 64 ++++++++++++++++++++++ public/assets/javascripts/ui/editor/EditorView.js | 1 + public/assets/stylesheets/app.css | 6 ++ server/index.js | 4 +- server/lib/api/collaborator.js | 4 +- server/lib/views.js | 2 + views/controls/editor/collaborators.ejs | 24 +++++--- views/controls/reader/about-room.ejs | 7 ++- views/partials/scripts.ejs | 1 + 9 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 public/assets/javascripts/ui/editor/Collaborators.js (limited to 'server/lib/api/collaborator.js') diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js new file mode 100644 index 0000000..bb163f8 --- /dev/null +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -0,0 +1,64 @@ + +var Collaborators = ModalFormView.extend({ + el: ".mediaDrawer.collaborators", + + template: $("#collaborator-template").html(), + + createAction: "/api/collaborator/:slug/create", + destroyAction: "/api/collaborator/:slug/destroy", + + events: { + "click [data-role=destroy-collaborator]": "destroy", + }, + + show: function(){ + if (! this.loaded) { + this.load() + } + else { + this.__super__.show.call(this) + } + }, + + load: function(){ + $.get("/api/collaborator/:slug/index", this.populate.bind(this)) + }, + + populate: function(collaborators){ + // + collaborators.forEach(function(collab){ + var $el = $( this.template ) + $el.data("collaborator-id", collab.id) + + if (collab.user) { + $el.find(".email").remove() + + $el.find(".user") + .attr("href", "/profile/" + collab.username) + + $el.find(".avatar") + .css("background-image", "url(" + collab.photo + ")") + + $el.find(".username") + .html( collab.displayName ) + } + else { + $el.remove(".user") + $el.find(".email").html( collab.email ) + } + + $("#collaborators").append($el) + }.bind(this)) + + this.__super__.show.call(this) + }, + + success: function(data){ + this.populate([data]) + }, + + destroy: function(e){ + var _id = $(e.currentTarget).closest("li").data("collaborator-id") + }, + +}) diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 4067c4d..5fc5147 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -16,6 +16,7 @@ var EditorView = View.extend({ this.mediaEditor = new MediaEditor ({ parent: this }) this.wallpaperPicker = new WallpaperPicker ({ parent: this }) this.lightControl = new LightControl ({ parent: this }) + this.collaborators = new Collaborators ({ parent: this }) }, load: function(name){ diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 3b00cd2..92eed33 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1615,6 +1615,12 @@ form li textarea { text-decoration:underline; } +.aboutRoom .editlink { + color: red; + text-decoration: none; + border-bottom: 1px dotted; +} + .aboutRoom h2{ font-size: 13px; margin: 5px 0; diff --git a/server/index.js b/server/index.js index 212db01..e946788 100644 --- a/server/index.js +++ b/server/index.js @@ -125,8 +125,8 @@ site.route = function () { app.get('/project', middleware.ensureAuthenticated, views.modal) app.get('/project/new', middleware.ensureAuthenticated, views.modal) app.get('/project/new/:layout', middleware.ensureAuthenticated, views.editor_new) - app.get('/project/:slug', middleware.ensureProject, views.reader) - app.get('/project/:slug/view', middleware.ensureProject, views.reader) + app.get('/project/:slug', middleware.ensureProject, middleware.ensureIsCollaborator, views.reader) + app.get('/project/:slug/view', middleware.ensureProject, middleware.ensureIsCollaborator, views.reader) app.get('/project/:slug/edit', middleware.ensureProject, middleware.ensureIsCollaborator, views.editor) app.get('/api/layout', middleware.ensureAuthenticated, api.layouts.index) diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js index 4b55f09..f39022f 100644 --- a/server/lib/api/collaborator.js +++ b/server/lib/api/collaborator.js @@ -54,9 +54,9 @@ var collaborator = { return res.json({ error: "can't find project" }) } var data = util.cleanQuery(req.body) - delete data.user_id - + data.email = util.sanitize( data.email ) data.project_id = req.project._id + delete data.user_id Collaborator.makeNonce(function(nonce){ data.nonce = nonce diff --git a/server/lib/views.js b/server/lib/views.js index 4faf80f..7137041 100644 --- a/server/lib/views.js +++ b/server/lib/views.js @@ -57,6 +57,8 @@ views.reader = function (req, res) { date: moment(req.project.updated_at).format("M/DD/YYYY"), author: user.displayName, authorlink: "/profile/" + user.username, + canEdit: req.isOwner || req.isCollaborator, + editlink: "/project/" + req.project.slug + "/edit", noui: !! (req.query.noui === '1'), }) }) diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 448b6d4..035507b 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -1,14 +1,6 @@ -
+
X -
    -
  • -
    - - -
  • -
-
To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet.
@@ -18,4 +10,18 @@ +
    +
+
+ + diff --git a/views/controls/reader/about-room.ejs b/views/controls/reader/about-room.ejs index f990da8..2aa244b 100644 --- a/views/controls/reader/about-room.ejs +++ b/views/controls/reader/about-room.ejs @@ -3,7 +3,12 @@ [[- name ]],
[[- author ]] -

Last modified [[- date ]]

+

+ Last modified [[- date ]] + [[ if (canEdit) { ]] + · Edit + [[ } ]] +

[[- description ]]
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 6d85699..ae5b31f 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -91,6 +91,7 @@ + -- cgit v1.2.3-70-g09d2 From 9257818363269a2893c1a7ee61adb497f749e38f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 18:15:40 -0400 Subject: collab stuff 90% there --- public/assets/img/logo.svg | 49 ++++++++++ .../assets/javascripts/ui/editor/Collaborators.js | 54 ++++++++--- .../assets/javascripts/ui/editor/EditorSettings.js | 12 ++- public/assets/javascripts/ui/editor/EditorView.js | 3 +- public/assets/javascripts/ui/lib/FormView.js | 12 ++- public/assets/stylesheets/app.css | 107 ++++++++++++++++++--- server/lib/api/collaborator.js | 20 ++-- server/lib/auth/mail.js | 2 +- server/lib/schemas/Collaborator.js | 1 + server/lib/views.js | 2 +- views/controls/editor/collaborators.ejs | 29 +++--- views/controls/editor/settings.ejs | 8 +- views/editor.ejs | 1 + views/mail/collaborator.html.ejs | 2 +- views/mail/welcome.html.ejs | 2 +- 15 files changed, 247 insertions(+), 57 deletions(-) create mode 100644 public/assets/img/logo.svg (limited to 'server/lib/api/collaborator.js') diff --git a/public/assets/img/logo.svg b/public/assets/img/logo.svg new file mode 100644 index 0000000..72b904a --- /dev/null +++ b/public/assets/img/logo.svg @@ -0,0 +1,49 @@ + + + +]> + + + + + + + + + + diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js index bb163f8..c27dbe0 100644 --- a/public/assets/javascripts/ui/editor/Collaborators.js +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -4,14 +4,18 @@ var Collaborators = ModalFormView.extend({ template: $("#collaborator-template").html(), - createAction: "/api/collaborator/:slug/create", - destroyAction: "/api/collaborator/:slug/destroy", + indexAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/index" }, + createAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/create" }, + destroyAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/destroy" }, events: { + "keydown [name=email]": "enterSubmit", "click [data-role=destroy-collaborator]": "destroy", }, show: function(){ + this.action = this.createAction + if (! this.loaded) { this.load() } @@ -21,44 +25,70 @@ var Collaborators = ModalFormView.extend({ }, load: function(){ - $.get("/api/collaborator/:slug/index", this.populate.bind(this)) + $.get(this.indexAction(), this.populate.bind(this)) }, populate: function(collaborators){ - // collaborators.forEach(function(collab){ var $el = $( this.template ) - $el.data("collaborator-id", collab.id) - + $el.data("collaborator-id", collab._id) + if (collab.user) { $el.find(".email").remove() $el.find(".user") - .attr("href", "/profile/" + collab.username) + .attr("href", "/profile/" + collab.user.username) $el.find(".avatar") - .css("background-image", "url(" + collab.photo + ")") + .css("background-image", "url(" + collab.user.photo + ")") $el.find(".username") - .html( collab.displayName ) + .html( collab.user.displayName ) + + if (collab.owner) { + $el.find("button").remove() + } + else { + $el.find(".role").remove() + } } else { - $el.remove(".user") + $el.find(".user").remove() + $el.find(".role").remove() $el.find(".email").html( collab.email ) } - $("#collaborators").append($el) + $("#collaborator-list").append($el) }.bind(this)) this.__super__.show.call(this) }, + enterSubmit: function (e) { + e.stopPropagation() + var base = this + if (e.keyCode == 13) { + setTimeout(function(){ + base.save(e) + base.reset() + }, 100) + } + }, + success: function(data){ + this.reset() this.populate([data]) }, destroy: function(e){ - var _id = $(e.currentTarget).closest("li").data("collaborator-id") + var $el = $(e.currentTarget).closest("li") + var _id = $el.data("collaborator-id") + $el.remove() + $.ajax({ + type: "DELETE", + url: this.destroyAction(), + data: { _id: _id, _csrf: $("[name=_csrf]").val() }, + }) }, }) diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index e9239e4..e5dd844 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -9,6 +9,7 @@ var EditorSettings = FormView.extend({ events: { "keydown": 'stopPropagation', "keydown [name=name]": 'enterSubmit', + "click [data-role='show-collaborators']": 'showCollaborators', "click [data-role='save-project']": 'save', "click [data-role='clone-project']": 'clone', "click [data-role='clear-project']": 'clear', @@ -28,7 +29,8 @@ var EditorSettings = FormView.extend({ load: function(data){ this.action = data.isNew ? this.createAction : this.updateAction - + this.parent.data = data + data.rooms && Rooms.deserialize(data.rooms) data.startPosition && scene.camera.move(data.startPosition) @@ -36,7 +38,6 @@ var EditorSettings = FormView.extend({ this.$name.val( "Room " + moment().format("DD/MM/YYYY ha") ) } else { - // console.log(data) this.thumbnailIsStale() this.$id.val( data._id ) @@ -48,6 +49,11 @@ var EditorSettings = FormView.extend({ } }, + showCollaborators: function(e){ + e && e.preventDefault() + this.parent.collaborators.show() + }, + clone: function(){ var names = this.$name.val().split(" ") if ( ! isNaN(Number( names[names.length-1] )) ) { @@ -152,6 +158,8 @@ var EditorSettings = FormView.extend({ Minotaur.hide() window.history.pushState(null, document.title, "/project/" + data.slug + "/edit") + + this.parent.data = data }, }) diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 5fc5147..b75a912 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -31,8 +31,9 @@ var EditorView = View.extend({ ready: function(data){ $("#map").hide() - + this.settings.load(data) + this.collaborators.show() }, readyLayout: function(data){ diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index ab33bc0..17b748a 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -33,7 +33,7 @@ var FormView = View.extend({ }, serialize: function(){ - var fd = new FormData() + var fd = new FormData(), hasCSRF = false this.$("input[name], select[name], textarea[name]").each( function(){ if (this.type == "file") { @@ -48,9 +48,14 @@ var FormView = View.extend({ } else { fd.append(this.name, this.value); + hasCSRF = hasCSRF || this.name == "_csrf" } }); + if (! hasCSRF) { + fd.append("_csrf", $("[name=_csrf]").val()) + } + return fd }, @@ -71,9 +76,12 @@ var FormView = View.extend({ return } } + + var action = typeof this.action == "function" ? this.action() : this.action + if (! action) return var request = $.ajax({ - url: this.action, + url: action, type: this.method, data: this.serialize(), dataType: "json", diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 92eed33..f59635b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1202,13 +1202,13 @@ input[type="range"]::-webkit-slider-thumb { transform: translateY(0px); } -#startpoint { +.modalLink { text-decoration: none; } - -#startpoint:hover { +.modalLink:hover { text-decoration: underline; } + @-webkit-keyframes fade { 50% { opacity:0.6; @@ -1270,7 +1270,7 @@ input[type="range"]::-webkit-slider-thumb { width: 100%; margin-top: 10px; } -.settings .subButtons a{ +.settings .subButtons a { font-size: 12px; font-weight: 300; width: 40px; @@ -1553,12 +1553,15 @@ form li textarea { position: fixed; right: 20px; top: 20px; + z-index: 20; } .close:hover { color:lightgreen; } + + .facebook { width: 100%; display: inline-block; @@ -1652,26 +1655,100 @@ form li textarea { .share a:hover{ text-decoration:underline; } -@-webkit-keyframes borderanimation -{ + +/* COLLABORATORS */ + +.collaborators > div { + width: 600px; + margin: 0 auto; + text-align: left; + background: white; + padding: 10px; + margin: 20px auto; +} +.collaborators button { + width: auto; + position: relative; + top: -2px; +} +.collaborators form { + max-width: none; +} +.collaborators form input[type=submit] { + float: none; + width: 150px; + position: relative; + top: -2px; + font-size: 11px; + + padding: 8px; + border: 1px solid; + font-weight: 500; + background: white; + cursor: pointer; +} +.collaborators form input[type=submit]:hover { + background-color: black; + border-color: black; +} +.collaborators p { + margin: 20px 0; +} +.collaborators form input[type=text] { + font-size: 16px; + width: 300px; +} +.collaborators h2 { + margin: 20px auto 10px; +} +#collaborator-list { + margin-top: 20px; +} +#collaborator-list li { + list-style-type: none; + background: #fff; + padding-top: 4px; +} +#collaborator-list .avatar { + width: 32px; + height: 32px; + background-size: cover; + display: inline-block; + margin-right: 10px; +} +#collaborator-list .username { + position: relative; + top: -10px; +} +#collaborator-list .role { + float: right; + font-style: italic; + margin-top: 5px; + font-weight: 300; +} +#collaborator-list .email { + line-height: 31px; + position: relative; + left: 42px; + font-weight: 300; + font-style: italic; +} + +/* MARCHING ANTS ANIMATION */ + +@-webkit-keyframes borderanimation { 0%{width:600px;} 100%{width:750px;left:2px;} } - -@-webkit-keyframes borderanimationleftright -{ +@-webkit-keyframes borderanimationleftright { 0%{height:250px;} 100%{height:500px;top:2px;} } - -@keyframes borderanimation -{ +@keyframes borderanimation { 0%{width:500px;} 100%{width:750px;left:2px;} } - -@keyframes borderanimationleftright -{ +@keyframes borderanimationleftright { 0%{height:250px;} 100%{height:500px;top:2px;} } diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js index f39022f..c080070 100644 --- a/server/lib/api/collaborator.js +++ b/server/lib/api/collaborator.js @@ -1,20 +1,22 @@ /* jshint node: true */ var _ = require('lodash'), + auth = require('../auth'), util = require('../util'), upload = require('../upload'), config = require('../../../config.json'), + User = require('../schemas/User'), Collaborator = require('../schemas/Collaborator'), Project = require('../schemas/Project'); var collaborator = { join: function(req, res){ - var nonce = req.query.nonce + var nonce = req.params.nonce if (! nonce || ! nonce.length) { return res.json({ error: "invalid invite code" }) } Collaborator.findOne({ nonce: nonce }, function(err, collaborator){ if (err || ! collaborator) { return res.json({ error: "can't find collaborator" }) } - collaborator.user_id = req.user.user_id + collaborator.user_id = req.user._id collaborator.nonce = "" collaborator.save(function(err, collaborator){ Project.findOne({ _id: collaborator.project_id }, function(err, project){ @@ -31,7 +33,7 @@ var collaborator = { if (! req.project) { return res.json({ error: "can't find project" }) } - if (req.project.user_id !== req.user._id) { return res.json({ error: "insufficient permission" }) } + if (String(req.project.user_id) !== String(req.user._id)) { return res.json({ error: "insufficient permission" }) } Collaborator.find({ project_id: req.project._id }, function(err, collaborators){ var user_ids = _.pluck(collaborators, "user_id").filter(function(id){ return !! id }) User.find({ _id: user_ids }, "username displayName photo", function(err, users){ @@ -44,6 +46,7 @@ var collaborator = { obj.user = userIndex[ obj.user_id ] return obj }) + collaborators.unshift( { user: req.user.toObject(), owner: true } ) res.json(collaborators) }) }) @@ -60,11 +63,12 @@ var collaborator = { Collaborator.makeNonce(function(nonce){ data.nonce = nonce + new Collaborator(data).save(function(err, collaborator){ if (err || ! collaborator) { return res.json({ error: err }) } - auth.mail.forgotPassword(req.project, req.user, collaborator, function(){ - res.json(collaborator) - }) + console.log(collaborator) + res.json(collaborator) + auth.mail.collaborator(req.project, req.user, collaborator, function(){}) }) }) }, @@ -73,10 +77,10 @@ var collaborator = { if (! req.project) { return res.json({ error: "can't find project" }) } - if (req.project.user_id !== req.user._id) { + if (String(req.project.user_id) !== String(req.user._id)) { return res.json({ error: "insufficient permission" }) } - Collaborator.remove({ _id: _id }, function(err){ + Collaborator.remove({ _id: req.body._id }, function(err){ res.json({ status: "OK" }) }) } diff --git a/server/lib/auth/mail.js b/server/lib/auth/mail.js index 0211325..0ba6d5d 100644 --- a/server/lib/auth/mail.js +++ b/server/lib/auth/mail.js @@ -81,7 +81,7 @@ var mail = { ] } mail.send(message, cb) - console.log("sent collaborator email to", user.email) + console.log("sent collaborator email to", collaborator.email) }, } diff --git a/server/lib/schemas/Collaborator.js b/server/lib/schemas/Collaborator.js index 79e3287..6b3d452 100644 --- a/server/lib/schemas/Collaborator.js +++ b/server/lib/schemas/Collaborator.js @@ -2,6 +2,7 @@ var mongoose = require('mongoose'), _ = require('lodash'), + crypto = require('crypto'), config = require('../../../config.json'), util = require('../util'); diff --git a/server/lib/views.js b/server/lib/views.js index 7137041..b3c1d18 100644 --- a/server/lib/views.js +++ b/server/lib/views.js @@ -33,7 +33,7 @@ views.editor = function (req, res) { if (! req.project) { res.redirect('/') } - else if (req.isCollaborator || req.isOwner) { + else if (req.isOwner || req.isCollaborator) { res.render('editor') } else { diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 035507b..1386a5c 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -1,27 +1,32 @@
X - +
- To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet. -
+

Collaborators

+ +

+ To invite others to contribute to this project, submit their email address below. They'll receive an email with instructions to join this blog and register if they're not a Vvalls user yet. +

-
- - -
- -
    -
+
+ + +
+ +
    +
+ +
diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index 6f46be3..e4ec7ee 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -3,11 +3,17 @@ +
diff --git a/views/editor.ejs b/views/editor.ejs index 5d1e052..9950878 100755 --- a/views/editor.ejs +++ b/views/editor.ejs @@ -17,6 +17,7 @@ [[ include controls/editor/media-editor ]] [[ include controls/editor/wallpaper ]] [[ include controls/editor/light-control ]] + [[ include controls/editor/collaborators ]] [[ include controls/editor/settings ]]
diff --git a/views/mail/collaborator.html.ejs b/views/mail/collaborator.html.ejs index 5621c1e..2a08a1c 100644 --- a/views/mail/collaborator.html.ejs +++ b/views/mail/collaborator.html.ejs @@ -2,7 +2,7 @@

- +

diff --git a/views/mail/welcome.html.ejs b/views/mail/welcome.html.ejs index 8b7194b..b2c329f 100644 --- a/views/mail/welcome.html.ejs +++ b/views/mail/welcome.html.ejs @@ -2,7 +2,7 @@

- +

-- cgit v1.2.3-70-g09d2 From 5f5fcfee56a4f7067c1b9ccf51e662463b71e7f1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 25 Aug 2014 18:32:45 -0400 Subject: showing the collab url --- .../assets/javascripts/ui/editor/Collaborators.js | 21 +++++++++++++++- public/assets/javascripts/ui/site/SignUpModal.js | 1 - server/lib/api/collaborator.js | 2 +- views/controls/editor/collaborators.ejs | 29 ++++++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) (limited to 'server/lib/api/collaborator.js') diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js index c27dbe0..eee412a 100644 --- a/public/assets/javascripts/ui/editor/Collaborators.js +++ b/public/assets/javascripts/ui/editor/Collaborators.js @@ -29,6 +29,7 @@ var Collaborators = ModalFormView.extend({ }, populate: function(collaborators){ + this.loaded = true collaborators.forEach(function(collab){ var $el = $( this.template ) $el.data("collaborator-id", collab._id) @@ -74,12 +75,30 @@ var Collaborators = ModalFormView.extend({ }, 100) } }, + + validate: function(){ + var errors = [] + + var email = this.$("[name=email]").val() + if (! email.length) { + errors.push("Please enter an email address"); + } + else if (email.indexOf("@") === -1) { + errors.push("Please enter a valid email address"); + } + + return errors + }, success: function(data){ this.reset() this.populate([data]) + // weird! this.$("#collaborator-url") not working here, but works without this + $("#collaborator-url").val("http://vvalls.com/join/" + data.nonce) + this.$("#collaborator-dummy-email").html(data.email) + this.$("#collaborator-url-rapper").slideDown(300) }, - + destroy: function(e){ var $el = $(e.currentTarget).closest("li") var _id = $el.data("collaborator-id") diff --git a/public/assets/javascripts/ui/site/SignUpModal.js b/public/assets/javascripts/ui/site/SignUpModal.js index 5c651ee..a452023 100644 --- a/public/assets/javascripts/ui/site/SignUpModal.js +++ b/public/assets/javascripts/ui/site/SignUpModal.js @@ -34,4 +34,3 @@ var SignUpModal = ModalFormView.extend({ } }) - diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js index c080070..1fda01b 100644 --- a/server/lib/api/collaborator.js +++ b/server/lib/api/collaborator.js @@ -57,7 +57,7 @@ var collaborator = { return res.json({ error: "can't find project" }) } var data = util.cleanQuery(req.body) - data.email = util.sanitize( data.email ) + data.email = util.trim( util.sanitize( data.email ) ) data.project_id = req.project._id delete data.user_id diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 1386a5c..69e5b64 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -13,6 +13,12 @@ +

+ We've sent a link to join this project to . + You can also send this link yourself: + +
+
@@ -30,3 +36,26 @@ owner + + -- cgit v1.2.3-70-g09d2