From 24614e0764ec4655ded8b66ba6832bf8cd3cda1d Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 29 Sep 2014 18:56:38 -0400 Subject: css --- public/assets/stylesheets/app.css | 10 +++------- views/controls/editor/light-control.ejs | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index e136e03..e08cc0b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1302,9 +1302,8 @@ span:hover .swatch { .color-swatches span:nth-child(1),.color-swatches span:nth-child(2){ margin-bottom:5px; } -.color-swatches span.active{ - background:red; - color:white; +.color-swatches span.active, .color-swatches span.active:hover{ + background:#eee; } .color-swatches span:nth-child(3){ clear:left; @@ -1313,9 +1312,6 @@ span:hover .swatch { background:#eee; } -.color-swatches span.active:hover { - background:red; -} .color-swatches label { font-size: 14px; font-weight: 300; @@ -1326,7 +1322,7 @@ span:hover .swatch { top: -2px; } .color-swatches span.active label { - font-weight: 600; + font-weight: 500; } diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index 8b133a5..b90b646 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -3,7 +3,7 @@
-

Brightness Control

+

Luminance Control

-- cgit v1.2.3-70-g09d2 From 746dc328ab759d95935177834525b4a1dfccffff Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 02:53:34 -0400 Subject: forgot $in --- server/lib/views/staff.js | 6 +++--- views/staff/_projects.ejs | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index ffacee2..41877c8 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -143,14 +143,14 @@ var staff = module.exports = { }, ensureObjectsUsers: function(objects, next){ - if (! objects) { return next () } + if (! objects) { return next () } var dedupe = {}, user_ids objects.forEach(function(obj){ dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] dedupe[ obj.user_id ].push(obj) }) user_ids = _.keys(dedupe) - User.find({ _id: user_ids }) + User.find({ _id: { $in: user_ids } }) .select(staff.fields.user) .exec(function (err, users) { if (! users) { return next () } @@ -527,4 +527,4 @@ var staff = module.exports = { }, } -} \ No newline at end of file +} diff --git a/views/staff/_projects.ejs b/views/staff/_projects.ejs index 0fdfcf5..2c3eb9f 100644 --- a/views/staff/_projects.ejs +++ b/views/staff/_projects.ejs @@ -7,11 +7,10 @@ [view] [edit] + [api] - [[ if (project.user) { ]] [[- project.user.username ]] - [[ } ]] [[- project.date ]] -- cgit v1.2.3-70-g09d2 From 166834f03505ec7e766cb5d6d7151310fbf54d49 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 11:47:11 -0400 Subject: profile stuff --- public/assets/stylesheets/app.css | 77 ++++++++++++++++++++++----------------- views/profile.ejs | 20 +++++----- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 299f757..d5dab4f 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -42,6 +42,7 @@ body.pastePaper .wallpaper.active span:hover{ a{ color:black; + text-decoration: none; } /*page*/ @@ -170,10 +171,10 @@ h5 { .page .profilepage, .page .projectList { - width: 100%; - margin: 40px 0 0 0; - border-spacing: 0; - clear: both; + width: 100%; + clear: both; + float:left; + display: inline-block; } .page .showcase { @@ -334,11 +335,12 @@ iframe.embed { } .page h1 { - font-size: 80px; - font-weight: 100; - padding-top: 25px; + font-size: 80px; + font-weight: 100; + padding: 20px 0 25px 0; float: left; width: 100%; + border-top: 1px solid; } /* DOCUMENTATION / ABOUT SECTION / FAQ PAGES */ @@ -380,10 +382,13 @@ iframe.embed { /* PROFILE PAGE */ -.profilepage .profilePic { - font-size: 148px; - background-size: cover; - background-position: center; +.profilePic { + font-size: 148px; + background-size: cover; + background-position: center; + width: 33.3333%; + height: 50vh; + float: left; } .editProfile { margin-right: 10px; @@ -417,13 +422,15 @@ iframe.embed { color: white; } .profilepage .bio { - text-align: left; - padding: 0 5%; - width: 66.5%; - background-image:url(../img/pattern.png); - background-size:100%; - background-color: lightyellow; - box-shadow: -4px 6px 7px rgba(0,0,0,0.1) inset; + text-align: left; + padding: 0 5%; + width: 66.5%; + background-image: url(../img/pattern.png); + background-size: 100%; + background-color: lightyellow; + display: table; + height: 50vh; + float: left; } .profilepage .bio.one { @@ -492,31 +499,35 @@ iframe.embed { background-size: contain; background-repeat: no-repeat; background-color: #fff; - background-image: url(http://upload.wikimedia.org/wikipedia/commons/d/d9/Graceland_Memphis_TN_Floorplan_Basement.jpg); width: 20vw; height: 20vh; display: inline-block; margin: 4vw; - border:1px solid white; + border:1px solid black; position: relative; } .templates span:after { - content: attr(data-name); - position: absolute; - top: 100%; - width: 100%; - left: 0; - background: #fff; - padding: 5px; - border-top: 1px solid black; + content: attr(data-name); + position: absolute; + top: 100%; + width: 100%; + left: 0; + background: #fff; + padding: 5px; + border-top: 1px solid black; + font-weight: 300; } .templates span:hover { - border:1px dashed black; + border:1px solid blue; cursor:pointer; } +.templates span:hover:after { + border-top: 1px solid blue; +} + .templates h1 { font-weight: 300; font-size: 21px; @@ -1304,7 +1315,8 @@ span:hover .swatch { margin-bottom:5px; } .color-swatches span.active, .color-swatches span.active:hover{ - background:#eee; + background:#000; + color:white; } .color-swatches span:nth-child(3){ clear:left; @@ -1322,9 +1334,6 @@ span:hover .swatch { cursor: pointer; top: -2px; } -.color-swatches span.active label { - font-weight: 500; -} .settings.info { @@ -1544,7 +1553,7 @@ button { } #builder-units { - width:100%; + width:75%; } #mediaEditor .warn { width:100%; diff --git a/views/profile.ejs b/views/profile.ejs index ada3d52..34b0bee 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -8,17 +8,17 @@
[[- include partials/header ]] - - +
[[ if (profile.photo && profile.photo.length) { ]] -
+
+
[[ } else { ]] - + [[ } ]] - - -
- +
-
+
+

[[- profile.displayName ]]

[[ if (profile.location) { ]] @@ -35,9 +35,9 @@ @[[- profile.twitterName ]] [[ } ]] -
+
+ + [[ if (projects.length) { ]]

[[- profile.username ]] has [[- projects.length ]] project[[- projects.length != 1 ? "s" : "" ]]

-- cgit v1.2.3-70-g09d2 From 915b0e3c15f59103803bc1514b414b86aff92b6c Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 11:54:03 -0400 Subject: fade thing --- public/assets/stylesheets/app.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index d47f196..3748401 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -196,6 +196,7 @@ iframe.embed { float: left; width: 100%; } + .projectList .room { width: 33.3333%; height:40vh; @@ -203,10 +204,20 @@ iframe.embed { position: relative; float:left; border-top:1px solid black; + } .projectList .room:nth-child(4n+1){ width:100%; } +.projectList .room:hover .holder{ + background: rgba(255,255,255,0); +} +.projectList .holder{ + background: rgba(255,255,255,0.7); + -webkit-transition:2s background; + -moz-transition:2s background; + transition:2s background; +} .page .btn { clear: both; padding: 30px 0; -- cgit v1.2.3-70-g09d2 From b6aa758e4a760c244594dd5bc17004347a66913d Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 11:59:53 -0400 Subject: keep showing resize dots after you click --- .../javascripts/rectangles/engine/scenery/resize.js | 4 ++-- .../rectangles/engine/scenery/types/_object.js | 16 ++++++++-------- public/assets/javascripts/ui/editor/EditorToolbar.js | 4 ++-- public/assets/javascripts/ui/editor/EditorView.js | 4 +++- public/assets/javascripts/ui/editor/MediaEditor.js | 3 +++ 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index e26c0a7..532ca4e 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -124,8 +124,8 @@ Scenery.resize = new function(){ Scenery.resize.hovering = true }, mouseleave: function(e){ - Scenery.resize.hovering = false - base.defer_hide() +// Scenery.resize.hovering = false +// base.defer_hide() } }) }) diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js index 2dbae48..5eed53e 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js @@ -70,17 +70,17 @@ Scenery.types.base = Fiber.extend(function(base){ }, enter: function(e){ - if (editor.permissions.resize) { - Scenery.resize.show(this) - Scenery.hovering = true - } +// if (editor.permissions.resize) { +// Scenery.resize.show(this) +// Scenery.hovering = true +// } }, leave: function(e){ - if (editor.permissions.resize) { - Scenery.resize.defer_hide(this) - Scenery.hovering = false - } +// if (editor.permissions.resize) { +// Scenery.resize.defer_hide(this) +// Scenery.hovering = false +// } }, serialize: function(){ diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index e91da0f..bc56d88 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -39,7 +39,7 @@ var EditorToolbar = View.extend({ }, resetMode: function(){ - this.resizeMedia(false) + this.resizeMedia(true) this.destroyMedia(false) }, @@ -114,7 +114,7 @@ var editor = new function(){ this.permissions = new Permissions({ 'pick': true, 'move': true, - 'resize': false, + 'resize': true, 'destroy': false, }) } \ No newline at end of file diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index e11f189..f200d0f 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -46,6 +46,8 @@ var EditorView = View.extend({ hideExtras: function(){ this.mediaEditor.hide() - } + Scenery.resize.hide() + Scenery.hovering = false + } }) diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index 9b20a43..cb57b69 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -58,6 +58,9 @@ var MediaEditor = FormView.extend({ this.bind(scenery) this.$el.addClass("active") + Scenery.resize.show(scenery) + Scenery.hovering = true + var media = scenery.media this.$name.val(media.title) -- cgit v1.2.3-70-g09d2 From c0c11162c5124f5452fe162b31d708be5ec40fcc Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 12:01:23 -0400 Subject: get rid of resize icon in toolbar --- views/controls/editor/toolbar.ejs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs index 4abf780..d721c07 100644 --- a/views/controls/editor/toolbar.ejs +++ b/views/controls/editor/toolbar.ejs @@ -3,10 +3,12 @@ data-role='open-media-viewer' data-info="add media" class="icon-ios7-photos-outline"> + Date: Tue, 30 Sep 2014 12:32:56 -0400 Subject: labeling some stuff --- public/assets/stylesheets/app.css | 30 +++++++++++++++++------------- views/controls/editor/light-control.ejs | 2 +- views/controls/editor/media-editor.ejs | 1 + views/controls/editor/settings.ejs | 1 + 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 3748401..6929cef 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1247,18 +1247,13 @@ iframe.embed { .lightcontrol { margin-top: 13%; right: 80px; - padding: 20px; + padding: 13px 20px 20px 20px; -webkit-transform: translateX(400px); -webkit-transition: -webkit-transform 0.2s ease-in-out; transform: translateX(400px); transition: -webkit-transform 0.2s ease-in-out; } -.lightcontrol h4 { - font-weight: 600; - font-size: 12px; - line-height: 0; - margin-top: 15px; -} + .lightcontrol.active { -webkit-transform: translateX(0px); transform: translateX(0px); @@ -1278,12 +1273,14 @@ input[type=range] { } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; - background-color: #000; - width: 10px; - height: 10px; + background-color: white; + width: 15px; + height: 15px; border-radius:10px; cursor:pointer; + border:3px solid #000; } + #color-picker { position: relative; } @@ -1353,14 +1350,21 @@ span:hover .swatch { left: 10px; } +.vvbox h4 { + font-weight: 600; + margin-bottom: 10px; + border-bottom: 1px solid #999; + padding-bottom: 6px; +} + .settings { - padding: 20px; + padding: 10px 20px 20px 20px; bottom: 20px; right: 10px; font-size: 12px; - -webkit-transform: translateY(400px); + -webkit-transform: translateY(450px); -webkit-transition: -webkit-transform 0.2s ease-in-out; - transform: translateY(400px); + transform: translateY(450px); transition: -webkit-transform 0.2s ease-in-out; } diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index b90b646..410aaff 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -1,9 +1,9 @@
+

Edit Room Colors

-

Luminance Control

diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs index 000e8db..8f2c1c8 100644 --- a/views/controls/editor/media-editor.ejs +++ b/views/controls/editor/media-editor.ejs @@ -1,4 +1,5 @@
+

Media Settings

diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index ed587fa..ad62b55 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -1,4 +1,5 @@
+

Room Settings

-- cgit v1.2.3-70-g09d2 From 742f4cc410bb04421800d7462f81fc64c59aa0bc Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 12:36:42 -0400 Subject: tracing menu appearing/disappearing logic ; set title from filename --- .../javascripts/rectangles/engine/scenery/move.js | 2 +- .../rectangles/engine/scenery/resize.js | 1 + .../assets/javascripts/rectangles/models/wall.js | 5 ++++- .../assets/javascripts/ui/editor/EditorToolbar.js | 5 ++++- public/assets/javascripts/ui/editor/MediaEditor.js | 23 ++++++++++++++++++---- public/assets/javascripts/util.js | 4 ++++ 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index 93bccb0..55d6ef1 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -142,7 +142,7 @@ Scenery.move = function(base){ if (editor.permissions.resize) { Scenery.resize.rotate_dots() -// Scenery.resize.move_dots() + Scenery.resize.move_dots() } cursor.x.a = cursor.x.b diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index 532ca4e..dc1a39a 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -195,6 +195,7 @@ Scenery.resize = new function(){ } function up (e, cursor){ + if (! dragging) return dragging = false selected_dot = null if (! editor.permissions.resize) { return } diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 1a3ef7c..5513a9b 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -64,7 +64,10 @@ e.stopPropagation() return } - + + Scenery.resize.show(scenery) + Scenery.hovering = true + UndoStack.push({ type: 'create-scenery', undo: { id: scenery.id }, diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index bc56d88..9c74c7c 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -37,15 +37,18 @@ var EditorToolbar = View.extend({ this.resetMode() this.resetControls() }, - + resetMode: function(){ this.resizeMedia(true) this.destroyMedia(false) + app.controller.hideExtras() }, resetControls: function(){ + $(".inuse").removeClass("inuse") this.parent.wallpaperPicker.hide() this.parent.lightControl.hide() + this.parent.settings.hide() }, resizeMedia: function(e, state){ diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index cb57b69..eaa3134 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -3,7 +3,7 @@ var MediaEditor = FormView.extend({ el: "#mediaEditor", events: { - "keydown": 'stopPropagation', + "keydown": 'taint', "focus [name]": "clearMinotaur", "click [data-role=play-media]": "togglePaused", "mousedown [name=keyframe]": "stopPropagation", @@ -58,12 +58,16 @@ var MediaEditor = FormView.extend({ this.bind(scenery) this.$el.addClass("active") +// app.controller.toolbar.resetMode() + app.controller.toolbar.resetControls() Scenery.resize.show(scenery) Scenery.hovering = true var media = scenery.media - this.$name.val(media.title) + console.log(media) + + this.$name.val(media.title || filenameFromUrl(media.url) ) this.$description.val(media.description) this.setDimensions() this.$units.val( "ft" ) @@ -101,12 +105,14 @@ var MediaEditor = FormView.extend({ seek: function(){ var n = parseFloat( this.$keyframe.val() ) this.scenery.seek(n) + this.tainted = true this.scenery.media.keyframe = n }, setAutoplay: function(){ var checked = this.$autoplay.prop('checked') this.scenery.media.autoplay = checked + this.tainted = true if (checked && this.scenery.paused()) { this.togglePaused() } @@ -114,17 +120,20 @@ var MediaEditor = FormView.extend({ setLoop: function(){ var checked = this.$loop.prop('checked') this.scenery.setLoop(checked) + this.tainted = true }, setMute: function(){ var checked = this.$mute.prop('checked') this.scenery.media.mute = checked this.scenery.mute(checked) + this.tainted = true }, setDimensions: function(){ if (! this.scenery) return this.$width.unitVal( Number(this.scenery.naturalDimensions.a * this.scenery.scale) || "" ) this.$height.unitVal( Number(this.scenery.naturalDimensions.b * this.scenery.scale) || "" ) + this.tainted = true }, changeWidth: function(e){ e.stopPropagation() @@ -140,6 +149,11 @@ var MediaEditor = FormView.extend({ app.units = this.$units.val() this.$('.units').resetUnitVal() }, + + taint: function(e){ + e.stopPropagation() + this.tainted = true + }, bind: function(scenery){ this.scenery = scenery @@ -148,7 +162,7 @@ var MediaEditor = FormView.extend({ }, unbind: function(){ - if (this.scenery) { + if (this.scenery && this.tainted) { this.scenery.media.title = this.$name.val() this.scenery.media.description = this.$description.val() Minotaur.watch( app.router.editorView.settings ) @@ -158,11 +172,12 @@ var MediaEditor = FormView.extend({ this.scenery.mx.el.classList.remove("picked") } } + this.tainted = false this.scenery = null }, destroy: function(){ - ConfirmModal.confirm("Are you sure you want delete to this media?", function(){ + ConfirmModal.confirm("Are you sure you want delete this object?", function(){ var scenery = this.scenery this.hide() Scenery.remove(scenery.id) diff --git a/public/assets/javascripts/util.js b/public/assets/javascripts/util.js index 7812a4d..5a89c48 100644 --- a/public/assets/javascripts/util.js +++ b/public/assets/javascripts/util.js @@ -173,6 +173,10 @@ function invert_hash (h) { for (var i in h) { if (h.hasOwnProperty(i)) k[h[i]] = i } return k } +function filenameFromUrl (url) { + var partz = url.split( "/" ) + return partz[partz.length-1].split(".")[0] +} function bitcount(v) { v = v - ((v >>> 1) & 0x55555555); -- cgit v1.2.3-70-g09d2 From 70efc8490ed885317f757eb5252bc14cdcb51a31 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 12:44:42 -0400 Subject: crisper dots --- public/assets/javascripts/rectangles/engine/scenery/resize.js | 3 ++- public/assets/javascripts/ui/editor/EditorSettings.js | 4 ++++ public/assets/javascripts/ui/editor/EditorView.js | 2 +- public/assets/stylesheets/app.css | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index dc1a39a..ca77525 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -31,7 +31,8 @@ Scenery.resize = new function(){ // generate a dot element base.build_dot = function(side) { var dot = new MX.Object3D('.dot') - dot.width = dot.height = dot_side + dot.width = dot.height = dot_side * 2 + dot.scale = 0.5 dot.side = side $(dot.el).on({ mouseenter: function(){ base.hovering = true }, diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index 8a88f7a..f47eb81 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -65,6 +65,10 @@ var EditorSettings = FormView.extend({ data.media && Scenery.deserialize(data.media) } + + app.on("rooms-built", function(){ + Walls.paint() + }) }, showCollaborators: function(e){ diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index f200d0f..6636a8c 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -31,7 +31,7 @@ var EditorView = View.extend({ ready: function(data){ $("#map").hide() - + this.settings.load(data) }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 6929cef..a2db961 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -673,8 +673,8 @@ iframe.embed { .dot { background:white; - border-radius:20px; - border: 1px solid black; + border-radius: 50%; + border: 2px solid black; } .image { -- cgit v1.2.3-70-g09d2 From 385dc017b65cbd7cd94b16e86a8368320d4274ea Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 13:10:08 -0400 Subject: adding prefixfree, bower install --- bower.json | 3 +- .../rectangles/engine/scenery/resize.js | 2 +- .../assets/javascripts/rectangles/models/wall.js | 5 +- .../assets/javascripts/rectangles/util/minotaur.js | 2 +- .../assets/javascripts/ui/editor/EditorToolbar.js | 59 +++++++++++++--------- views/partials/scripts.ejs | 1 + 6 files changed, 44 insertions(+), 28 deletions(-) diff --git a/bower.json b/bower.json index ee8f9ba..faffbfb 100644 --- a/bower.json +++ b/bower.json @@ -7,6 +7,7 @@ "momentjs": "~2.5.1", "lodash": "", "fiber": "", - "jquery-jsonview": "1.2.0" + "jquery-jsonview": "1.2.0", + "prefixfree": "" } } diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index ca77525..96817c2 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -122,7 +122,7 @@ Scenery.resize = new function(){ Scenery.mouse.bind_el(dot.el) $(dot.el).bind({ mouseenter: function(e){ - Scenery.resize.hovering = true +// Scenery.resize.hovering = true }, mouseleave: function(e){ // Scenery.resize.hovering = false diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 5513a9b..2bfb258 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -64,9 +64,10 @@ e.stopPropagation() return } - + + app.controller.toolbar.resetPermissions() Scenery.resize.show(scenery) - Scenery.hovering = true + Scenery.hovering = true UndoStack.push({ type: 'create-scenery', diff --git a/public/assets/javascripts/rectangles/util/minotaur.js b/public/assets/javascripts/rectangles/util/minotaur.js index 0fcc766..4d9a795 100644 --- a/public/assets/javascripts/rectangles/util/minotaur.js +++ b/public/assets/javascripts/rectangles/util/minotaur.js @@ -4,7 +4,7 @@ var base = this base.$el = $("#minotaur") base.timeout = null - base.delay = 1000 + base.delay = 5000 base.objects = {} base.init = function () { diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 9c74c7c..ec6bb46 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -6,7 +6,7 @@ var EditorToolbar = View.extend({ "click [data-role='toggle-map-view']": 'toggleMap', "click [data-role='toggle-project-settings']": 'toggleSettings', "click [data-role='open-media-viewer']": 'openMediaViewer', - "click [data-role='resize-media']": 'resizeMedia', +// "click [data-role='resize-media']": 'resizeMedia', "click [data-role='destroy-media']": 'destroyMedia', "click [data-role='toggle-wallpaper-panel']": 'toggleWallpaper', "click [data-role='toggle-light-control']": 'toggleLightControl', @@ -39,9 +39,10 @@ var EditorToolbar = View.extend({ }, resetMode: function(){ - this.resizeMedia(true) + // this.resizeMedia(true) this.destroyMedia(false) app.controller.hideExtras() + base.resetPermissions() }, resetControls: function(){ @@ -51,27 +52,34 @@ var EditorToolbar = View.extend({ this.parent.settings.hide() }, - resizeMedia: function(e, state){ - this.resetControls() - if (! state && typeof e == "boolean") { - state = e - editor.permissions.assign("resize", state) - } - else { - state = editor.permissions.toggle("resize") - } - ! state && editor.permissions.assign("move", true) - $(".inuse").removeClass("inuse") - $("[data-role='resize-media']").toggleClass("inuse", state) - if (state) { - if (this.parent.mediaEditor.scenery) { - Scenery.resize.show( this.parent.mediaEditor.scenery ) - } - } - else { - Scenery.resize.hide() - } + resetPermissions: function(){ + editor.permissions.assign("pick", true) + editor.permissions.assign("move", true) + editor.permissions.assign("resize", true) + editor.permissions.assign("destroy", false) }, + +// resizeMedia: function(e, state){ +// this.resetControls() +// if (! state && typeof e == "boolean") { +// state = e +// editor.permissions.assign("resize", state) +// } +// else { +// state = editor.permissions.toggle("resize") +// } +// ! state && editor.permissions.assign("move", true) +// $(".inuse").removeClass("inuse") +// $("[data-role='resize-media']").toggleClass("inuse", state) +// if (state) { +// if (this.parent.mediaEditor.scenery) { +// Scenery.resize.show( this.parent.mediaEditor.scenery ) +// } +// } +// else { +// Scenery.resize.hide() +// } +// }, destroyMedia: function(e, state){ this.resetControls() @@ -82,7 +90,12 @@ var EditorToolbar = View.extend({ else { state = editor.permissions.toggle("destroy") } - ! state && editor.permissions.assign("move", true) + if (! state) { + this.resetPermissions() + } + else { + app.controller.hideExtras() + } $(".inuse").removeClass("inuse") $("[data-role='destroy-media']").toggleClass("inuse", state) $("body").toggleClass("destroyActive", state) diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 7d56b2e..e0dd0f5 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -2,6 +2,7 @@ + -- cgit v1.2.3-70-g09d2 From c32a6ff52628fbe0a530b4f72fc907a2ef651127 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 13:18:45 -0400 Subject: fixing points not moving bug --- .../assets/javascripts/rectangles/engine/scenery/resize.js | 2 +- public/assets/javascripts/rectangles/models/wall.js | 2 +- public/assets/javascripts/rectangles/util/permissions.js | 2 +- public/assets/javascripts/ui/editor/EditorToolbar.js | 12 ++++++------ public/assets/javascripts/ui/site/LayoutsModal.js | 1 - 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index 96817c2..2ba84a1 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -147,7 +147,7 @@ Scenery.resize = new function(){ function down (e, cursor){ var selection = dots.filter(function(dot){return e.target == dot.el}) if (! selection.length) return - + selected_dot = selection[0] dragging = true diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 2bfb258..1b37aa0 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -64,7 +64,7 @@ e.stopPropagation() return } - + app.controller.toolbar.resetPermissions() Scenery.resize.show(scenery) Scenery.hovering = true diff --git a/public/assets/javascripts/rectangles/util/permissions.js b/public/assets/javascripts/rectangles/util/permissions.js index 1b5a1b5..9e3ef4d 100644 --- a/public/assets/javascripts/rectangles/util/permissions.js +++ b/public/assets/javascripts/rectangles/util/permissions.js @@ -31,7 +31,7 @@ Permissions.prototype.add = function (key) { Permissions.prototype.remove = function (key) { var base = this - base[key] = true + base[key] = false } Permissions.prototype.clear = function () { diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index ec6bb46..9f439c8 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -41,8 +41,8 @@ var EditorToolbar = View.extend({ resetMode: function(){ // this.resizeMedia(true) this.destroyMedia(false) - app.controller.hideExtras() - base.resetPermissions() + this.parent.hideExtras() + this.resetPermissions() }, resetControls: function(){ @@ -53,10 +53,10 @@ var EditorToolbar = View.extend({ }, resetPermissions: function(){ - editor.permissions.assign("pick", true) - editor.permissions.assign("move", true) - editor.permissions.assign("resize", true) - editor.permissions.assign("destroy", false) + editor.permissions.add("pick") + editor.permissions.add("move") + editor.permissions.add("resize") + editor.permissions.remove("destroy") }, // resizeMedia: function(e, state){ diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 2449465..1bfc6cb 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -29,7 +29,6 @@ var LayoutsIndex = View.extend({ this.$templates.append($span) }.bind(this)) - console.log(this.$templates.html()) this.show() } -- cgit v1.2.3-70-g09d2 From 52284f59cfd973a9fa9e67493a9c540e67412d58 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 13:19:36 -0400 Subject: lines --- public/assets/stylesheets/app.css | 44 ++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index a2db961..ef99608 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -203,9 +203,14 @@ iframe.embed { display:table; position: relative; float:left; - border-top:1px solid black; + border-top:1px solid; +} +.projectList .room:nth-child(4n+3) { + border-left:1px solid black; + border-right:1px solid black; } + .projectList .room:nth-child(4n+1){ width:100%; } @@ -260,11 +265,7 @@ iframe.embed { color:white; } -.projectList .editBtn { - position: absolute; - right: 10px; - top: 10px; -} + /* .room1 { @@ -685,10 +686,10 @@ iframe.embed { /* AUTOSAVE MONITOR */ #minotaur { - position: absolute; - top: 25px; - right: 260px; - opacity: 0; + position: absolute; + top: 0; + right: 230px; + opacity: 0; } #minotaur .label:after { padding: 6px; @@ -696,11 +697,13 @@ iframe.embed { font-weight: 300; } #minotaur.saving { - background: white; - opacity: 1; - z-index: 20; - font-size: 13px; - border: 1px solid; + padding: 20px 8px; + color: white; + background: black; + font-weight: 300; + float: right; + text-decoration: none; + z-index: 33; } #minotaur.saving .label:after { content: 'SAVING'; @@ -1032,17 +1035,21 @@ iframe.embed { } .editBtn{ - color: #FF3B30; + color: red; padding: 3px; font-size: 12px; display: inline-block; cursor:pointer; font-weight:600; text-decoration:none; + position: absolute; + right: 10px; + top: 10px; } .editBtn:hover { - background:black; + background:red; + color:white; } .deleteArmed .mediaDrawer h3 { @@ -1753,6 +1760,9 @@ form li textarea { display: inline-block; padding: 60px 20px; border-radius: 230px; + -webkit-transition:0.2s all; + -moz-transition:0.2s all; + transition:0.2s all; } .hero .circle:hover { -- cgit v1.2.3-70-g09d2 From d929430f16c88b405482a55a93eae9cc4e8dbf76 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 13:37:01 -0400 Subject: delete cursor --- public/assets/img/delete-cursor.png | Bin 0 -> 2635 bytes public/assets/stylesheets/app.css | 8 +++++--- 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 public/assets/img/delete-cursor.png diff --git a/public/assets/img/delete-cursor.png b/public/assets/img/delete-cursor.png new file mode 100644 index 0000000..d7822c8 Binary files /dev/null and b/public/assets/img/delete-cursor.png differ diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index ef99608..70cf498 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -597,6 +597,10 @@ iframe.embed { -webkit-box-sizing: content-box; box-sizing: content-box; } +.destroyActive .mx-scene, .destroyActive .mx-object3d.image { + cursor:url(/assets/img/delete-cursor.png), auto; +} + .mx-scenery:active { cursor: pointer; } @@ -898,9 +902,7 @@ iframe.embed { background-image:url(https://s3.amazonaws.com/luckyplop/735c46b0268cd511a22c37bc0c11e9f60c4459b2.png)!important; cursor:move; } -.deleteActive .mx-object3d.image { - cursor:pointer; -} + .deleteActive .mx-object3d.image:after { content: "\e68f"; font-family: 'ionicons'; -- cgit v1.2.3-70-g09d2 From e3b1885a05f78a41ffc51f60324976c2330a0d20 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 14:11:05 -0400 Subject: fix video resize --- public/assets/javascripts/rectangles/engine/scenery/types/video.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/video.js b/public/assets/javascripts/rectangles/engine/scenery/types/video.js index ef25d8d..76f32ac 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/video.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/video.js @@ -4,8 +4,8 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ var exports = { init: function(opt){ - opt.scale = opt.scale || 300 / max(300, opt.media.width) - + opt.scale = opt.scale || (opt.data && opt.data.scale) || 300 / max(300, opt.media.width) + base.init.call(this, opt) this.build() @@ -106,6 +106,8 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ deserialize: function(data){ this.mx.move(data.position) + this.mx.ops.width = data.dimensions.a + this.mx.ops.height = data.dimensions.b }, } -- cgit v1.2.3-70-g09d2 From ecf6606d7ac31d53fdb2bce8ade3eababc871dbd Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 14:29:26 -0400 Subject: reset --- public/assets/stylesheets/app.css | 38 ++++++++++++++++++++++++++++++------- views/controls/editor/wallpaper.ejs | 2 +- views/editor.ejs | 1 + 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 70cf498..869e5ee 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -597,7 +597,7 @@ iframe.embed { -webkit-box-sizing: content-box; box-sizing: content-box; } -.destroyActive .mx-scene, .destroyActive .mx-object3d.image { +.destroyActive .mx-scene, .destroyActive .mx-object3d.image, .menu span.inuse[data-role="destroy-media"] { cursor:url(/assets/img/delete-cursor.png), auto; } @@ -1127,7 +1127,19 @@ iframe.embed { .mediaContainer img, .mediaContainer video { max-width:100%; } - +#reset { + position: fixed; + bottom: 160px; + left: 20px; + border-bottom: 1px solid black; + padding-bottom: 3px; + z-index:3; +} +#reset:hover { + cursor:pointer; + background:black; + color:white; +} #minimap { position: fixed; bottom: 20px; @@ -1168,6 +1180,7 @@ iframe.embed { -webkit-transform: translateX(400px); transition: transform 0.1s ease-in-out; transform: translateX(400px); + padding: 5px 5px 9px 5px; } .wallpaper.active { display:inline-block; @@ -1192,13 +1205,13 @@ iframe.embed { } .wallpaper .swatches { width: 100%; - border-bottom: 1px solid black; min-height: 30px; } -.wallpaper { - font-size: 14px; - font-weight: 300; + +.wallpaperUpload { + border: 1px solid; } + .wallpaper label { position: relative; top: -6px; @@ -1206,6 +1219,12 @@ iframe.embed { } .wallpaper form { padding: 2px 0 0 0; + font-size: 14px; + font-weight: 300; +} +.wallpaper form:hover { + background:black; + color:white; } .wallpaper .icon-ios7-upload-outline { font-size: 26px; @@ -1367,7 +1386,7 @@ span:hover .swatch { } .settings { - padding: 10px 20px 20px 20px; + padding: 10px 12px 12px 12px; bottom: 20px; right: 10px; font-size: 12px; @@ -1872,6 +1891,11 @@ a[data-role="forgot-password"] { padding:5px 0; display: inline-block; } + +.vvbox .txt { + padding:5px; +} + .aboutRoom h1 a{ text-decoration: none; font-style: italic; diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index 208dfff..95cf827 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -1,5 +1,5 @@
- +

Add Wallpaper

Add custom wallpaper to walls. Begin by uploading a pattern. Or try this one -> diff --git a/views/editor.ejs b/views/editor.ejs index 9950878..d2823fa 100755 --- a/views/editor.ejs +++ b/views/editor.ejs @@ -24,6 +24,7 @@
+
Reset Position
-- cgit v1.2.3-70-g09d2 From d3985f1d76d8d70b5d1e618d1b3150c8baf4d467 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 30 Sep 2014 14:57:55 -0400 Subject: fix settings hiding --- public/assets/javascripts/ui/editor/EditorSettings.js | 3 ++- public/assets/javascripts/ui/editor/EditorToolbar.js | 6 +++--- public/assets/javascripts/ui/editor/MediaViewer.js | 12 ++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index f47eb81..eb0d044 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -113,7 +113,8 @@ var EditorSettings = FormView.extend({ toggle: function(state){ var state = typeof state == 'boolean' ? state : ! this.$el.hasClass("active") this.$el.toggleClass("active", state) - + + $(".inuse").removeClass("inuse") $("[data-role='toggle-project-settings']").toggleClass("inuse", state) }, diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 9f439c8..bb4b145 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -23,8 +23,7 @@ var EditorToolbar = View.extend({ }, toggleSettings: function(){ - this.resetMode() - $(".inuse").removeClass("inuse") +// this.resetMode() this.parent.lightControl.hide() this.parent.wallpaperPicker.hide() this.parent.mediaEditor.hide() @@ -40,7 +39,8 @@ var EditorToolbar = View.extend({ resetMode: function(){ // this.resizeMedia(true) - this.destroyMedia(false) + // this.destroyMedia(false) + $(".inuse").removeClass("inuse") this.parent.hideExtras() this.resetPermissions() }, diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index 436c0cb..15245cf 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -22,17 +22,17 @@ var MediaViewer = ModalView.extend({ }, foundToggle: function(){ - this.foundMedia.addClass("active"); - this.myMedia.addClass("inactive"); + this.$foundMedia.addClass("active"); + this.$myMedia.addClass("inactive"); this.$("a").removeClass("active"); - this.foundToggle.addClass("active"); + this.$foundToggle.addClass("active"); }, userToggle: function(){ - this.foundMedia.removeClass("active"); - this.myMedia.removeClass("inactive"); + this.$foundMedia.removeClass("active"); + this.$myMedia.removeClass("inactive"); this.$("a").removeClass("active"); - this.userToggle.addClass("active"); + this.$userToggle.addClass("active"); }, show: function(){ -- cgit v1.2.3-70-g09d2 From d42fb4d07ad373d4c2523a11fbd535481f1ce265 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 14:57:58 -0400 Subject: delete thing --- public/assets/stylesheets/app.css | 41 +++++++++++++++++++++------------- views/controls/editor/media-drawer.ejs | 2 +- views/controls/editor/media-editor.ejs | 2 +- views/controls/editor/signed-out.ejs | 2 +- views/controls/editor/toolbar.ejs | 2 +- views/controls/reader/about-room.ejs | 2 +- views/editor.ejs | 1 - 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 869e5ee..3464b5c 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -402,16 +402,7 @@ iframe.embed { height: 50vh; float: left; } -.editProfile { - margin-right: 10px; - color: black; - font-weight: 100; - text-decoration: none; - padding: 50px 0 100px 0; -} -.editProfile span { - vertical-align: middle; -} + .topLinks { float: right; z-index: 3; @@ -425,7 +416,7 @@ iframe.embed { padding: 20px 8px; color: black; font-weight: 300; - float:right; + float:left; text-decoration: none; border-bottom:1px solid transparent; } @@ -445,6 +436,10 @@ iframe.embed { float: left; } +.profilepage .bio a:hover { + text-decoration:underline; +} + .profilepage .bio.one { background-color: lightyellow; } @@ -902,7 +897,23 @@ iframe.embed { background-image:url(https://s3.amazonaws.com/luckyplop/735c46b0268cd511a22c37bc0c11e9f60c4459b2.png)!important; cursor:move; } - +#deleteMedia:after { + content:"delete media?"; +} +.deleteArmed #deleteMedia:after { + content:"click media you want to delete"; +} +.deleteArmed #deleteMedia:before { + content: "X"; + background: black; + width: 23px; + height: 23px; + position: absolute; + margin-left: -25px; + margin-top: -4px; + font-size: 19px; + +} .deleteActive .mx-object3d.image:after { content: "\e68f"; font-family: 'ionicons'; @@ -1936,17 +1947,17 @@ a[data-role="forgot-password"] { .share h2 { font-weight: 300; font-size: 18px; - text-align: right; } .share a{ color: #017cfe; text-decoration: none; - margin-left: 6px; font-size: 13px; font-weight: 600; } - +.share a:nth-child(3){ + margin-left:4px; +} .share a:hover{ text-decoration:underline; } diff --git a/views/controls/editor/media-drawer.ejs b/views/controls/editor/media-drawer.ejs index d73a3ef..dbab237 100644 --- a/views/controls/editor/media-drawer.ejs +++ b/views/controls/editor/media-drawer.ejs @@ -17,7 +17,7 @@
X

Your MediaFound Media


-

delete media?

+

diff --git a/views/controls/editor/media-editor.ejs b/views/controls/editor/media-editor.ejs index 8f2c1c8..ef46e6f 100644 --- a/views/controls/editor/media-editor.ejs +++ b/views/controls/editor/media-editor.ejs @@ -52,6 +52,6 @@
diff --git a/views/controls/editor/signed-out.ejs b/views/controls/editor/signed-out.ejs index 20e3715..118fb7c 100644 --- a/views/controls/editor/signed-out.ejs +++ b/views/controls/editor/signed-out.ejs @@ -8,7 +8,7 @@
diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs index d721c07..1c4c26f 100644 --- a/views/controls/editor/toolbar.ejs +++ b/views/controls/editor/toolbar.ejs @@ -8,11 +8,11 @@ data-role='resize-media' data-info="resize media" class="icon-arrow-resize"> - --> + --> diff --git a/views/editor.ejs b/views/editor.ejs index d2823fa..9950878 100755 --- a/views/editor.ejs +++ b/views/editor.ejs @@ -24,7 +24,6 @@
-
Reset Position
-- cgit v1.2.3-70-g09d2 From 515d99f03615b11a5810879e39d34e7bddb043cb Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 14:59:11 -0400 Subject: semi trans file upload --- public/assets/stylesheets/app.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 3464b5c..9ece31e 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -951,7 +951,7 @@ iframe.embed { left: 50%; padding: 26px 20px; margin-left: -200px; - background: white; + background: rgba(255,255,255,0.9); z-index: 4; -webkit-transform: translateY(-1000%); -webkit-transition: -webkit-transform 0.6s ease-in-out; -- cgit v1.2.3-70-g09d2 From c88ab70d90193babda2e06b455fafc05fec54ccb Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 15:22:16 -0400 Subject: updated grid --- public/assets/stylesheets/app.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 9ece31e..8554d59 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -198,7 +198,7 @@ iframe.embed { } .projectList .room { - width: 33.3333%; + width: 50%; height:40vh; display:table; position: relative; @@ -206,13 +206,13 @@ iframe.embed { border-top:1px solid; } -.projectList .room:nth-child(4n+3) { - border-left:1px solid black; +.projectList .room:nth-child(3n+2) { border-right:1px solid black; } -.projectList .room:nth-child(4n+1){ - width:100%; +.projectList .room:nth-child(3n+1) { + width: 100%; + height: 50vh; } .projectList .room:hover .holder{ background: rgba(255,255,255,0); -- cgit v1.2.3-70-g09d2 From 7562a585d47e79fa5fa8a32885f7b4bd29da4a39 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 30 Sep 2014 15:42:25 -0400 Subject: fixed header --- public/assets/stylesheets/app.css | 77 +++++++++------------------------------ views/partials/header.ejs | 9 ++++- views/profile.ejs | 2 +- 3 files changed, 25 insertions(+), 63 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 8554d59..2b6cc3e 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -45,6 +45,15 @@ a{ text-decoration: none; } +#header { + position: fixed; + width: 100%; + top: 0; + left: 0; + background: white; + z-index: 6; +} + /*page*/ .topLogo { @@ -58,9 +67,6 @@ a{ cursor: -moz-grabbing; } -.floatimgImg.edit { - -} .floatingSwatch { width: 50px; @@ -266,57 +272,6 @@ iframe.embed { } - -/* -.room1 { - position: relative; - overflow: hidden; - background-image:url(https://s3.amazonaws.com/luckyplop/7eb159e99924e6e371046d6fa12e566fd77901c9.jpg); -} -.room2 { - background-image:url(https://s3.amazonaws.com/luckyplop/fd4ebe8a7a4246c8273fc999fb1ef0d6a8260b8c.png); -} - -.room1 form textarea { - width: 226px; -} - -.room1 .radio-group { - width: 226px; -} - -.room1 .radio-group__label { - width: 106px; - font-size: 13px; -} - -.room1 .formHolder { - top: 0; - padding-top: 10px; - display: table; - width: 100%; - height: 100%; - background: rgba(255,255,255,0.9); - -webkit-transform:translateY(-100%); - transform:translateY(-100%); -} - -.room1 form { - padding: 0 10px; - max-width: 440px; -} - -.room1 .formInner { - display: table-cell; - vertical-align: middle; -} - -.room1.editing .formHolder { - -webkit-transform:translateY(0); - transform:translateY(0); -} -*/ - .page .questions { background: #55efcb; color:white; @@ -433,6 +388,7 @@ iframe.embed { background-color: lightyellow; display: table; height: 50vh; + border-top: 1px solid; float: left; } @@ -1778,12 +1734,13 @@ form li textarea { } .hero { - float:left; - width:100%; - clear:both; - height:70vh; - display:table; - background-size:cover; + float: left; + width: 100%; + clear: both; + height: 80vh; + display: table; + background-size: cover; + margin-top: 63px; } .hero .circle { font-size: 20px; diff --git a/views/partials/header.ejs b/views/partials/header.ejs index a48c5e1..d46155f 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -1,3 +1,4 @@ + +

Whats VValls For?

+ +
+
+
+ + + +

Plan Your Art Show

+ Whether you're and artist or curator, VValls makes visualizing art within a physical space much easier. With VValls you can build 3D rooms and put your add art to the walls. Map out how your next gallery show will look without having to drill into sheetrock. +
+
+
+ +
+
+ + + +

Defy The Status Quo

+ There is no platform on the internet quite like VValls. Built using advanced HTML5 techniques, VValls opens up the possibilities of expression online. Go crazy, make other worldly rooms. +
+
+
+ +
+
+ + + +

Put on a Show!

+ There's no cooler way than VValls for displaying your images online. Take your pix out of that drab Tumblr theme and present them in the freshest way online! +
+
+
+ +
+

Room Showcase

[[ include projects/list-projects ]] -- cgit v1.2.3-70-g09d2 From c2fe9c3df33d02e6c23c738047faa22662df978b Mon Sep 17 00:00:00 2001 From: ryderr Date: Wed, 1 Oct 2014 14:09:41 -0400 Subject: stylez --- public/assets/stylesheets/app.css | 9 +++------ views/home.ejs | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 1392e05..545207a 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -516,8 +516,10 @@ iframe.embed { .profilepage .bio span { font-size: 16px; font-weight: 300; + float: left; + clear: both; } -.profilepage .bio span:after { content: ' \00b7 ' } + .profilepage .bio span:last-of-type:after { display: none; } .templates { @@ -742,11 +744,6 @@ iframe.embed { .logo { float:left; padding:6px 8px 9px 8px; - z-index:4; - position:relative; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; } .logo:hover { diff --git a/views/home.ejs b/views/home.ejs index 83ed375..885c339 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -50,10 +50,10 @@
- + -

Put on a Show!

+

Put on a Show

There's no cooler way than VValls for displaying your images online. Take your pix out of that drab Tumblr theme and present them in the freshest way online!
-- cgit v1.2.3-70-g09d2 From 4aa421b68f59b383f39661119eabc582976c1d13 Mon Sep 17 00:00:00 2001 From: ryderr Date: Wed, 1 Oct 2014 14:49:11 -0400 Subject: wow --- public/assets/javascripts/app.js | 2 + public/assets/javascripts/vendor/wow.js | 452 +++++ public/assets/stylesheets/animate.css | 3158 +++++++++++++++++++++++++++++++ public/assets/stylesheets/app.css | 1 + views/home.ejs | 8 +- views/partials/meta.ejs | 1 + views/partials/scripts.ejs | 1 + 7 files changed, 3619 insertions(+), 4 deletions(-) create mode 100644 public/assets/javascripts/vendor/wow.js create mode 100644 public/assets/stylesheets/animate.css diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index 1dd8a5e..a6b6088 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -15,6 +15,8 @@ else { $("html").addClass("desktop"); } +new WOW().init(); + var scene, cam, map; var app = new function(){} diff --git a/public/assets/javascripts/vendor/wow.js b/public/assets/javascripts/vendor/wow.js new file mode 100644 index 0000000..83ca71b --- /dev/null +++ b/public/assets/javascripts/vendor/wow.js @@ -0,0 +1,452 @@ +(function() { + var MutationObserver, Util, WeakMap, getComputedStyle, getComputedStyleRX, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + Util = (function() { + function Util() {} + + Util.prototype.extend = function(custom, defaults) { + var key, value; + for (key in defaults) { + value = defaults[key]; + if (custom[key] == null) { + custom[key] = value; + } + } + return custom; + }; + + Util.prototype.isMobile = function(agent) { + return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent); + }; + + Util.prototype.addEvent = function(elem, event, fn) { + if (elem.addEventListener != null) { + return elem.addEventListener(event, fn, false); + } else if (elem.attachEvent != null) { + return elem.attachEvent("on" + event, fn); + } else { + return elem[event] = fn; + } + }; + + Util.prototype.removeEvent = function(elem, event, fn) { + if (elem.removeEventListener != null) { + return elem.removeEventListener(event, fn, false); + } else if (elem.detachEvent != null) { + return elem.detachEvent("on" + event, fn); + } else { + return delete elem[event]; + } + }; + + Util.prototype.innerHeight = function() { + if ('innerHeight' in window) { + return window.innerHeight; + } else { + return document.documentElement.clientHeight; + } + }; + + return Util; + + })(); + + WeakMap = this.WeakMap || this.MozWeakMap || (WeakMap = (function() { + function WeakMap() { + this.keys = []; + this.values = []; + } + + WeakMap.prototype.get = function(key) { + var i, item, _i, _len, _ref; + _ref = this.keys; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + item = _ref[i]; + if (item === key) { + return this.values[i]; + } + } + }; + + WeakMap.prototype.set = function(key, value) { + var i, item, _i, _len, _ref; + _ref = this.keys; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + item = _ref[i]; + if (item === key) { + this.values[i] = value; + return; + } + } + this.keys.push(key); + return this.values.push(value); + }; + + return WeakMap; + + })()); + + MutationObserver = this.MutationObserver || this.WebkitMutationObserver || this.MozMutationObserver || (MutationObserver = (function() { + function MutationObserver() { + if (typeof console !== "undefined" && console !== null) { + console.warn('MutationObserver is not supported by your browser.'); + } + if (typeof console !== "undefined" && console !== null) { + console.warn('WOW.js cannot detect dom mutations, please call .sync() after loading new content.'); + } + } + + MutationObserver.notSupported = true; + + MutationObserver.prototype.observe = function() {}; + + return MutationObserver; + + })()); + + getComputedStyle = this.getComputedStyle || function(el, pseudo) { + this.getPropertyValue = function(prop) { + var _ref; + if (prop === 'float') { + prop = 'styleFloat'; + } + if (getComputedStyleRX.test(prop)) { + prop.replace(getComputedStyleRX, function(_, char) { + return char.toUpperCase(); + }); + } + return ((_ref = el.currentStyle) != null ? _ref[prop] : void 0) || null; + }; + return this; + }; + + getComputedStyleRX = /(\-([a-z]){1})/g; + + this.WOW = (function() { + WOW.prototype.defaults = { + boxClass: 'wow', + animateClass: 'animated', + offset: 0, + mobile: true, + live: true + }; + + function WOW(options) { + if (options == null) { + options = {}; + } + this.scrollCallback = __bind(this.scrollCallback, this); + this.scrollHandler = __bind(this.scrollHandler, this); + this.start = __bind(this.start, this); + this.scrolled = true; + this.config = this.util().extend(options, this.defaults); + this.animationNameCache = new WeakMap(); + } + + WOW.prototype.init = function() { + var _ref; + this.element = window.document.documentElement; + if ((_ref = document.readyState) === "interactive" || _ref === "complete") { + this.start(); + } else { + this.util().addEvent(document, 'DOMContentLoaded', this.start); + } + return this.finished = []; + }; + + WOW.prototype.start = function() { + var box, _i, _len, _ref; + this.stopped = false; + this.boxes = (function() { + var _i, _len, _ref, _results; + _ref = this.element.querySelectorAll("." + this.config.boxClass); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + box = _ref[_i]; + _results.push(box); + } + return _results; + }).call(this); + this.all = (function() { + var _i, _len, _ref, _results; + _ref = this.boxes; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + box = _ref[_i]; + _results.push(box); + } + return _results; + }).call(this); + if (this.boxes.length) { + if (this.disabled()) { + this.resetStyle(); + } else { + _ref = this.boxes; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + box = _ref[_i]; + this.applyStyle(box, true); + } + this.util().addEvent(window, 'scroll', this.scrollHandler); + this.util().addEvent(window, 'resize', this.scrollHandler); + this.interval = setInterval(this.scrollCallback, 50); + } + } + if (this.config.live) { + return new MutationObserver((function(_this) { + return function(records) { + var node, record, _j, _len1, _results; + _results = []; + for (_j = 0, _len1 = records.length; _j < _len1; _j++) { + record = records[_j]; + _results.push((function() { + var _k, _len2, _ref1, _results1; + _ref1 = record.addedNodes || []; + _results1 = []; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + node = _ref1[_k]; + _results1.push(this.doSync(node)); + } + return _results1; + }).call(_this)); + } + return _results; + }; + })(this)).observe(document.body, { + childList: true, + subtree: true + }); + } + }; + + WOW.prototype.stop = function() { + this.stopped = true; + this.util().removeEvent(window, 'scroll', this.scrollHandler); + this.util().removeEvent(window, 'resize', this.scrollHandler); + if (this.interval != null) { + return clearInterval(this.interval); + } + }; + + WOW.prototype.sync = function(element) { + if (MutationObserver.notSupported) { + return this.doSync(this.element); + } + }; + + WOW.prototype.doSync = function(element) { + var box, _i, _len, _ref, _results; + if (!this.stopped) { + if (element == null) { + element = this.element; + } + if (element.nodeType !== 1) { + return; + } + element = element.parentNode || element; + _ref = element.querySelectorAll("." + this.config.boxClass); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + box = _ref[_i]; + if (__indexOf.call(this.all, box) < 0) { + this.applyStyle(box, true); + this.boxes.push(box); + this.all.push(box); + _results.push(this.scrolled = true); + } else { + _results.push(void 0); + } + } + return _results; + } + }; + + WOW.prototype.show = function(box) { + this.applyStyle(box); + return box.className = "" + box.className + " " + this.config.animateClass; + }; + + WOW.prototype.applyStyle = function(box, hidden) { + var delay, duration, iteration; + duration = box.getAttribute('data-wow-duration'); + delay = box.getAttribute('data-wow-delay'); + iteration = box.getAttribute('data-wow-iteration'); + return this.animate((function(_this) { + return function() { + return _this.customStyle(box, hidden, duration, delay, iteration); + }; + })(this)); + }; + + WOW.prototype.animate = (function() { + if ('requestAnimationFrame' in window) { + return function(callback) { + return window.requestAnimationFrame(callback); + }; + } else { + return function(callback) { + return callback(); + }; + } + })(); + + WOW.prototype.resetStyle = function() { + var box, _i, _len, _ref, _results; + _ref = this.boxes; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + box = _ref[_i]; + _results.push(box.setAttribute('style', 'visibility: visible;')); + } + return _results; + }; + + WOW.prototype.customStyle = function(box, hidden, duration, delay, iteration) { + if (hidden) { + this.cacheAnimationName(box); + } + box.style.visibility = hidden ? 'hidden' : 'visible'; + if (duration) { + this.vendorSet(box.style, { + animationDuration: duration + }); + } + if (delay) { + this.vendorSet(box.style, { + animationDelay: delay + }); + } + if (iteration) { + this.vendorSet(box.style, { + animationIterationCount: iteration + }); + } + this.vendorSet(box.style, { + animationName: hidden ? 'none' : this.cachedAnimationName(box) + }); + return box; + }; + + WOW.prototype.vendors = ["moz", "webkit"]; + + WOW.prototype.vendorSet = function(elem, properties) { + var name, value, vendor, _results; + _results = []; + for (name in properties) { + value = properties[name]; + elem["" + name] = value; + _results.push((function() { + var _i, _len, _ref, _results1; + _ref = this.vendors; + _results1 = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + vendor = _ref[_i]; + _results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value); + } + return _results1; + }).call(this)); + } + return _results; + }; + + WOW.prototype.vendorCSS = function(elem, property) { + var result, style, vendor, _i, _len, _ref; + style = getComputedStyle(elem); + result = style.getPropertyCSSValue(property); + _ref = this.vendors; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + vendor = _ref[_i]; + result = result || style.getPropertyCSSValue("-" + vendor + "-" + property); + } + return result; + }; + + WOW.prototype.animationName = function(box) { + var animationName; + try { + animationName = this.vendorCSS(box, 'animation-name').cssText; + } catch (_error) { + animationName = getComputedStyle(box).getPropertyValue('animation-name'); + } + if (animationName === 'none') { + return ''; + } else { + return animationName; + } + }; + + WOW.prototype.cacheAnimationName = function(box) { + return this.animationNameCache.set(box, this.animationName(box)); + }; + + WOW.prototype.cachedAnimationName = function(box) { + return this.animationNameCache.get(box); + }; + + WOW.prototype.scrollHandler = function() { + return this.scrolled = true; + }; + + WOW.prototype.scrollCallback = function() { + var box; + if (this.scrolled) { + this.scrolled = false; + this.boxes = (function() { + var _i, _len, _ref, _results; + _ref = this.boxes; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + box = _ref[_i]; + if (!(box)) { + continue; + } + if (this.isVisible(box)) { + this.show(box); + continue; + } + _results.push(box); + } + return _results; + }).call(this); + if (!(this.boxes.length || this.config.live)) { + return this.stop(); + } + } + }; + + WOW.prototype.offsetTop = function(element) { + var top; + while (element.offsetTop === void 0) { + element = element.parentNode; + } + top = element.offsetTop; + while (element = element.offsetParent) { + top += element.offsetTop; + } + return top; + }; + + WOW.prototype.isVisible = function(box) { + var bottom, offset, top, viewBottom, viewTop; + offset = box.getAttribute('data-wow-offset') || this.config.offset; + viewTop = window.pageYOffset; + viewBottom = viewTop + Math.min(this.element.clientHeight, this.util().innerHeight()) - offset; + top = this.offsetTop(box); + bottom = top + box.clientHeight; + return top <= viewBottom && bottom >= viewTop; + }; + + WOW.prototype.util = function() { + return this._util != null ? this._util : this._util = new Util(); + }; + + WOW.prototype.disabled = function() { + return !this.config.mobile && this.util().isMobile(navigator.userAgent); + }; + + return WOW; + + })(); + +}).call(this); diff --git a/public/assets/stylesheets/animate.css b/public/assets/stylesheets/animate.css new file mode 100644 index 0000000..f784ce8 --- /dev/null +++ b/public/assets/stylesheets/animate.css @@ -0,0 +1,3158 @@ +@charset "UTF-8"; +/*! +Animate.css - http://daneden.me/animate +Licensed under the MIT license - http://opensource.org/licenses/MIT + +Copyright (c) 2014 Daniel Eden +*/ + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.animated.infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +.animated.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; +} + +@-webkit-keyframes bounce { + 0%, 20%, 53%, 80%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + -webkit-transform: translate3d(0,0,0); + transform: translate3d(0,0,0); + } + + 40%, 43% { + -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0); + } + + 70% { + -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0); + } + + 90% { + -webkit-transform: translate3d(0,-4px,0); + transform: translate3d(0,-4px,0); + } +} + +@keyframes bounce { + 0%, 20%, 53%, 80%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + -webkit-transform: translate3d(0,0,0); + transform: translate3d(0,0,0); + } + + 40%, 43% { + -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0); + } + + 70% { + -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0); + } + + 90% { + -webkit-transform: translate3d(0,-4px,0); + transform: translate3d(0,-4px,0); + } +} + +.bounce { + -webkit-animation-name: bounce; + animation-name: bounce; + -webkit-transform-origin: center bottom; + -ms-transform-origin: center bottom; + transform-origin: center bottom; +} + +@-webkit-keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +@keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +.flash { + -webkit-animation-name: flash; + animation-name: flash; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes pulse { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes pulse { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse; +} + +@-webkit-keyframes rubberBand { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(.95, 1.05, 1); + transform: scale3d(.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, .95, 1); + transform: scale3d(1.05, .95, 1); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes rubberBand { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 30% { + -webkit-transform: scale3d(1.25, 0.75, 1); + transform: scale3d(1.25, 0.75, 1); + } + + 40% { + -webkit-transform: scale3d(0.75, 1.25, 1); + transform: scale3d(0.75, 1.25, 1); + } + + 50% { + -webkit-transform: scale3d(1.15, 0.85, 1); + transform: scale3d(1.15, 0.85, 1); + } + + 65% { + -webkit-transform: scale3d(.95, 1.05, 1); + transform: scale3d(.95, 1.05, 1); + } + + 75% { + -webkit-transform: scale3d(1.05, .95, 1); + transform: scale3d(1.05, .95, 1); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.rubberBand { + -webkit-animation-name: rubberBand; + animation-name: rubberBand; +} + +@-webkit-keyframes shake { + 0%, 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +@keyframes shake { + 0%, 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } +} + +.shake { + -webkit-animation-name: shake; + animation-name: shake; +} + +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg); + } + + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg); + } + + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg); + } + + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg); + } + + 100% { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg); + } +} + +@keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg); + } + + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg); + } + + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg); + } + + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg); + } + + 100% { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg); + } +} + +.swing { + -webkit-transform-origin: top center; + -ms-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing; +} + +@-webkit-keyframes tada { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 10%, 20% { + -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes tada { + 0% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + 10%, 20% { + -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + 100% { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.tada { + -webkit-animation-name: tada; + animation-name: tada; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes wobble { + 0% { + -webkit-transform: none; + transform: none; + } + + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + } + + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + } + + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + } + + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + } + + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes wobble { + 0% { + -webkit-transform: none; + transform: none; + } + + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + } + + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + } + + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + } + + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + } + + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +.wobble { + -webkit-animation-name: wobble; + animation-name: wobble; +} + +@-webkit-keyframes bounceIn { + 0%, 20%, 40%, 60%, 80%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97); + } + + 100% { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes bounceIn { + 0%, 20%, 40%, 60%, 80%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97); + } + + 100% { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +.bounceIn { + -webkit-animation-name: bounceIn; + animation-name: bounceIn; + -webkit-animation-duration: .75s; + animation-duration: .75s; +} + +@-webkit-keyframes bounceInDown { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes bounceInDown { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0); + } + + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +.bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown; +} + +@-webkit-keyframes bounceInLeft { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes bounceInLeft { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +.bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft; +} + +@-webkit-keyframes bounceInRight { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +@keyframes bounceInRight { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0); + } + + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0); + } + + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0); + } + + 100% { + -webkit-transform: none; + transform: none; + } +} + +.bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight; +} + +@-webkit-keyframes bounceInUp { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +@keyframes bounceInUp { + 0%, 60%, 75%, 90%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0); + } + + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0); + } + + 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp; +} + +@-webkit-keyframes bounceOut { + 20% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + + 50%, 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } +} + +@keyframes bounceOut { + 20% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + + 50%, 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } +} + +.bounceOut { + -webkit-animation-name: bounceOut; + animation-name: bounceOut; + -webkit-animation-duration: .75s; + animation-duration: .75s; +} + +@-webkit-keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +.bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown; +} + +@-webkit-keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +.bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft; +} + +@-webkit-keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +.bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight; +} + +@-webkit-keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0); + } + + 40%, 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0); + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +.bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp; +} + +@-webkit-keyframes fadeIn { + 0% {opacity: 0;} + 100% {opacity: 1;} +} + +@keyframes fadeIn { + 0% {opacity: 0;} + 100% {opacity: 1;} +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +@-webkit-keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +@-webkit-keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig; +} + +@-webkit-keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +@-webkit-keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig; +} + +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +@-webkit-keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig; +} + +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig; +} + +@-webkit-keyframes fadeOut { + 0% {opacity: 1;} + 100% {opacity: 0;} +} + +@keyframes fadeOut { + 0% {opacity: 1;} + 100% {opacity: 0;} +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes fadeOutDown { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +@-webkit-keyframes fadeOutDownBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +@keyframes fadeOutDownBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } +} + +.fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig; +} + +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes fadeOutLeft { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +@-webkit-keyframes fadeOutLeftBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +@keyframes fadeOutLeftBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0); + } +} + +.fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig; +} + +@-webkit-keyframes fadeOutRight { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@keyframes fadeOutRight { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +@-webkit-keyframes fadeOutRightBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +@keyframes fadeOutRightBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0); + } +} + +.fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig; +} + +@-webkit-keyframes fadeOutUp { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes fadeOutUp { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes fadeOutUpBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +@keyframes fadeOutUpBig { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0); + } +} + +.fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig; +} + +@-webkit-keyframes flip { + 0% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) scale3d(.95, .95, .95); + transform: perspective(400px) scale3d(.95, .95, .95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +@keyframes flip { + 0% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) scale3d(.95, .95, .95); + transform: perspective(400px) scale3d(.95, .95, .95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +.animated.flip { + -webkit-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip; +} + +@-webkit-keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + + 100% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + } + + 100% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +.flipInX { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInX; + animation-name: flipInX; +} + +@-webkit-keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + } + + 100% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +@keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + } + + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1; + } + + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + } + + 100% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } +} + +.flipInY { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInY; + animation-name: flipInY; +} + +@-webkit-keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +@keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0; + } +} + +.flipOutX { + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + -webkit-animation-duration: .75s; + animation-duration: .75s; + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; +} + +@-webkit-keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0; + } +} + +@keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px); + transform: perspective(400px); + } + + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0; + } +} + +.flipOutY { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY; + -webkit-animation-duration: .75s; + animation-duration: .75s; +} + +@-webkit-keyframes lightSpeedIn { + 0% { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + opacity: 1; + } + + 100% { + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes lightSpeedIn { + 0% { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1; + } + + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + opacity: 1; + } + + 100% { + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.lightSpeedIn { + -webkit-animation-name: lightSpeedIn; + animation-name: lightSpeedIn; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} + +@-webkit-keyframes lightSpeedOut { + 0% { + opacity: 1; + } + + 100% { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} + +@keyframes lightSpeedOut { + 0% { + opacity: 1; + } + + 100% { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0; + } +} + +.lightSpeedOut { + -webkit-animation-name: lightSpeedOut; + animation-name: lightSpeedOut; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} + +@-webkit-keyframes rotateIn { + 0% { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes rotateIn { + 0% { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn; +} + +@-webkit-keyframes rotateInDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes rotateInDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft; +} + +@-webkit-keyframes rotateInDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes rotateInDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight; +} + +@-webkit-keyframes rotateInUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes rotateInUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft; +} + +@-webkit-keyframes rotateInUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes rotateInUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight; +} + +@-webkit-keyframes rotateOut { + 0% { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1; + } + + 100% { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0; + } +} + +@keyframes rotateOut { + 0% { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1; + } + + 100% { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0; + } +} + +.rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut; +} + +@-webkit-keyframes rotateOutDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } +} + +@keyframes rotateOutDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0; + } +} + +.rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft; +} + +@-webkit-keyframes rotateOutDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +@keyframes rotateOutDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +.rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight; +} + +@-webkit-keyframes rotateOutUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +@keyframes rotateOutUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0; + } +} + +.rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft; +} + +@-webkit-keyframes rotateOutUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0; + } +} + +.rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight; +} + +@-webkit-keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40%, 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + 100% { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} + +@keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40%, 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + 100% { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0; + } +} + +.hinge { + -webkit-animation-name: hinge; + animation-name: hinge; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +.rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + } +} + +@keyframes rollOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + } +} + +.rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut; +} + +@-webkit-keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + + 50% { + opacity: 1; + } +} + +@keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + + 50% { + opacity: 1; + } +} + +.zoomIn { + -webkit-animation-name: zoomIn; + animation-name: zoomIn; +} + +@-webkit-keyframes zoomInDown { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +@keyframes zoomInDown { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +.zoomInDown { + -webkit-animation-name: zoomInDown; + animation-name: zoomInDown; +} + +@-webkit-keyframes zoomInLeft { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +@keyframes zoomInLeft { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +.zoomInLeft { + -webkit-animation-name: zoomInLeft; + animation-name: zoomInLeft; +} + +@-webkit-keyframes zoomInRight { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +@keyframes zoomInRight { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +.zoomInRight { + -webkit-animation-name: zoomInRight; + animation-name: zoomInRight; +} + +@-webkit-keyframes zoomInUp { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +@keyframes zoomInUp { + 0% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +.zoomInUp { + -webkit-animation-name: zoomInUp; + animation-name: zoomInUp; +} + +@-webkit-keyframes zoomOut { + 0% { + opacity: 1; + } + + 50% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + + 100% { + opacity: 0; + } +} + +@keyframes zoomOut { + 0% { + opacity: 1; + } + + 50% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + + 100% { + opacity: 0; + } +} + +.zoomOut { + -webkit-animation-name: zoomOut; + animation-name: zoomOut; +} + +@-webkit-keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +@keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +.zoomOutDown { + -webkit-animation-name: zoomOutDown; + animation-name: zoomOutDown; +} + +@-webkit-keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.1) translate3d(-2000px, 0, 0); + transform: scale(.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center; + } +} + +@keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.1) translate3d(-2000px, 0, 0); + transform: scale(.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center; + } +} + +.zoomOutLeft { + -webkit-animation-name: zoomOutLeft; + animation-name: zoomOutLeft; +} + +@-webkit-keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.1) translate3d(2000px, 0, 0); + transform: scale(.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center; + } +} + +@keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.1) translate3d(2000px, 0, 0); + transform: scale(.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center; + } +} + +.zoomOutRight { + -webkit-animation-name: zoomOutRight; + animation-name: zoomOutRight; +} + +@-webkit-keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +@keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); + } + + 100% { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); + } +} + +.zoomOutUp { + -webkit-animation-name: zoomOutUp; + animation-name: zoomOutUp; +} + +@-webkit-keyframes slideInDown { + 0% { + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes slideInDown { + 0% { + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +.slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown; +} + +@-webkit-keyframes slideInLeft { + 0% { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes slideInLeft { + 0% { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +.slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft; +} + +@-webkit-keyframes slideInRight { + 0% { + -webkit-transform: translateX(100%); + transform: translateX(100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes slideInRight { + 0% { + -webkit-transform: translateX(100%); + transform: translateX(100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +.slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight; +} + +@-webkit-keyframes slideInUp { + 0% { + -webkit-transform: translateY(100%); + transform: translateY(100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes slideInUp { + 0% { + -webkit-transform: translateY(100%); + transform: translateY(100%); + visibility: visible; + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +.slideInUp { + -webkit-animation-name: slideInUp; + animation-name: slideInUp; +} + +@-webkit-keyframes slideOutDown { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateY(100%); + transform: translateY(100%); + } +} + +@keyframes slideOutDown { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateY(100%); + transform: translateY(100%); + } +} + +.slideOutDown { + -webkit-animation-name: slideOutDown; + animation-name: slideOutDown; +} + +@-webkit-keyframes slideOutLeft { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + } +} + +@keyframes slideOutLeft { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + } +} + +.slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft; +} + +@-webkit-keyframes slideOutRight { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateX(100%); + transform: translateX(100%); + } +} + +@keyframes slideOutRight { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateX(100%); + transform: translateX(100%); + } +} + +.slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight; +} + +@-webkit-keyframes slideOutUp { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + } +} + +@keyframes slideOutUp { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + visibility: hidden; + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + } +} + +.slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp; +} diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 05b4871..ebe307a 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -17,6 +17,7 @@ body{ overflow-x:hidden; } + body.noOverflow{ overflow:hidden; } diff --git a/views/home.ejs b/views/home.ejs index 885c339..3c1a1dc 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -15,7 +15,7 @@
- + Create 3D Rooms

Watch video. @@ -26,7 +26,7 @@

Whats VValls For?

-
+
@@ -37,7 +37,7 @@
-
+
@@ -48,7 +48,7 @@
-
+
diff --git a/views/partials/meta.ejs b/views/partials/meta.ejs index 9916b34..4e94a5e 100644 --- a/views/partials/meta.ejs +++ b/views/partials/meta.ejs @@ -32,6 +32,7 @@ +
diff --git a/views/controls/editor/text-editor.ejs b/views/controls/editor/text-editor.ejs new file mode 100644 index 0000000..205fbdf --- /dev/null +++ b/views/controls/editor/text-editor.ejs @@ -0,0 +1,32 @@ +
+

Edit Text

+ +
+ + +
+ +
+ +
+ + +
+ + \ No newline at end of file diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs index 63df73c..92807e1 100644 --- a/views/controls/editor/toolbar.ejs +++ b/views/controls/editor/toolbar.ejs @@ -12,9 +12,8 @@ data-role='destroy-media' data-info="delete media" class="icon-ios7-trash-outline"> - --> @@ -26,6 +25,13 @@ data-role='toggle-light-control' data-info="edit room colors" class="icon-ios7-sunny-outline"> + +[[ if (user.username == "test12343") { ]] + +[[ } ]] diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 88d832d..065385d 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -67,7 +67,10 @@ [[ } else if (! profile) { ]] Profile [[ } ]] + + [[ if (opt.editing) { ]] + [[ } ]] [[ } else { ]] diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 2e2d8b6..1ce180a 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -100,6 +100,7 @@ + -- cgit v1.2.3-70-g09d2 From 52cabd89039fa852cbd59db9b8bfcb29e1e0a170 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 2 Oct 2014 11:25:15 -0400 Subject: add project photo --- views/projects/list-projects.ejs | 1 + 1 file changed, 1 insertion(+) diff --git a/views/projects/list-projects.ejs b/views/projects/list-projects.ejs index a9f9523..5694648 100644 --- a/views/projects/list-projects.ejs +++ b/views/projects/list-projects.ejs @@ -6,6 +6,7 @@ + [[ mediaCount = 0 ]] [[ project.media.some(function(media){ ]] [[ if (media.media.type != "image") { return false } ]] -- cgit v1.2.3-70-g09d2 From 7767259acb90375f55b15ad906e3d434219d43fc Mon Sep 17 00:00:00 2001 From: ryderr Date: Thu, 2 Oct 2014 12:26:38 -0400 Subject: no border on side --- public/assets/stylesheets/app.css | 15 +++++---------- views/home.ejs | 2 +- views/partials/header.ejs | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index fbe9140..e278fab 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -69,6 +69,10 @@ a{ } #help-button { display: none; + border-right:0px!important; +} +.editProfile, .profileLink { + border-right:0px!important; } .editing #help-button { display: inline; @@ -318,15 +322,6 @@ iframe.embed { width: 100%; height: 50vh; } -.projectList .room:hover .holder{ - background: rgba(255,255,255,0); -} -.projectList .holder{ - background: rgba(255,255,255,0.7); - -webkit-transition:2s background; - -moz-transition:2s background; - transition:2s background; -} .room .images { position: absolute; @@ -491,7 +486,7 @@ iframe.embed { border-right:1px solid; } -.topLinks a:last-child { +.page .topLinks a:last-child { border-right:0px solid; } .topLinks a:hover { diff --git a/views/home.ejs b/views/home.ejs index 76b6cea..47c13e4 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -63,7 +63,7 @@

Room Showcase

- + [[ include projects/list-projects ]] View More diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 88d832d..c946037 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -65,7 +65,7 @@ [[ if (profile && String(user._id) == String(profile._id)) { ]] Settings [[ } else if (! profile) { ]] - Profile + Profile [[ } ]] -- cgit v1.2.3-70-g09d2 From 7990eabde341aa44f20f22927954bca6783dc60f Mon Sep 17 00:00:00 2001 From: ryderr Date: Thu, 2 Oct 2014 12:59:36 -0400 Subject: demo thumbnail display --- views/home.ejs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/views/home.ejs b/views/home.ejs index 47c13e4..a6f5a88 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -62,9 +62,10 @@

Room Showcase

- + + View More [[ include partials/confirm-modal ]] -- cgit v1.2.3-70-g09d2 From 6e5dbdeb78b72bf9775ed2ea233db0b2ad8b5e41 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 2 Oct 2014 13:03:24 -0400 Subject: get coordinates for point --- .../assets/javascripts/rectangles/models/wall.js | 8 ++++++ .../assets/javascripts/rectangles/util/coords.js | 33 ++++++++++++++++++++++ views/partials/scripts.ejs | 3 ++ 3 files changed, 44 insertions(+) create mode 100644 public/assets/javascripts/rectangles/util/coords.js diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 1b37aa0..07c3971 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -51,6 +51,14 @@ }) }, mousemove: function(e){ + var offset = offsetFromPoint(e, mx.el) + if (offset) { + console.log([offset.left * mx.width + mx.face.x.a, (1-offset.top) * mx.height + mx.face.y.a].map(Math.round)) +// console.log(mx) + } + else { + console.log("NONE") + } }, mousedown: function(e){ if (Scenery.nextMedia) { diff --git a/public/assets/javascripts/rectangles/util/coords.js b/public/assets/javascripts/rectangles/util/coords.js new file mode 100644 index 0000000..74b7fda --- /dev/null +++ b/public/assets/javascripts/rectangles/util/coords.js @@ -0,0 +1,33 @@ +function offsetFromPoint(event, element) { + function a(width) { + var l = 0, r = 200; + while (r - l > 0.0001) { + var mid = (r + l) / 2; + var a = document.createElement('div'); + a.style.cssText = 'position: absolute;left:0;top:0;background: red;z-index: 1000;'; + a.style[width ? 'width' : 'height'] = mid.toFixed(3) + '%'; + a.style[width ? 'height' : 'width'] = '100%'; + element.appendChild(a); + var x = document.elementFromPoint(event.clientX, event.clientY); + element.removeChild(a); + if (x === a) { + r = mid; + } else { + if (r === 200) { + return null; + } + l = mid; + } + } + return mid; + } + var l = a(1), + t = a(0); + return l && t ? { + left: l / 100, + top: t / 100, + toString: function () { + return 'left: ' + l + '%, top: ' + t + '%'; + } + } : null; +} diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 1ce180a..5ddab2a 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -21,8 +21,10 @@ + + @@ -33,6 +35,7 @@ + -- cgit v1.2.3-70-g09d2 From b512bcdfe49e0bce336f848dcf620c3c533e1f8c Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 2 Oct 2014 13:12:40 -0400 Subject: saving icon --- public/assets/javascripts/rectangles/engine/scenery/move.js | 1 + public/assets/javascripts/rectangles/util/minotaur.js | 2 +- public/assets/stylesheets/app.css | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index 55d6ef1..e7ca4ef 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -88,6 +88,7 @@ Scenery.move = function(base){ } function up (e, cursor){ + console.log(dragging, oldState) if (! dragging || ! oldState) return dragging = false diff --git a/public/assets/javascripts/rectangles/util/minotaur.js b/public/assets/javascripts/rectangles/util/minotaur.js index 4d9a795..d165ccc 100644 --- a/public/assets/javascripts/rectangles/util/minotaur.js +++ b/public/assets/javascripts/rectangles/util/minotaur.js @@ -4,7 +4,7 @@ var base = this base.$el = $("#minotaur") base.timeout = null - base.delay = 5000 + base.delay = 2500 base.objects = {} base.init = function () { diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index e278fab..57ca3c6 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -757,8 +757,8 @@ iframe.embed { #minotaur { position: absolute; - top: 0; - right: 230px; + top: 0px; + right: 0px; opacity: 0; } #minotaur .label:after { @@ -771,9 +771,9 @@ iframe.embed { color: white; background: black; font-weight: 300; - float: right; text-decoration: none; z-index: 33; + opacity: 1; } #minotaur.saving .label:after { content: 'SAVING'; -- cgit v1.2.3-70-g09d2 From d584725202624b2629a85dd209cebc701706ff4b Mon Sep 17 00:00:00 2001 From: ryderr Date: Thu, 2 Oct 2014 13:19:23 -0400 Subject: save position --- public/assets/stylesheets/app.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 57ca3c6..63d5a9f 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -758,7 +758,7 @@ iframe.embed { #minotaur { position: absolute; top: 0px; - right: 0px; + left: 150px; opacity: 0; } #minotaur .label:after { -- cgit v1.2.3-70-g09d2 From fe5ac8ac5921bcc47edd3cd7748414f5ecba0a9f Mon Sep 17 00:00:00 2001 From: ryderr Date: Thu, 2 Oct 2014 13:42:22 -0400 Subject: collaborators touchup --- package.json | 3 ++- public/assets/stylesheets/app.css | 17 +++++++++++++---- views/controls/editor/collaborators.ejs | 10 ++++++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index b4ac400..adefb82 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "multer": "~0.1.0", "body-parser": "1.3.0", "marked": "~0.3.2", - "emailjs": "~0.3.6" + "emailjs": "~0.3.6", + "intro.js": "^0.9.0" }, "devDependencies": { "grunt": "~0.4.1", diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 63d5a9f..3edad4f 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -2087,14 +2087,22 @@ a[data-role="forgot-password"] { /* COLLABORATORS */ -.collaborators > div { - width: 600px; +.collaborators .rap { + display: table; + width: 100%; + height: 100%; +} + +.collaborators .rap .holder .inner { + width: 480px; margin: 0 auto; text-align: left; background: white; padding: 10px; margin: 20px auto; +position: relative; } + .collaborators button { width: auto; position: relative; @@ -2121,14 +2129,15 @@ a[data-role="forgot-password"] { border-color: black; } .collaborators p { - margin: 20px 0; + margin: 10px 0 20px; + font-weight: 300; } .collaborators form input[type=text] { font-size: 16px; width: 300px; } .collaborators h2 { - margin: 20px auto 10px; + margin: 20px auto 0; } #collaborator-list { margin-top: 20px; diff --git a/views/controls/editor/collaborators.ejs b/views/controls/editor/collaborators.ejs index 69e5b64..b658bf6 100644 --- a/views/controls/editor/collaborators.ejs +++ b/views/controls/editor/collaborators.ejs @@ -1,7 +1,9 @@
X - -
+ +
+
+

Collaborators

@@ -21,9 +23,9 @@

-
- +
+
+ -- cgit v1.2.3-70-g09d2 From 49ce8683ce072d8ae24176aff7fadbf5195f5922 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 7 Oct 2014 16:48:11 -0400 Subject: wallpaper buttons --- public/assets/stylesheets/app.css | 12 +++++++----- views/controls/editor/wallpaper.ejs | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 6a034ea..943fc8e 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1332,7 +1332,7 @@ iframe.embed { padding-bottom: 6px; } -.wallpaperUpload, .wallpaperRemove { +.toolButton { border: 1px solid; display: inline-block; width: 100%; @@ -1341,9 +1341,9 @@ iframe.embed { font-weight: 300; } -.wallpaper label { +.toolButton label { position: relative; - top: -6px; + vertical-align: middle; float: none; } .wallpaper form { @@ -1357,8 +1357,10 @@ iframe.embed { color:white; cursor:pointer; } -.wallpaper .ion-ios7-upload-outline { - font-size: 26px; +.toolButton > span, .toolButton form > span{ + font-size: 26px; + margin: 0 7px; + vertical-align: middle; } .wallpaper .wallpaperRemove { cursor: pointer; diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index 01cf771..97a9232 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -5,7 +5,7 @@ -
+
@@ -16,13 +16,13 @@ -->
-
+
-
- +
+
-- cgit v1.2.3-70-g09d2 From 646b9a935b4fbcc7b0108a66fe7309a61c55d3c1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 16:52:43 -0400 Subject: tiling wallpaper on ceiling / floor --- .../javascripts/rectangles/engine/rooms/grouper.js | 2 ++ public/assets/javascripts/rectangles/models/floor.js | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/rooms/grouper.js b/public/assets/javascripts/rectangles/engine/rooms/grouper.js index ec776a2..890a476 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/grouper.js +++ b/public/assets/javascripts/rectangles/engine/rooms/grouper.js @@ -171,10 +171,12 @@ base.groupFloors = function(floors, collections){ var floor = new Floor ({ id: 'floor', + side: FLOOR, mx: collections[FLOOR] }) var ceiling = new Floor ({ id: 'ceiling', + side: CEILING, mx: collections[CEILING] }) floors.push(floor) diff --git a/public/assets/javascripts/rectangles/models/floor.js b/public/assets/javascripts/rectangles/models/floor.js index ee264c7..78e9019 100644 --- a/public/assets/javascripts/rectangles/models/floor.js +++ b/public/assets/javascripts/rectangles/models/floor.js @@ -32,11 +32,10 @@ Floor.prototype.bind = function(){ var base = this base.$els = $( this.mx.map(function(mx){ return mx.el }) ) - console.log("HELLO") + this.mx.forEach(function(mx, index){ $(mx.el).bind({ mousedown: function(e){ - console.log("clicked on", base.id) if (Scenery.nextWallpaper) { var oldState = base.serialize() base.wallpaper(Scenery.nextWallpaper) @@ -119,22 +118,23 @@ var w = Math.round( this.backgroundImage.naturalWidth * this.background.scale ) var h = Math.round( this.backgroundImage.naturalHeight * this.background.scale ) - this.surface.faces.forEach(function(face, i){ + this.mx.forEach(function(mx, i){ + + var region = mx.rect if (shouldFlip) { - mx = this.mx[this.mx.length-1-i] - dx = Math.round( this.background.x + face.x.a ) - dy = Math.round( this.background.y + face.y.b ) + dx = Math.round( this.background.x - region.x.a ) + dy = Math.round( this.background.y - region.y.a ) } else { - mx = this.mx[i] - dx = Math.round( this.background.x - face.x.b ) - dy = Math.round( this.background.y + face.y.b ) + dx = Math.round( this.background.x - region.x.a ) + dy = Math.round( this.background.y + region.y.b ) } mx.el.style.backgroundPosition = dx + 'px ' + dy + 'px' mx.el.style.backgroundSize = w + 'px ' + h + 'px' }.bind(this)) + bbb = this } if ('window' in this) { -- cgit v1.2.3-70-g09d2 From a672e348038e06a439a8135d9a2e0254f54c2aae Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 7 Oct 2014 16:58:17 -0400 Subject: wallpaper stuff --- public/assets/stylesheets/app.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 943fc8e..2d966ee 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1346,13 +1346,16 @@ iframe.embed { vertical-align: middle; float: none; } +.wallpaperUpload:hover { + cursor:pointer; +} .wallpaper form { position: relative; padding: 2px 0 0 0; font-size: 14px; font-weight: 300; } -.wallpaper form:hover, .wallpaperRemove:hover { +.toolButton:hover { background:black; color:white; cursor:pointer; -- cgit v1.2.3-70-g09d2 From 8a0f5258f0d03cf121d6fde49c5c7731c2212154 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 17:03:37 -0400 Subject: storing floor/ceiling wallpaper --- .../assets/javascripts/rectangles/engine/rooms/_walls.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/rooms/_walls.js b/public/assets/javascripts/rectangles/engine/rooms/_walls.js index b3611c8..7438cd4 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_walls.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_walls.js @@ -80,16 +80,20 @@ } base.forEach = function(f){ - return base.list.forEach(f) + return base.values().forEach(f) } base.map = function(f){ - return base.list.map(f) + return base.values().map(f) + } + + base.values = function(){ + return _.values(base.lookup) } base.serialize = function(){ var data = [] - base.list.forEach(function(wall){ + base.forEach(function(wall){ data.push(wall.serialize()) }) return data @@ -108,7 +112,7 @@ var outlineColor = rgb_string(Walls.colors.outline) var floorColor = rgb_string(Walls.colors.floor) var ceilingColor = rgb_string(Walls.colors.ceiling) - Walls.forEach(function(wall){ + Walls.list.forEach(function(wall){ wall.outline(wallColor, outlineColor) }) Rooms.forEach(function(room){ @@ -122,7 +126,7 @@ wall: function(rgb){ var rgbaColor = rgba_string(rgb, app.defaults.wallOpacity) Walls.colors.wall = rgb - Walls.forEach(function(wall){ + Walls.list.forEach(function(wall){ wall.outline(rgbaColor, null) }) }, @@ -130,7 +134,7 @@ outline: function(rgb){ var rgbColor = rgb_string(rgb) Walls.colors.outline = rgb - Walls.forEach(function(wall){ + Walls.list.forEach(function(wall){ wall.outline(null, rgbColor) }) }, -- cgit v1.2.3-70-g09d2 From 24cc36bf81987c721aee4dae57a64edf5dd515bb Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 7 Oct 2014 17:18:40 -0400 Subject: delete icon --- public/assets/stylesheets/app.css | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 2d966ee..0831a36 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1188,22 +1188,24 @@ iframe.embed { } .deleteArmed .mediaContainer:before { - content: "\e68f"; - font-family: 'ionicons'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - font-size: 60px; - margin-top: -62px; - position: absolute; - background: #FF3B30; - border-radius: 1000px; - margin-left: -59px; - color: white; + content: "\f1eb"; + font-family: 'ionicons'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + -webkit-font-smoothing: antialiased; + font-size: 40px; + margin-top: -62px; + position: absolute; + background: #FF3B30; + border-radius: 1000px; + margin-left: -59px; + color: white; + width: 50px; + height: 50px; + line-height: 50px; } .deleteArmed .mediaContainer.deleted { -- cgit v1.2.3-70-g09d2 From eb1d33b2c32c15821a6307306ca46fda262eb8b9 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 17:26:29 -0400 Subject: no projects --- views/profile.ejs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/views/profile.ejs b/views/profile.ejs index 22c824c..b64e1d5 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -41,11 +41,15 @@ [[ if (projects.length) { ]]

[[- profile.username ]] has [[- projects.length ]] project[[- projects.length != 1 ? "s" : "" ]]

- [[ } ]] - [[ include projects/list-projects ]] + [[ include projects/list-projects ]] - view more + view more + [[ } else { ]] +

Welcome to VVALLS

+

+ You don't have any projects yet. To get started click "New Project" up at the top of the screen. + [[ } ]] [[ include partials/edit-profile ]] [[ include projects/layouts-modal ]] -- cgit v1.2.3-70-g09d2 From ea5cce0042a6448636d4bd583c1200c26a7efe87 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 7 Oct 2014 17:34:36 -0400 Subject: no profile pic thing --- public/assets/stylesheets/app.css | 30 +++++++++++++++++++++++------- views/profile.ejs | 6 +++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 0831a36..cef90a9 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -9,7 +9,9 @@ body,textarea,input { font-family: 'Lato', sans-serif; } - +input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill { + background:white; +} *, *:before, *:after { moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } @@ -468,14 +470,27 @@ iframe.embed { /* PROFILE PAGE */ .profilePic { - font-size: 148px; background-size: cover; background-position: center; width: 40%; height: 50vh; float: left; + display:table; } +.profilePic .ion-ios7-person-outline { + font-size: 100px; +} + + +.noPic input { + position: absolute; + width: 40%; + height: 48vh; + margin-top: -33vh; + margin-left: -20%; + opacity: 0; +} .topLinks { float: right; z-index: 3; @@ -1197,11 +1212,11 @@ iframe.embed { text-transform: none; -webkit-font-smoothing: antialiased; font-size: 40px; - margin-top: -62px; + margin-top: -50px; position: absolute; background: #FF3B30; border-radius: 1000px; - margin-left: -59px; + margin-left: -50px; color: white; width: 50px; height: 50px; @@ -2036,8 +2051,9 @@ form li textarea { letter-spacing: 2px; } .facebook b { - float: left; - font-size: 50px; + float: left; + font-size: 50px; + margin: 0 0 0 20px; } a[data-role="forgot-password"] { @@ -2049,7 +2065,7 @@ a[data-role="forgot-password"] { vertical-align: bottom; padding-right: 14px; font-size: 19px; - line-height: 16px; + line-height: 7px; } .aboutRoom { diff --git a/views/profile.ejs b/views/profile.ejs index 22c824c..6a5b3ea 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -13,8 +13,12 @@
[[ } else { ]] -
+
+ +
click to add profile pic
+ +
[[ } ]]
-- cgit v1.2.3-70-g09d2 From eb1e515f5446d8a90d92c2f60722eca23a9c4fe5 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 17:55:35 -0400 Subject: clamp looking up/down --- public/assets/javascripts/mx/extensions/mx.movements.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/assets/javascripts/mx/extensions/mx.movements.js b/public/assets/javascripts/mx/extensions/mx.movements.js index f94bbc2..065c93b 100644 --- a/public/assets/javascripts/mx/extensions/mx.movements.js +++ b/public/assets/javascripts/mx/extensions/mx.movements.js @@ -16,8 +16,8 @@ MX.Movements = function (cam) { creeping = false, locked = false, gravity = false, - rotationX_min = PI/-2, - rotationX_max = PI/2 + rotationX_min = PI/-4, + rotationX_max = PI/6 var v = 12, vr = Math.PI * 0.012, -- cgit v1.2.3-70-g09d2 From c60434bc4655d0e020ca75fc7c5fddf53ac58ede Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 18:29:08 -0400 Subject: invert logo if background is dark, match body bg to wall color --- .../rectangles/engine/map/ui_minimap.js | 2 ++ .../javascripts/rectangles/engine/rooms/_walls.js | 9 +++++++++ public/assets/stylesheets/app.css | 23 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/public/assets/javascripts/rectangles/engine/map/ui_minimap.js b/public/assets/javascripts/rectangles/engine/map/ui_minimap.js index fabbdb9..d7280b9 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_minimap.js +++ b/public/assets/javascripts/rectangles/engine/map/ui_minimap.js @@ -7,6 +7,7 @@ Map.UI.Minimap = function(map){ base.creating = base.dragging = base.resizing = false +/* base.mouse = new mouse({ el: map.el, down: down, @@ -15,6 +16,7 @@ Map.UI.Minimap = function(map){ up: up, rightclick: rightclick, }) +*/ base.wheel = new wheel({ el: map.el, diff --git a/public/assets/javascripts/rectangles/engine/rooms/_walls.js b/public/assets/javascripts/rectangles/engine/rooms/_walls.js index 7438cd4..5ff53fe 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_walls.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_walls.js @@ -125,6 +125,15 @@ wall: function(rgb){ var rgbaColor = rgba_string(rgb, app.defaults.wallOpacity) + var rgbColor = rgb_string(rgb) + + var rgb_max = Math.max.apply(0, rgb) + var rgb_min = Math.min.apply(255, rgb) + var luminance = (rgb_max + rgb_min ) / 2 + + $("#header").toggleClass("black", luminance < 128) + $("body").css("background-color", rgbColor) + Walls.colors.wall = rgb Walls.list.forEach(function(wall){ wall.outline(rgbaColor, null) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index cef90a9..b4d176f 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -71,6 +71,27 @@ a{ left: 0; z-index: 6; } +#header.black .logo:hover { + background: white; +} +#header.black .logo:hover path { + fill: black; +} +#header.black path { + fill: white; +} +#header.black .topLinks a { + color: white; +} +#header.black .topLinks a:hover { + color: black; + background-color: white; +} +#header.black a#help-button:hover { + background-color: transparent; + text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff; +} + #help-button { display: none; border-right:0px!important; @@ -1566,7 +1587,7 @@ input[type="range"]::-webkit-slider-thumb { bottom: 10px; right: 10px; font-size: 12px; - -webkit-transform: translateY(450px); + -webkit-transform: translateY(500px); -webkit-transition: -webkit-transform 0.2s ease-in-out; transform: translateY(450px); transition: -webkit-transform 0.2s ease-in-out; -- cgit v1.2.3-70-g09d2 From 4dede1ce3a31cfb17cbad80749863725a9957d19 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 18:38:43 -0400 Subject: inverse colors --- public/assets/javascripts/ui/editor/LightControl.js | 11 ++++++----- public/assets/stylesheets/app.css | 6 +++++- views/controls/editor/light-control.ejs | 6 +++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index 2b7cfaa..51e6be7 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -134,17 +134,18 @@ var LightControl = View.extend({ floor: [255,255,0], ceiling: [225,118,252], }, - seapunk: { - wall: [110,255,255], - outline: [146,133,255], - floor: [89,221,255], - ceiling: [139,255,173], + inverse: { + wall: [0,0,0], + outline: [0,230,255], + floor: [0,0,0], + ceiling: [0,0,0], }, }, selectPreset: function(e){ var preset = $(e.currentTarget).data('preset') if (! this.presets[preset]) return this.load(this.presets[preset]) + $(e.currentTarget).addClass('active') }, beginBrightness: function(){ diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index b4d176f..f770637 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1529,6 +1529,10 @@ input[type="range"]::-webkit-slider-thumb { width: 50%; float:left; cursor:pointer; + border-bottom: 1px transparent solid; +} +.presets span.active { + border-bottom: 1px dotted; } .color-swatches span { display: inline-block; @@ -1589,7 +1593,7 @@ input[type="range"]::-webkit-slider-thumb { font-size: 12px; -webkit-transform: translateY(500px); -webkit-transition: -webkit-transform 0.2s ease-in-out; - transform: translateY(450px); + transform: translateY(500px); transition: -webkit-transform 0.2s ease-in-out; width: 210px; } diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs index 1fc4484..8f42d8d 100644 --- a/views/controls/editor/light-control.ejs +++ b/views/controls/editor/light-control.ejs @@ -30,11 +30,11 @@ Shaded + + Inverse + P.Funk - - SeaPunk -
-- cgit v1.2.3-70-g09d2 From e9c849ff9d69ceeafa0a98b22040d027f82d7dc3 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 7 Oct 2014 18:51:50 -0400 Subject: wallpaper --- views/controls/editor/wallpaper.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index 97a9232..3c621b1 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -1,7 +1,7 @@

Add Wallpaper

- Add custom wallpaper to walls. Begin by uploading a pattern. Or try this one -> + Add custom wallpaper to walls. Begin by uploading a pattern. Or try one of these -> -- cgit v1.2.3-70-g09d2 From a980ce6da41d8358c8fa973bf83809e80325ccd5 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 7 Oct 2014 18:54:16 -0400 Subject: start of default wallpaper --- views/controls/editor/wallpaper.ejs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index 3c621b1..2d47e04 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -1,9 +1,14 @@

Add Wallpaper

- Add custom wallpaper to walls. Begin by uploading a pattern. Or try one of these -> + Add custom wallpaper to walls. Begin by uploading a pattern. Or try one of these -> - + + + + + +
-- cgit v1.2.3-70-g09d2 From 8ae73f097e27cd54f685c562081f3a1bc7c9b13d Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 18:59:04 -0400 Subject: resize/scale wallpaper --- public/assets/javascripts/ui/editor/EditorView.js | 1 + .../javascripts/ui/editor/WallpaperPicker.js | 57 +++++++++++++++++++++- public/assets/stylesheets/app.css | 12 +++++ public/assets/test/bg.html | 2 +- views/controls/editor/wallpaper.ejs | 6 +++ 5 files changed, 76 insertions(+), 2 deletions(-) diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index f95d909..f60b149 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -54,6 +54,7 @@ var EditorView = View.extend({ pickWall: function(wall, pos){ this.hideExtras() + this.wallpaperPicker.pickWall(wall) }, hideExtras: function(){ diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index 7f9b8f7..3694095 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -6,8 +6,11 @@ var WallpaperPicker = UploadView.extend({ uploadAction: "/api/media/upload", events: { + "mousedown": 'stopPropagation', "click .swatch": 'pick', "click .wallpaperRemove": 'remove', + "input [data-role='wallpaper-scale']": 'updateScale', + }, initialize: function(){ @@ -15,6 +18,11 @@ var WallpaperPicker = UploadView.extend({ this.$swatches = this.$(".swatches") this.$remove = this.$(".wallpaperRemove") this.$remove.hide() + + this.$position = this.$("[data-role='wallpaper-position']") + this.$scale = this.$("[data-role='wallpaper-scale']") + + this.initializePositionCursor() }, loaded: false, @@ -122,5 +130,52 @@ var WallpaperPicker = UploadView.extend({ _followCursor(e); }) }, - + + wall: null, + pickWall: function(wall){ + if (wall.background.src == "none") { + return; + } + console.log(wall) + this.wall = wall + }, + + updateScale: function(){ + if (! this.wall) return; + s = parseFloat(this.$scale.val()) + this.wall.wallpaperPosition({ scale: s }) + }, + + initializePositionCursor: function(){ + var base = this + var dx = 0, dy = 0, dragging = false + var x = 0, y = 0, s = 1 + var mymouse = new mouse({ + el: this.$position[0], + down: function(e, cursor){ + if (! base.wall) return + s = parseFloat( base.$scale.val() ) + x = base.wall.background.x + y = base.wall.background.y + dragging = true + }, + drag: function(e, cursor){ + if (! dragging) return + delta = cursor.delta() + delta.a = - delta.a + dx = delta.a*s + dy = delta.b*s + base.wall.wallpaperPosition({ + scale: s, + x: x+dx, + y: y+dy, + }) + }, + up: function(e, cursor, new_cursor){ + delta.zero() + dragging = false + }, + }) + }, + }) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index f770637..6e23962 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1487,6 +1487,18 @@ input[type="range"]::-webkit-slider-thumb { border:3px solid #000; } +.wallpaperResizeControls input[type=range] { + width: 130px; + position: relative; + top: -10px; +} +.wallpaperResizeControls { + font-size: 30px; +} +.wallpaperResizeControls span { + cursor: pointer; +} + #color-picker { position: relative; } diff --git a/public/assets/test/bg.html b/public/assets/test/bg.html index cd7eaa8..fecf811 100644 --- a/public/assets/test/bg.html +++ b/public/assets/test/bg.html @@ -88,7 +88,7 @@ var x0 = 0, y0 = 0 var mymouse = new mouse({ el: cursor, down: function(e, cursor){ - console.log(cursor.x.a, cursor.y.a) + console.log(cursor.x.a, cursor.y.a) dragging = true }, drag: function(e, cursor){ diff --git a/views/controls/editor/wallpaper.ejs b/views/controls/editor/wallpaper.ejs index 97a9232..719c8ff 100644 --- a/views/controls/editor/wallpaper.ejs +++ b/views/controls/editor/wallpaper.ejs @@ -25,6 +25,12 @@
+ +
+ + +
+
-- cgit v1.2.3-70-g09d2 From bd952badbe37dcd1c4089b2b869a6a4d85c0b198 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 19:01:10 -0400 Subject: update when u click wall --- public/assets/javascripts/ui/editor/WallpaperPicker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index 3694095..140076d 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -136,8 +136,8 @@ var WallpaperPicker = UploadView.extend({ if (wall.background.src == "none") { return; } - console.log(wall) this.wall = wall + this.$scale.val( this.wall.background.scale ) }, updateScale: function(){ -- cgit v1.2.3-70-g09d2 From c2e2334328256fa0409341692284f25f3167ab30 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 7 Oct 2014 19:03:56 -0400 Subject: scale cil/floor wallapper --- public/assets/javascripts/rectangles/models/floor.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/assets/javascripts/rectangles/models/floor.js b/public/assets/javascripts/rectangles/models/floor.js index 78e9019..7ed52a1 100644 --- a/public/assets/javascripts/rectangles/models/floor.js +++ b/public/assets/javascripts/rectangles/models/floor.js @@ -49,6 +49,9 @@ // TODO: watch individual scenery object here Minotaur.watch( app.router.editorView.settings ) + } + else { + app.controller.pickWall(base, null) } } }) -- cgit v1.2.3-70-g09d2 From 1f66850f5ec5a2e664ee8eaafbe25c46dad34102 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 12:11:18 -0400 Subject: generate masks for thumbnails --- .../javascripts/rectangles/engine/map/draw.js | 64 ++++++++++++++-------- .../javascripts/rectangles/engine/rooms/_walls.js | 4 ++ .../assets/javascripts/rectangles/models/wall.js | 2 +- .../javascripts/ui/builder/BuilderSettings.js | 4 +- .../assets/javascripts/ui/editor/EditorSettings.js | 4 +- .../javascripts/ui/editor/WallpaperPicker.js | 7 +-- 6 files changed, 54 insertions(+), 31 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/map/draw.js b/public/assets/javascripts/rectangles/engine/map/draw.js index 3e185d2..07e2d9f 100644 --- a/public/assets/javascripts/rectangles/engine/map/draw.js +++ b/public/assets/javascripts/rectangles/engine/map/draw.js @@ -10,7 +10,7 @@ Map.Draw = function(map, opt){ draw.animate = function(){ ctx.save() draw.clear() - // draw.ruler() + draw.fill("rgba(255,255,255,0.98)") if (opt.minimap) { ctx.translate( map.dimensions.a * 1/2, map.dimensions.b * 1/2) @@ -19,7 +19,7 @@ Map.Draw = function(map, opt){ ctx.scale( -1, 1 ) draw.coords() - draw.regions(Rooms.regions, [ "#fff" ]) + draw.regions(Rooms.regions, [ "#fff" ], "#000") draw.camera(scene.camera) } @@ -29,7 +29,7 @@ Map.Draw = function(map, opt){ ctx.translate( map.center.a, map.center.b ) ctx.scale( -1, 1 ) - draw.regions(Rooms.regions, [ "#f8f8f8" ]) + draw.regions(Rooms.regions, [ "#f8f8f8" ], "#000") draw.mouse(map.ui.mouse.cursor) draw.coords() scene && draw.camera(scene.camera) @@ -39,7 +39,12 @@ Map.Draw = function(map, opt){ } draw.render = function(){ - ctx.save() + // change the ctx temporarily + var canvas = document.createElement("canvas") + ctx = canvas.getContext('2d') + canvas.width = map.canvas.width + canvas.height = map.canvas.height + draw.clear() ctx.translate( map.dimensions.a * 1/2, map.dimensions.b * 1/2) @@ -47,37 +52,52 @@ Map.Draw = function(map, opt){ ctx.translate( map.center.a, map.center.b ) ctx.scale( -1, 1 ) - draw.regions(Rooms.regions, ["#fff"]) - draw.mouse(map.ui.mouse.cursor) - scene && draw.camera(scene.camera) - + draw.regions(Rooms.regions, ["#fff"], null) + ctx.restore() + + // invert opacity + var pixelData = ctx.getImageData(0, 0, canvas.width, canvas.height) + var pixels = pixelData.data + for (var i = 0, k, _len = pixels.length; i < _len; i++) { + k = i*4 + if (pixels[k+3] == 0) { + pixels[k] = pixels[k+1] = pixels[k+2] = pixels[k+3] = 255 + } + else { + pixels[k] = pixels[k+1] = pixels[k+2] = 255 + pixels[k+3] = 0 + } + } + ctx.putImageData(pixelData, 0, 0) + + // reset the ctx + ctx = map.canvas.getContext("2d") + + return canvas } draw.clear = function(){ - ctx.fillStyle = "rgba(255,255,255,0.98)" ctx.clearRect(0, 0, map.dimensions.a, map.dimensions.b) - ctx.fillRect(0, 0, map.dimensions.a, map.dimensions.b) } - draw.ruler = function (){ - ctx.strokeStyle = "rgba(80,80,80,0.5)" - ctx.lineWidth = 1 - var len = 5 - for (var i = 0.5; i < map.dimensions.a; i += 10) { - line(i, 0, i, len) - line(0, i, len, i) - } + draw.fill = function(fillStyle){ + ctx.fillStyle = fillStyle + ctx.fillRect(0, 0, map.dimensions.a, map.dimensions.b) } - draw.regions = function(regions, colors){ + draw.regions = function(regions, colors, stroke){ + if (stroke) { + ctx.strokeStyle = "#000" + ctx.lineWidth = (1 / map.zoom) + } for (var i = 0; i < regions.length; i++) { if (regions[i].dupe) continue ctx.fillStyle = colors[i % colors.length] - ctx.strokeStyle = "#000" - ctx.lineWidth = (1 / map.zoom) fill_region(regions[i]) - stroke_sides(regions[i]) + if (stroke) { + stroke_sides(regions[i]) + } } } diff --git a/public/assets/javascripts/rectangles/engine/rooms/_walls.js b/public/assets/javascripts/rectangles/engine/rooms/_walls.js index 5ff53fe..71ddde9 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_walls.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_walls.js @@ -103,6 +103,10 @@ walls_data.forEach(function(wall_data){ if (! wall_data) { return } var wall = base.lookup[ wall_data.id ] + if (! wall) { + console.log(wall_data); + return + } wall.deserialize( wall_data ) }) }, diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 8174de7..fcb2f5e 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -13,7 +13,7 @@ } var Wall = function(opt){ - this.id = [ opt.side, opt.edge, opt.vec.a ].join("_") + this.id = [ opt.side|0, opt.edge|0, opt.vec.a|0 ].join("_") this.vec = opt.vec this.edge = opt.edge this.side = opt.side diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index 94eed29..99bceed 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -107,7 +107,7 @@ var BuilderSettings = FormView.extend({ }, serialize: function(){ - map.draw.render() + var thumbnail = map.canvas.render() var fd = new FormData() fd.append( "_csrf", this.$csrf.val() ) fd.append( "_id", this.$id.val() ) @@ -115,7 +115,7 @@ var BuilderSettings = FormView.extend({ fd.append( "privacy", this.$privacy.filter(":checked").val() == "private" ) fd.append( "rooms", JSON.stringify( Rooms.serialize() ) ) fd.append( "startPosition", JSON.stringify( app.position(scene.camera) ) ) - fd.append( "thumbnail", dataUriToBlob(map.canvas.toDataURL()) ) + fd.append( "thumbnail", dataUriToBlob(thumbnail.toDataURL()) ) return fd }, diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index fd251b7..0c08369 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -146,7 +146,6 @@ var EditorSettings = FormView.extend({ }, serialize: function(){ - map.draw.render() var fd = new FormData() fd.append( "_csrf", this.$csrf.val() ) fd.append( "_id", this.$id.val() ) @@ -160,7 +159,8 @@ var EditorSettings = FormView.extend({ fd.append( "startPosition", JSON.stringify( app.position(scene.camera) ) ) if (this.thumbnailIsStale()) { - fd.append( "thumbnail", dataUriToBlob(map.canvas.toDataURL()) ) + var thumbnail = map.draw.render() + fd.append( "thumbnail", dataUriToBlob(thumbnail.toDataURL()) ) } return fd }, diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index 140076d..6bf2542 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -133,7 +133,7 @@ var WallpaperPicker = UploadView.extend({ wall: null, pickWall: function(wall){ - if (wall.background.src == "none") { + if (! wall.background || wall.background.src == "none") { return; } this.wall = wall @@ -148,16 +148,16 @@ var WallpaperPicker = UploadView.extend({ initializePositionCursor: function(){ var base = this - var dx = 0, dy = 0, dragging = false + var dx = 0, dy = 0, dragging = false, delta var x = 0, y = 0, s = 1 var mymouse = new mouse({ el: this.$position[0], down: function(e, cursor){ if (! base.wall) return + dragging = true s = parseFloat( base.$scale.val() ) x = base.wall.background.x y = base.wall.background.y - dragging = true }, drag: function(e, cursor){ if (! dragging) return @@ -172,7 +172,6 @@ var WallpaperPicker = UploadView.extend({ }) }, up: function(e, cursor, new_cursor){ - delta.zero() dragging = false }, }) -- cgit v1.2.3-70-g09d2 From 6f4cd32fa13efe3b0e8b26183589f66889dd3738 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 13:26:08 -0400 Subject: render thumbnails as masks --- .../javascripts/rectangles/engine/map/draw.js | 20 ++++++++++++------- .../javascripts/rectangles/engine/rooms/_rooms.js | 10 ++++++++++ .../assets/javascripts/rectangles/models/rect.js | 23 ++++++++++++++++++++++ .../javascripts/ui/builder/BuilderSettings.js | 2 +- public/assets/stylesheets/app.css | 11 +++++------ 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/map/draw.js b/public/assets/javascripts/rectangles/engine/map/draw.js index 07e2d9f..6c27ff1 100644 --- a/public/assets/javascripts/rectangles/engine/map/draw.js +++ b/public/assets/javascripts/rectangles/engine/map/draw.js @@ -38,18 +38,24 @@ Map.Draw = function(map, opt){ ctx.restore() } + // changes the ctx temporarily draw.render = function(){ - // change the ctx temporarily + var thumbnail_side = 1000 + + var extent = Rooms.extent() + var center = extent.center() + var zoom = thumbnail_side / Math.max( extent.width(), extent.height() ) * 0.99 + var canvas = document.createElement("canvas") ctx = canvas.getContext('2d') - canvas.width = map.canvas.width - canvas.height = map.canvas.height + canvas.width = thumbnail_side + canvas.height = thumbnail_side draw.clear() - ctx.translate( map.dimensions.a * 1/2, map.dimensions.b * 1/2) - ctx.scale( map.zoom, map.zoom ) - ctx.translate( map.center.a, map.center.b ) + ctx.translate( thumbnail_side * 1/2, thumbnail_side * 1/2) + ctx.scale( zoom, zoom ) + ctx.translate( center.a, -center.b ) ctx.scale( -1, 1 ) draw.regions(Rooms.regions, ["#fff"], null) @@ -73,7 +79,7 @@ Map.Draw = function(map, opt){ // reset the ctx ctx = map.canvas.getContext("2d") - + return canvas } diff --git a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js index 6f96275..0c3cfd4 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js @@ -118,6 +118,16 @@ return data } + base.extent = function(){ + var extent = new Rect ( new vec2(Infinity, -Infinity), new vec2(Infinity, -Infinity) ) + + base.forEach(function(room){ + extent.expand(room.rect) + }) + + return extent + } + base.sorted_by_position = function(){ return sort.rooms_by_position( base.values() ) } diff --git a/public/assets/javascripts/rectangles/models/rect.js b/public/assets/javascripts/rectangles/models/rect.js index a08176a..00f2c55 100644 --- a/public/assets/javascripts/rectangles/models/rect.js +++ b/public/assets/javascripts/rectangles/models/rect.js @@ -141,6 +141,29 @@ Rect.prototype.width = function(){ return this.x.length() } Rect.prototype.height = function(){ return this.y.length() } Rect.prototype.delta = function(){ return new vec2( this.x.magnitude(), this.y.magnitude() ) } + Rect.prototype.expand = function(rect){ + this.x.a = Math.min( this.x.a, rect.x.a ) + this.x.b = Math.max( this.x.b, rect.x.b ) + this.y.a = Math.min( this.y.a, rect.y.a ) + this.y.b = Math.max( this.y.b, rect.y.b ) + return this + } + Rect.prototype.square = function(){ + var width = this.x.length() + var height = this.y.length() + var diff + if (width < height) { + diff = (height - width) / 2 + this.x.a -= diff + this.x.b += diff + } + else { + diff = (width - height) / 2 + this.y.a -= diff + this.y.b += diff + } + return this + } Rect.prototype.toString = function(){ var sides = sidesToString(this.sides) var s = "[" + this.x.toString() + " " + this.y.toString() + "] " + sides diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index 99bceed..7ae6294 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -107,7 +107,7 @@ var BuilderSettings = FormView.extend({ }, serialize: function(){ - var thumbnail = map.canvas.render() + var thumbnail = map.draw.render() var fd = new FormData() fd.append( "_csrf", this.$csrf.val() ) fd.append( "_id", this.$id.val() ) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 6e23962..d47b5a7 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -619,16 +619,16 @@ iframe.embed { display: none; } -.templates span{ +.templates span { background-position: center; background-size: contain; background-repeat: no-repeat; background-color: #fff; width: 20vw; - height: 20vh; + height: 20vw; display: inline-block; margin: 4vw; - border:1px solid black; + background-color: #ddd; position: relative; } @@ -640,17 +640,16 @@ iframe.embed { left: 0; background: #fff; padding: 5px; - border-top: 1px solid black; font-weight: 300; } .templates span:hover { - border:1px solid blue; + background-color: #f00; cursor:pointer; } .templates span:hover:after { - border-top: 1px solid blue; + color: #f00; } .templates h1 { -- cgit v1.2.3-70-g09d2 From 88f0fe47a3f130efc25ee9e2579427c814667086 Mon Sep 17 00:00:00 2001 From: ryderr Date: Wed, 8 Oct 2014 13:29:08 -0400 Subject: minor --- public/assets/stylesheets/app.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 6e23962..29e23c8 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -499,6 +499,10 @@ iframe.embed { display:table; } +.noPic { + border-right: 1px solid; +} + .profilePic .ion-ios7-person-outline { font-size: 100px; } @@ -1669,6 +1673,7 @@ input[type="range"]::-webkit-slider-thumb { font-size: 12px; width: 100%; max-height: 200px; + max-width: 100%; } #textEditor.settings textarea { max-height: none; @@ -2256,6 +2261,7 @@ a[data-role="forgot-password"] { background-size: cover; display: inline-block; margin-right: 10px; + background-color: #ccc; } #collaborator-list .username { position: relative; -- cgit v1.2.3-70-g09d2 From 583d213f22be93a1363c24ac2cdf9f083833703f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 14:47:47 -0400 Subject: projectList item formatting --- .../javascripts/rectangles/engine/map/draw.js | 19 ++++-- .../javascripts/rectangles/engine/rooms/_rooms.js | 2 - public/assets/stylesheets/app.css | 77 +++++++++++++++------- server/lib/views/index.js | 5 ++ views/projects/list-projects.ejs | 34 +++++----- 5 files changed, 88 insertions(+), 49 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/map/draw.js b/public/assets/javascripts/rectangles/engine/map/draw.js index 6c27ff1..7eb6e7c 100644 --- a/public/assets/javascripts/rectangles/engine/map/draw.js +++ b/public/assets/javascripts/rectangles/engine/map/draw.js @@ -40,20 +40,29 @@ Map.Draw = function(map, opt){ // changes the ctx temporarily draw.render = function(){ - var thumbnail_side = 1000 + var thumbnail_width = 1000 + var thumbnail_height = 750 var extent = Rooms.extent() var center = extent.center() - var zoom = thumbnail_side / Math.max( extent.width(), extent.height() ) * 0.99 + var extent_width = extent.width() + var extent_height = extent.height() + var zoom + if (extent_width > extent_height) { + zoom = thumbnail_width / extent.width() * 0.9 + } + else { + zoom = thumbnail_height / extent.height() * 0.9 + } var canvas = document.createElement("canvas") ctx = canvas.getContext('2d') - canvas.width = thumbnail_side - canvas.height = thumbnail_side + canvas.width = thumbnail_width + canvas.height = thumbnail_height draw.clear() - ctx.translate( thumbnail_side * 1/2, thumbnail_side * 1/2) + ctx.translate( thumbnail_width * 1/2, thumbnail_height * 1/2) ctx.scale( zoom, zoom ) ctx.translate( center.a, -center.b ) ctx.scale( -1, 1 ) diff --git a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js index 0c3cfd4..3603f0c 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js @@ -120,11 +120,9 @@ base.extent = function(){ var extent = new Rect ( new vec2(Infinity, -Infinity), new vec2(Infinity, -Infinity) ) - base.forEach(function(room){ extent.expand(room.rect) }) - return extent } diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index d47b5a7..24ca772 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -327,27 +327,42 @@ iframe.embed { .projectList { display: inline-block; float: left; - width: 100%; + width: 98vw; + margin: 2vw; } +.projectList a { + width: 32vw; + float:left; + clear: right; + padding-bottom: 2vw; +} .projectList .room { - width: 50%; - height:40vh; + width: 30vw; + height: 23vw; + margin: 1vw; + border: 1vw solid white; display:table; position: relative; - float:left; - border-top:1px solid; + z-index: 1; } - -.projectList .room:nth-child(3n+2) { - border-right:1px solid black; +.projectList .holder { + position: absolute; + top: 50%; + z-index: 2; } -.projectList .room:nth-child(3n+1) { - width: 100%; - height: 50vh; +.room .mask { + position: absolute; + top: 0; left: 0; + z-index: 1; + width: 100%; + height: 100%; + text-align: center; + overflow: hidden; + background-size: cover; + background-repeat: no-repeat; } - .room .images { position: absolute; top: 0; left: 0; @@ -358,15 +373,28 @@ iframe.embed { overflow: hidden; } .room .images img { - max-height: 100%; - max-width: 100%; + width: 50%; + position: absolute; } +.room .images[data-mediacount='1'] img:nth-child(1) { left: 20%; top: 20%; } + +.room .images[data-mediacount='2'] img:nth-child(1) { left: 51%; bottom: 0%; width: auto; height: 100%; } +.room .images[data-mediacount='2'] img:nth-child(2) { right: 51%; bottom: 0%; width: auto; height: 100%; } + +.room .images[data-mediacount='3'] img:nth-child(1) { right: 51%; bottom: 41%; } +.room .images[data-mediacount='3'] img:nth-child(2) { left: 51%; bottom: 0%; width:auto; height:100%;} +.room .images[data-mediacount='3'] img:nth-child(3) { right: 51%; top: 61%; } + +.room .images[data-mediacount='4'] img:nth-child(1) { right: 51%; bottom: 41%; } +.room .images[data-mediacount='4'] img:nth-child(2) { left: 51%; bottom: 61%; } +.room .images[data-mediacount='4'] img:nth-child(3) { right: 51%; top: 61%; } +.room .images[data-mediacount='4'] img:nth-child(4) { left: 51%; top: 41%; } + .page .btn { clear: both; padding: 30px 0; border: 0; - } .page .viewMore { @@ -385,22 +413,21 @@ iframe.embed { vertical-align: middle; } -.page .room .holder a { - font-weight: 300; - font-size: 20px; - letter-spacing: 1px; +.page label { + font-weight: 500; + font-size: 15px; color: black; - background: white; - border: 1px solid; padding: 5px; - box-shadow: -3px 3px black; text-decoration:none; - max-width: 180px; display: inline-block; + cursor: pointer; } -.page .room .holder a:hover { - background:black; +.projectList a:hover { + background: linear-gradient( 0deg, blue, red ); +} + +.projectList a:hover label { color:white; } diff --git a/server/lib/views/index.js b/server/lib/views/index.js index ca48159..3f3880f 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -139,6 +139,11 @@ views.profile = function (req, res) { projects = projects.map(function(project){ project = project.toObject() project.date = moment(project.updated_at).format("M/DD/YYYY") + if (project.colors.wall && project.colors.wall[0] == project.colors.wall[1] && project.colors.wall[1] == project.colors.wall[2] && project.colors.wall[2] > 238) { + project.color = [238,238,238] + } else { + project.color = project.colors.wall + } return project }) done(err, user, projects) diff --git a/views/projects/list-projects.ejs b/views/projects/list-projects.ejs index a12f237..f469f5c 100644 --- a/views/projects/list-projects.ejs +++ b/views/projects/list-projects.ejs @@ -4,31 +4,31 @@ [[ projects.forEach(function(project, i) { ]] - - - + [[ if (String(user._id) == String(project.user_id)) { ]] + + [[ } else { ]] + + [[ } ]] + + + [[ mediaCount = 0 ]] [[ project.media.some(function(media){ ]] [[ if (media.media.type != "image") { return false } ]] - [[ if (++mediaCount > 3) { return true } ]] + [[ if (++mediaCount > 1) { return true } ]] [[ }) ]] - - + + + + + [[ }) ]]
-- cgit v1.2.3-70-g09d2 From 06f14d5f9cce84bd6e3409b6d59fcb85c6c1aac0 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 15:25:51 -0400 Subject: less ridic hover effect --- public/assets/stylesheets/app.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 24ca772..93645e1 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -421,14 +421,14 @@ iframe.embed { text-decoration:none; display: inline-block; cursor: pointer; + border: 1px solid transparent; } .projectList a:hover { - background: linear-gradient( 0deg, blue, red ); } .projectList a:hover label { - color:white; + border: 1px solid black; } -- cgit v1.2.3-70-g09d2 From 82343a901aa641569ecf03e55d4560f691bea9ba Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 15:34:10 -0400 Subject: better markup on layouts modal --- public/assets/javascripts/ui/site/LayoutsModal.js | 12 ++++++--- public/assets/stylesheets/app.css | 30 ++++++++++++----------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 1bfc6cb..8eaf081 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -22,10 +22,16 @@ var LayoutsIndex = View.extend({ this.$templates.empty() data.forEach(function(room){ var $span = $("") - // $span.html(JSON.stringify(room)) $span.data("slug", room.slug) - $span.css("background-image", "url(" + room.photo + ")") - $span.attr("data-name", room.name) + + var $label = $("
-
+ [[ if (projects.length) { ]]

[[- profile.username ]] has [[- projects.length ]] project[[- projects.length != 1 ? "s" : "" ]]

@@ -50,11 +50,23 @@ view more [[ } else { ]] +

Welcome to VVALLS

-

- You don't have any projects yet. To get started click "New Project" up at the top of the screen. +
+

+ VValls lets you create awesome 3D rooms. +

+ +

+ You don't have any projects yet. +

+

+ Create a New Project +

+ +
[[ } ]] - +
[[ include partials/edit-profile ]] [[ include projects/layouts-modal ]] [[ include projects/edit-project ]] -- cgit v1.2.3-70-g09d2 From 32710444724fa6271d7d1d86a917be3b7457217c Mon Sep 17 00:00:00 2001 From: ryderr Date: Wed, 8 Oct 2014 15:54:05 -0400 Subject: data role --- views/profile.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/profile.ejs b/views/profile.ejs index adc9562..5ff2eb0 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -61,7 +61,7 @@ You don't have any projects yet.

- Create a New Project + Create a New Project

-- cgit v1.2.3-70-g09d2 From dc553c1adc365c8a6201c13ae622f7d8a3040725 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 16:05:25 -0400 Subject: fix fields on layouts editor --- public/assets/stylesheets/app.css | 1 + 1 file changed, 1 insertion(+) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 0062dca..f320db7 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1663,6 +1663,7 @@ input[type="range"]::-webkit-slider-thumb { .settings.info { right: auto; left: 10px; + width: 230px; } .vvbox h4 { -- cgit v1.2.3-70-g09d2 From 084769b40b5ab5dc8fa2f2dfa82d1ebc4ff41795 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 8 Oct 2014 16:11:19 -0400 Subject: don't remove h1 --- public/assets/javascripts/ui/site/LayoutsModal.js | 2 +- public/assets/stylesheets/app.css | 14 ++++++-------- views/projects/list-projects.ejs | 8 ++++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 8eaf081..ef6a36c 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -19,7 +19,7 @@ var LayoutsIndex = View.extend({ this.$form.hide() this.$noTemplates.show() } - this.$templates.empty() + this.$templates.children("span").remove() data.forEach(function(room){ var $span = $("") $span.data("slug", room.slug) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index f320db7..a8f8e51 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -361,29 +361,28 @@ iframe.embed { text-align: center; overflow: hidden; background-size: cover; - background-repeat: no-repeat; } .room .images { position: absolute; top: 0; left: 0; - z-index: -1; + z-index: 2; width: 100%; height: 100%; text-align: center; overflow: hidden; } .room .images img { - width: 50%; + width: 30%; position: absolute; } .room .images[data-mediacount='1'] img:nth-child(1) { left: 20%; top: 20%; } -.room .images[data-mediacount='2'] img:nth-child(1) { left: 51%; bottom: 0%; width: auto; height: 100%; } -.room .images[data-mediacount='2'] img:nth-child(2) { right: 51%; bottom: 0%; width: auto; height: 100%; } +.room .images[data-mediacount='2'] img:nth-child(1) { left: 51%; bottom: 0%; width: auto; height: 30%; } +.room .images[data-mediacount='2'] img:nth-child(2) { right: 51%; bottom: 0%; width: auto; height: 30%; } .room .images[data-mediacount='3'] img:nth-child(1) { right: 51%; bottom: 41%; } -.room .images[data-mediacount='3'] img:nth-child(2) { left: 51%; bottom: 0%; width:auto; height:100%;} +.room .images[data-mediacount='3'] img:nth-child(2) { left: 51%; bottom: 0%; width:auto; height:30%;} .room .images[data-mediacount='3'] img:nth-child(3) { right: 51%; top: 61%; } .room .images[data-mediacount='4'] img:nth-child(1) { right: 51%; bottom: 41%; } @@ -702,8 +701,7 @@ border-left: 1px solid black; } .templates span .image { background-position: center; - background-size: contain; - background-repeat: no-repeat; + background-size: cover; background-color: #fff; width: 20vw; height: 15vw; diff --git a/views/projects/list-projects.ejs b/views/projects/list-projects.ejs index f469f5c..45b73e2 100644 --- a/views/projects/list-projects.ejs +++ b/views/projects/list-projects.ejs @@ -11,16 +11,16 @@ [[ } ]] - + + + [[ mediaCount = 0 ]] [[ project.media.some(function(media){ ]] [[ if (media.media.type != "image") { return false } ]] - [[ if (++mediaCount > 1) { return true } ]] + [[ if (++mediaCount > 3) { return true } ]] [[ }) ]] - -
-- cgit v1.2.3-70-g09d2 From 490aac9f5489594f679d844f67ab09a4565f9422 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 18 Nov 2014 13:04:11 -0500 Subject: footer --- views/partials/footer.ejs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index a94acb1..5b0c0e9 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -1,7 +1,6 @@
-

Keyboard Shortcuts

+

Keyboard Shortcuts

diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index 5b0c0e9..75d06e5 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -1,6 +1,6 @@ diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index 75d06e5..15b658f 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -3,6 +3,7 @@ How To Terms Privacy + Contact ©2014 Dot Dash 3, Inc. -- cgit v1.2.3-70-g09d2 From fd91cb2a84c5150f4ffa9f45d3713ebe30e094aa Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 19 Nov 2014 15:51:53 -0500 Subject: fb share image, add credit link to footer --- server/lib/middleware.js | 2 +- views/partials/footer.ejs | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 60f2e46..7b37658 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -40,7 +40,7 @@ var middleware = { res.locals.user = req.user || { _id: undefined } res.locals.config = config res.locals.profile = null - res.locals.ogImage = "" + res.locals.ogImage = "http://okfocus.s3.amazonaws.com/images/vvalls-fb.png" res.locals.ogTitle = "VValls" res.locals.ogUrl = "http://vvalls.com/" res.locals.ogDescription = "3D gallery space, fully customizable" diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index 15b658f..4005507 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -1,15 +1,6 @@ -- cgit v1.2.3-70-g09d2 From 8ab181a8706bf8638522fd0b762a7b53786db275 Mon Sep 17 00:00:00 2001 From: ryderr Date: Fri, 21 Nov 2014 14:31:58 -0500 Subject: new viewport tag --- public/assets/stylesheets/app.css | 2 +- views/about/howto.ejs | 2 +- views/partials/footer.ejs | 2 +- views/partials/meta.ejs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 632d816..5aab111 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1,4 +1,3 @@ -@import url(http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic); *{ margin:0; @@ -3141,6 +3140,7 @@ a[data-role="forgot-password"] { } } + @media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (-webkit-min-device-pixel-ratio: 2) { .hero{ height: 500pt; diff --git a/views/about/howto.ejs b/views/about/howto.ejs index d5aeab7..74009d1 100644 --- a/views/about/howto.ejs +++ b/views/about/howto.ejs @@ -77,7 +77,7 @@
- +

Getting around VValls is easier with the keyboard.

diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index 4005507..7b01162 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -17,7 +17,7 @@ Terms Privacy Contact - +

©2014 Dot Dash 3, Inc. Site by OKFocus diff --git a/views/partials/meta.ejs b/views/partials/meta.ejs index defb187..57453de 100644 --- a/views/partials/meta.ejs +++ b/views/partials/meta.ejs @@ -17,7 +17,7 @@ - + @@ -28,9 +28,9 @@ + - - + -- cgit v1.2.3-70-g09d2 From d4b057efd7f5d1dc92c95606ac9c6f75a2d88239 Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 24 Nov 2014 10:40:36 -0500 Subject: fix thumbs in safari --- public/assets/stylesheets/app.css | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 8832e10..707d43c 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -13,11 +13,9 @@ input:-webkit-autofill { } .mobile input { -webkit-appearance: none; + border-radius:0; } -input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill { - background:white!important; -} *, *:before, *:after { moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } @@ -432,10 +430,11 @@ iframe.embed { .projectList .projectItem { margin: 4%; + width: 22vw; display: inline-block; } .projectList .room { - width: 22vw; + width: 100%; height: 16vw; margin: 1vw 1vw 10px 1vw; display: table; @@ -2501,7 +2500,7 @@ form li textarea { -moz-transition:0.2s background; transition:0.2s background; position: relative; - z-index: 5; + z-index: 10; } @@ -2717,7 +2716,7 @@ a[data-role="forgot-password"] { .share a:nth-child(3), .share a:nth-child(4) { margin-left:4px; } -.share a:hover{ +.desktop .share a:hover{ text-decoration:underline; } .vvbox.share { @@ -3089,6 +3088,9 @@ a[data-role="forgot-password"] { .reader .topLinks a { display:none; } + .reader iframe { + display:none; + } } @media screen and (orientation:portrait) { @@ -3112,7 +3114,6 @@ a[data-role="forgot-password"] { border-top: 1px solid; border-bottom: 1px solid; padding: 20px 0; - background-color:rgba(255,255,255,0.7); } } -- cgit v1.2.3-70-g09d2 From 278a124a50d70571945cd7f868d62f9087cd3883 Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 24 Nov 2014 11:22:05 -0500 Subject: more safari fixes --- public/assets/stylesheets/app.css | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index e26df00..65df135 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -881,6 +881,7 @@ iframe.embed { overflow: auto; max-height: 100%; width: 100%; + height: 100%; padding: 20px 0 40px 0; } .templates-list { @@ -910,6 +911,7 @@ border-left: 1px solid black; display: block; float: left; margin: 1vw 0; + width:25%; padding: 2vw; cursor: pointer; } @@ -917,7 +919,7 @@ border-left: 1px solid black; background-position: center; background-size: cover; background-color: #fff; - width: 20vw; + width: 100%; height: 15vw; display: block; background-color: #ddd; @@ -2502,7 +2504,7 @@ form li textarea { -moz-transition:0.2s background; transition:0.2s background; position: relative; - z-index: 10; + z-index: 6; } -- cgit v1.2.3-70-g09d2 From bc106e54c39ee5438b48fbde0320a051c9e93629 Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 24 Nov 2014 11:25:08 -0500 Subject: more safari fixes --- public/assets/stylesheets/app.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 65df135..467c83b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -16,6 +16,8 @@ input:-webkit-autofill { border-radius:0; } + + *, *:before, *:after { moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } @@ -42,6 +44,11 @@ body.editing *{ -moz-user-select: none; user-select: none; } + +body.editing input { + -webkit-user-select: auto; +} + body.noOverflow{ overflow:hidden; } -- cgit v1.2.3-70-g09d2 From 377fa673972f32e558faabe74903a237ee1b5c65 Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 24 Nov 2014 11:31:15 -0500 Subject: one other thing --- public/assets/stylesheets/app.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 467c83b..218f38b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -918,7 +918,7 @@ border-left: 1px solid black; display: block; float: left; margin: 1vw 0; - width:25%; + width:20%; padding: 2vw; cursor: pointer; } -- cgit v1.2.3-70-g09d2 From d941ec46ee1d3842387837377140e8d1fc854b17 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 11:56:07 -0500 Subject: dividing everything by devicePixelRatio --- public/assets/javascripts/mx/mx.js | 14 +++++++------- public/assets/javascripts/mx/primitives/mx.text.js | 2 +- public/assets/javascripts/mx/primitives/mx.video.js | 4 ++-- public/assets/javascripts/mx/primitives/mx.vimeo.js | 4 ++-- public/assets/javascripts/mx/primitives/mx.youtube.js | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/public/assets/javascripts/mx/mx.js b/public/assets/javascripts/mx/mx.js index 40a5f2e..d59a551 100644 --- a/public/assets/javascripts/mx/mx.js +++ b/public/assets/javascripts/mx/mx.js @@ -162,24 +162,24 @@ var MX = MX || (function (undefined) { Object.defineProperty(this, 'width', { get: function () { return width - || parseInt(self.el.style.width, 10) + || parseInt(self.el.style.width*devicePixelRatio, 10) || 0 }, set: function (val) { width = val - this.el.style.width = width + 'px' + this.el.style.width = (width/devicePixelRatio) + 'px' } }) Object.defineProperty(this, 'height', { get: function () { return height - || parseInt(self.el.style.height, 10) + || parseInt(self.el.style.height*devicePixelRatio, 10) || 0 }, set: function (val) { height = val - this.el.style.height = height + 'px' + this.el.style.height = (height/devicePixelRatio) + 'px' } }) } @@ -302,9 +302,9 @@ var MX = MX || (function (undefined) { + (-this.y).toFixed(floatPrecision) + 'px,' + (-this.z).toFixed(floatPrecision) + 'px) ' + 'scale3d(' - + this.scaleX.toFixed(floatPrecision) + ',' - + this.scaleY.toFixed(floatPrecision) + ',' - + this.scaleZ.toFixed(floatPrecision) + ') ' + + (devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ',' + + (devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ',' + + (devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') ' if (rotationTranslation) { transformString += rotationTranslation.before diff --git a/public/assets/javascripts/mx/primitives/mx.text.js b/public/assets/javascripts/mx/primitives/mx.text.js index a0f9283..6b5681b 100644 --- a/public/assets/javascripts/mx/primitives/mx.text.js +++ b/public/assets/javascripts/mx/primitives/mx.text.js @@ -47,7 +47,7 @@ MX.Text = MX.Object3D.extend({ if (! font.color || font.color[0] == "#") { font.color = [0,0,0] } this.inner.style.fontFamily = "'" + font.family + "',sans-serif" - this.el.style.fontSize = (2 * font.size) + "pt" + this.el.style.fontSize = (2 * font.size / devicePixelRatio) + "pt" this.el.style.textAlign = font.align this.el.style.color = rgb_string(font.color) }, diff --git a/public/assets/javascripts/mx/primitives/mx.video.js b/public/assets/javascripts/mx/primitives/mx.video.js index 333e1d2..c281f02 100644 --- a/public/assets/javascripts/mx/primitives/mx.video.js +++ b/public/assets/javascripts/mx/primitives/mx.video.js @@ -31,8 +31,8 @@ MX.Video = MX.Object3D.extend({ this.player.addEventListener("loadedmetadata", this.ready.bind(this)) this.player.addEventListener("error", this.error.bind(this)) this.player.addEventListener("ended", this.finished.bind(this)) - this.player.width = this.width - this.player.height = this.height + this.player.width = "100%" + this.player.height = "100%" this.player.src = this.media.url this.player.load() diff --git a/public/assets/javascripts/mx/primitives/mx.vimeo.js b/public/assets/javascripts/mx/primitives/mx.vimeo.js index e71b105..fe5ce86 100644 --- a/public/assets/javascripts/mx/primitives/mx.vimeo.js +++ b/public/assets/javascripts/mx/primitives/mx.vimeo.js @@ -32,8 +32,8 @@ MX.Vimeo = MX.Object3D.extend({ preload.id = uid preload.setAttribute("src", "//player.vimeo.com/video/" + this.media.token + "?api=1&badge=0&controls=0branding=0&byline=0&portrait=0&title=0&" + loop + "&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.width = "100%" + preload.style.height = "100%" preload.style.border = "0" preload.style.pointerEvents = "none" preload.className = "preload" diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js index 3f342a1..5c92378 100644 --- a/public/assets/javascripts/mx/primitives/mx.youtube.js +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -31,8 +31,8 @@ MX.Youtube = MX.Object3D.extend({ preload.id = uid preload.style.backgroundImage = "url(" + this.media.thumbnail + ")" preload.style.backgroundSize = "cover" - preload.style.width = this.media.width + "px" - preload.style.height = this.media.height + "px" + preload.style.width = "100%" + preload.style.height = "100%" preload.style.pointerEvents = "none" preload.style.position = "absolute" preload.style.top = "0" -- cgit v1.2.3-70-g09d2 From 47c3a54e2e5935e4db526637ef3f108bd98fce9c Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 12:40:17 -0500 Subject: add repl script, preloads schema --- server/repl.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 server/repl.js diff --git a/server/repl.js b/server/repl.js new file mode 100644 index 0000000..ba94d45 --- /dev/null +++ b/server/repl.js @@ -0,0 +1,17 @@ +var DB_HOST = 'localhost' +var mongoose = require('mongoose') +mongoose.connect('mongodb://' + DB_HOST + '/vvalls', {}, function(){ + console.log("vvalls: connected to", DB_HOST) + var repl = require("repl").start({}); + [ "./lib/schemas/User", + "./lib/schemas/Collaborator", + "./lib/schemas/Documentation", + "./lib/schemas/Layout", + "./lib/schemas/Media", + "./lib/schemas/Project", + ].forEach(function(modName){ + // console.log(name, modName) + var namez = modName.split("/"), name = namez[namez.length-1]; + repl.context[name] = require(modName); + }); +}); -- cgit v1.2.3-70-g09d2 From 5d3b848b729c06bda5d4d6d3834b110dcbb3ef71 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:08:04 -0500 Subject: use req.ips[0] --- server/lib/auth/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js index 0c46105..79f1e34 100644 --- a/server/lib/auth/index.js +++ b/server/lib/auth/index.js @@ -86,9 +86,9 @@ var auth = { return res.redirect('/auth/usernameTaken'); } if (! user.created_ip) { - user.created_ip = util.ip2num( req.ip ) + user.created_ip = util.ip2num( req.ips[0] ) } - user.last_ip = util.ip2num( req.ip ) + user.last_ip = util.ip2num( req.ips[0] ) user.save(function(err, data){ if (err) console.err('error setting ip for user') }) req.logIn(user, function(err) { @@ -111,7 +111,7 @@ var auth = { } user.last_seen = new Date () - user.last_ip = util.ip2num( req.ip ) + user.last_ip = util.ip2num( req.ips[0] ) user.save(function(err, data){ if (err) console.err('error setting ip for user') }) req.logIn(user, function(err) { @@ -171,8 +171,8 @@ var auth = { displayName: username, password: password, email: email, - created_ip: util.ip2num( req.ip ), - last_ip: util.ip2num( req.ip ), + created_ip: util.ip2num( req.ips[0] ), + last_ip: util.ip2num( req.ips[0] ), created_at: new Date (), last_seen: new Date (), } -- cgit v1.2.3-70-g09d2 From 9d5c4dcc8e45e96ee9a976ca337a9d389750fb8a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:10:03 -0500 Subject: sanity check --- server/lib/util.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/lib/util.js b/server/lib/util.js index 1f63a30..273d7d1 100644 --- a/server/lib/util.js +++ b/server/lib/util.js @@ -45,7 +45,9 @@ util.cleanQuery = function (query) { } util.ip2num = function(dot) { - var d = dot.split('.'); + console.log(dot); + + var d = (dot || "127.0.0.1").split('.'); return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]); } -- cgit v1.2.3-70-g09d2 From 74c1e0ca2b343eb9084a90e7a9490f58cb2c81d1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:12:00 -0500 Subject: databaseHost --- config.json.example | 1 + server/index.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.json.example b/config.json.example index 90df381..6028021 100644 --- a/config.json.example +++ b/config.json.example @@ -3,6 +3,7 @@ "hostName": "lvh.me", "port": 3000, "socketPort": 1337, + "databaseHost": "lvh.me", "pageSize": 10, "env": { "development": 1 } } diff --git a/server/index.js b/server/index.js index 4fbd8d1..e817566 100644 --- a/server/index.js +++ b/server/index.js @@ -20,7 +20,7 @@ var http = require('http'), var app = express() var server -var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://' + config.hostName + '/vvalls') +var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://' + config.databaseHost + '/vvalls') // -- cgit v1.2.3-70-g09d2 From 668241bbbc5150f8d4f573be9a1b4c17c1d017b6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:29:02 -0500 Subject: cache x-forwarded-for ip address on session object --- server/index.js | 1 + server/lib/middleware.js | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/server/index.js b/server/index.js index e817566..9a9323c 100644 --- a/server/index.js +++ b/server/index.js @@ -68,6 +68,7 @@ site.setup = function(){ // Essential middleware // app.all('*', middleware.enableCORS); app.all('*', middleware.ensureLocals); + app.all('*', middleware.ensureIP); server = http.createServer(app) server.listen(app.get('port'), function () { diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 7b37658..ad0d228 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -33,6 +33,15 @@ var middleware = { } next(); }, + + ensureIP: function (req, res, next) { + if (req.ips) { + req.ip = req.session.ip = req.ips[0] + } + else { + req.ip = req.session.ip || "127.0.0.1" + } + }, ensureLocals: function (req, res, next) { res.locals.token = req.csrfToken(); -- cgit v1.2.3-70-g09d2 From 0965d0011f1858adae736cfd4df8e88cf1e24893 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:30:56 -0500 Subject: z --- server/lib/auth/index.js | 10 +++++----- server/lib/middleware.js | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js index 79f1e34..0c46105 100644 --- a/server/lib/auth/index.js +++ b/server/lib/auth/index.js @@ -86,9 +86,9 @@ var auth = { return res.redirect('/auth/usernameTaken'); } if (! user.created_ip) { - user.created_ip = util.ip2num( req.ips[0] ) + user.created_ip = util.ip2num( req.ip ) } - user.last_ip = util.ip2num( req.ips[0] ) + 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) { @@ -111,7 +111,7 @@ var auth = { } user.last_seen = new Date () - user.last_ip = util.ip2num( req.ips[0] ) + 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) { @@ -171,8 +171,8 @@ var auth = { displayName: username, password: password, email: email, - created_ip: util.ip2num( req.ips[0] ), - last_ip: util.ip2num( req.ips[0] ), + created_ip: util.ip2num( req.ip ), + last_ip: util.ip2num( req.ip ), created_at: new Date (), last_seen: new Date (), } diff --git a/server/lib/middleware.js b/server/lib/middleware.js index ad0d228..2d24693 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -38,9 +38,10 @@ var middleware = { if (req.ips) { req.ip = req.session.ip = req.ips[0] } - else { + else if (req.session.ip) { req.ip = req.session.ip || "127.0.0.1" } + next() }, ensureLocals: function (req, res, next) { -- cgit v1.2.3-70-g09d2 From 58e1ca092e01da7b13e133a0ea50c9767bd48744 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:35:21 -0500 Subject: session.save --- server/lib/middleware.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 2d24693..173701d 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -37,6 +37,7 @@ var middleware = { ensureIP: function (req, res, next) { if (req.ips) { req.ip = req.session.ip = req.ips[0] + req.session.save() } else if (req.session.ip) { req.ip = req.session.ip || "127.0.0.1" -- cgit v1.2.3-70-g09d2 From c9325286ba7fcb38166deff8937105789edfb1d2 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 24 Nov 2014 17:40:53 -0500 Subject: need to store ip on the session due to haproxy --- server/lib/auth/index.js | 10 +++++----- server/lib/middleware.js | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js index 0c46105..a9a2400 100644 --- a/server/lib/auth/index.js +++ b/server/lib/auth/index.js @@ -86,9 +86,9 @@ var auth = { return res.redirect('/auth/usernameTaken'); } if (! user.created_ip) { - user.created_ip = util.ip2num( req.ip ) + user.created_ip = util.ip2num( req.session.ip ) } - user.last_ip = util.ip2num( req.ip ) + user.last_ip = util.ip2num( req.session.ip ) user.save(function(err, data){ if (err) console.err('error setting ip for user') }) req.logIn(user, function(err) { @@ -111,7 +111,7 @@ var auth = { } user.last_seen = new Date () - user.last_ip = util.ip2num( req.ip ) + user.last_ip = util.ip2num( req.session.ip ) user.save(function(err, data){ if (err) console.err('error setting ip for user') }) req.logIn(user, function(err) { @@ -171,8 +171,8 @@ var auth = { displayName: username, password: password, email: email, - created_ip: util.ip2num( req.ip ), - last_ip: util.ip2num( req.ip ), + created_ip: util.ip2num( req.session.ip ), + last_ip: util.ip2num( req.session.ip ), created_at: new Date (), last_seen: new Date (), } diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 173701d..4848ab0 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -35,13 +35,13 @@ var middleware = { }, ensureIP: function (req, res, next) { - if (req.ips) { + if (req.session.ip) { + req.ip = req.session.ip || "127.0.0.1" + } + else if (req.ips) { req.ip = req.session.ip = req.ips[0] req.session.save() } - else if (req.session.ip) { - req.ip = req.session.ip || "127.0.0.1" - } next() }, -- cgit v1.2.3-70-g09d2 From 6a4828631b4ee55f453a34e4aeb3be7d46eb799e Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 25 Nov 2014 12:14:36 -0500 Subject: hide 360 thing --- public/assets/stylesheets/app.css | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 218f38b..e33a22d 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -3113,6 +3113,9 @@ a[data-role="forgot-password"] { .reader iframe { display:none; } + #threesixty { + display:inline; + } } @media screen and (orientation:portrait) { @@ -3149,12 +3152,7 @@ a[data-role="forgot-password"] { pointer-events:none; } -@media screen and (orientation:landscape) { - #threesixty { - display:inline; - } -} @media screen and (orientation:landscape) and (max-width: 680px){ .projectList.about .item span:nth-child(1) { height: 180px; -- cgit v1.2.3-70-g09d2 From 161a32efda5ed3fa243770d23c1d756a90bb2104 Mon Sep 17 00:00:00 2001 From: ryderr Date: Tue, 25 Nov 2014 12:14:58 -0500 Subject: hide 360 thing --- public/assets/stylesheets/app.css | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index e33a22d..3c380ef 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -2908,6 +2908,18 @@ a[data-role="forgot-password"] { 100%{height:500px;top:2px;} } + +#threesixty { + display:none; + width:80px; + z-index: 3; + position: fixed; + bottom: 0; + right: 0; + pointer-events:none; +} + + /* KEYBOARD SHORTCUTS */ .keyboard { float: left; width: 50%; margin-top: 50px; } @@ -3142,16 +3154,6 @@ a[data-role="forgot-password"] { } } -#threesixty { - display:none; - width:80px; - z-index: 3; - position: fixed; - bottom: 0; - right: 0; - pointer-events:none; -} - @media screen and (orientation:landscape) and (max-width: 680px){ .projectList.about .item span:nth-child(1) { -- cgit v1.2.3-70-g09d2 From 150a5ef3ab0dbd8a63009ddad02a6e9df007d824 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Thu, 27 Nov 2014 15:21:23 -0500 Subject: tabs/spaces --- public/assets/javascripts/ui/lib/AlertModal.js | 38 ++-- public/assets/javascripts/ui/lib/ConfirmModal.js | 36 +-- public/assets/javascripts/ui/lib/ErrorModal.js | 38 ++-- public/assets/javascripts/ui/lib/FormView.js | 224 +++++++++--------- public/assets/javascripts/ui/lib/ModalView.js | 84 +++---- public/assets/javascripts/ui/lib/UploadView.js | 156 ++++++------- public/assets/javascripts/ui/lib/View.js | 278 +++++++++++------------ 7 files changed, 427 insertions(+), 427 deletions(-) diff --git a/public/assets/javascripts/ui/lib/AlertModal.js b/public/assets/javascripts/ui/lib/AlertModal.js index 1b0f40f..a4bf241 100644 --- a/public/assets/javascripts/ui/lib/AlertModal.js +++ b/public/assets/javascripts/ui/lib/AlertModal.js @@ -1,25 +1,25 @@ var AlertModal = new( ModalFormView.extend({ - el: ".mediaDrawer.alert", + el: ".mediaDrawer.alert", - events: { - "click .ok": "advance", - "click .close": "advance", - }, - - alert: function(message, callback){ - this.$(".message").empty().append(message) - this.callback = callback - this.show() - this.$(".ok").focus() - }, - - advance: function(e){ - e && e.preventDefault() - this.hide() - this.callback && this.callback() - this.callback = null - } + events: { + "click .ok": "advance", + "click .close": "advance", + }, + + alert: function(message, callback){ + this.$(".message").empty().append(message) + this.callback = callback + this.show() + this.$(".ok").focus() + }, + + advance: function(e){ + e && e.preventDefault() + this.hide() + this.callback && this.callback() + this.callback = null + } })) diff --git a/public/assets/javascripts/ui/lib/ConfirmModal.js b/public/assets/javascripts/ui/lib/ConfirmModal.js index 01720bb..a72b31e 100644 --- a/public/assets/javascripts/ui/lib/ConfirmModal.js +++ b/public/assets/javascripts/ui/lib/ConfirmModal.js @@ -1,24 +1,24 @@ var ConfirmModal = new( ModalFormView.extend({ - el: ".mediaDrawer.confirm", + el: ".mediaDrawer.confirm", - events: { - "click .yes": "advance", - "click .no": "hide", - }, - - confirm: function(question, callback){ - this.$(".question").empty().append(question) - this.callback = callback - this.show() - }, - - advance: function(e){ - e && e.preventDefault() - this.hide() - this.callback && this.callback() - this.callback = null - } + events: { + "click .yes": "advance", + "click .no": "hide", + }, + + confirm: function(question, callback){ + this.$(".question").empty().append(question) + this.callback = callback + this.show() + }, + + advance: function(e){ + e && e.preventDefault() + this.hide() + this.callback && this.callback() + this.callback = null + } }) ) \ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/ErrorModal.js b/public/assets/javascripts/ui/lib/ErrorModal.js index 8b01077..cfc2e6d 100644 --- a/public/assets/javascripts/ui/lib/ErrorModal.js +++ b/public/assets/javascripts/ui/lib/ErrorModal.js @@ -1,26 +1,26 @@ var ErrorModal = new( ModalFormView.extend({ - el: ".mediaDrawer.error", + el: ".mediaDrawer.error", - events: { - "click .ok": "advance", - "click .close": "advance", - }, - - alert: function(message, callback){ - this.$(".errorList").empty().append(message) - this.callback = callback - this.show() - this.$(".ok").focus() - }, - - advance: function(e){ - e && e.preventDefault() - this.hide() - this.callback && this.callback() - this.callback = null - } + events: { + "click .ok": "advance", + "click .close": "advance", + }, + + alert: function(message, callback){ + this.$(".errorList").empty().append(message) + this.callback = callback + this.show() + this.$(".ok").focus() + }, + + advance: function(e){ + e && e.preventDefault() + this.hide() + this.callback && this.callback() + this.callback = null + } })) diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index b3a4c71..f5845e7 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -1,135 +1,135 @@ var FormView = View.extend({ - method: "post", - useMinotaur: false, + method: "post", + useMinotaur: false, - events: { - "submit form": "save" - }, + events: { + "submit form": "save" + }, - initialize: function(opt){ - if (opt && opt.parent) { - this.parent = opt.parent - } - this.$form = this.$("form") - this.$errors = this.$(".errors") - this.$errorList = this.$(".errorList") - }, + initialize: function(opt){ + if (opt && opt.parent) { + this.parent = opt.parent + } + this.$form = this.$("form") + this.$errors = this.$(".errors") + this.$errorList = this.$(".errorList") + }, - reset: function(){ - this.$("input,textarea").not("[type='submit']").not("[type='hidden']").val("") - }, - - showErrors: function(errors){ - if (errors && errors.length) { - this.$errorList.empty(); - for (var i in errors) { - this.$errorList.append('
' + errors[i] + '
'); - } - this.$errors.css("opacity", 1.0); - setTimeout(function(){ - this.$errors.show().css("opacity", 1.0); - }.bind(this), 200) - } - }, - - serialize: function(){ - var fd = new FormData(), hasCSRF = false - - this.$("input[name], select[name], textarea[name]").each( function(){ - if (this.type == "file") { - if (this.files.length > 0) { - fd.append(this.name, this.files[0]); - } - } - else if (this.type == "password") { - if (this.value.length > 0) { - fd.append(this.name, SHA1.hex('lol$' + this.value + '$vvalls')) - } - } - else { - fd.append(this.name, this.value); - hasCSRF = hasCSRF || this.name == "_csrf" - } - }); - - if (! hasCSRF) { + reset: function(){ + this.$("input,textarea").not("[type='submit']").not("[type='hidden']").val("") + }, + + showErrors: function(errors){ + if (errors && errors.length) { + this.$errorList.empty(); + for (var i in errors) { + this.$errorList.append('
' + errors[i] + '
'); + } + this.$errors.css("opacity", 1.0); + setTimeout(function(){ + this.$errors.show().css("opacity", 1.0); + }.bind(this), 200) + } + }, + + serialize: function(){ + var fd = new FormData(), hasCSRF = false + + this.$("input[name], select[name], textarea[name]").each( function(){ + if (this.type == "file") { + if (this.files.length > 0) { + fd.append(this.name, this.files[0]); + } + } + else if (this.type == "password") { + if (this.value.length > 0) { + fd.append(this.name, SHA1.hex('lol$' + this.value + '$vvalls')) + } + } + else { + fd.append(this.name, this.value); + hasCSRF = hasCSRF || this.name == "_csrf" + } + }); + + if (! hasCSRF) { fd.append("_csrf", $("[name=_csrf]").val()) } - - return fd - }, - - save: function(e, successCallback, errorCallback){ - e && e.preventDefault() + + return fd + }, + + save: function(e, successCallback, errorCallback){ + e && e.preventDefault() - this.$errors.hide().css("opacity", 0.0); - - if (this.validate) { - var errors = this.validate() - if (errors && errors.length) { - if (errorCallback) { - errorCallback(errors) - } - else { + this.$errors.hide().css("opacity", 0.0); + + if (this.validate) { + var errors = this.validate() + if (errors && errors.length) { + if (errorCallback) { + errorCallback(errors) + } + else { this.showErrors(errors) - } - return - } - } - - var action = typeof this.action == "function" ? this.action() : this.action - if (! action) return + } + return + } + } + + var action = typeof this.action == "function" ? this.action() : this.action + if (! action) return - var request = $.ajax({ - url: action, - type: this.method, - data: this.serialize(), - dataType: "json", - processData: false, - contentType: false, - }) + var request = $.ajax({ + url: action, + type: this.method, + data: this.serialize(), + dataType: "json", + processData: false, + contentType: false, + }) if (this.useMinotaur) { Minotaur.show() } - - request.done($.proxy(function (response) { - if (this.useMinotaur) { - Minotaur.hide() - } - if (response.error) { - var errors = [] - for (var key in response.error.errors) { - errors.push(response.error.errors[key].message); - } - if (errorCallback) { - errorCallback(errors) - } - else { + + request.done($.proxy(function (response) { + if (this.useMinotaur) { + Minotaur.hide() + } + if (response.error) { + var errors = [] + for (var key in response.error.errors) { + errors.push(response.error.errors[key].message); + } + if (errorCallback) { + errorCallback(errors) + } + else { this.showErrors(errors) - } - return - } - else { - if (successCallback) { - successCallback(response) - } - if (this.success) { - this.success(response) - } - } - }, this)); - } + } + return + } + else { + if (successCallback) { + successCallback(response) + } + if (this.success) { + this.success(response) + } + } + }, this)); + } }) var ModalFormView = ModalView.extend(FormView.prototype).extend({ - load: function(){ - this.reset() - this.show() - } + load: function(){ + this.reset() + this.show() + } }) diff --git a/public/assets/javascripts/ui/lib/ModalView.js b/public/assets/javascripts/ui/lib/ModalView.js index 1c41861..f70fbb3 100644 --- a/public/assets/javascripts/ui/lib/ModalView.js +++ b/public/assets/javascripts/ui/lib/ModalView.js @@ -1,50 +1,50 @@ var ModalView = View.extend({ - events: { - "click .close": 'close', - }, - - initialize: function(opt){ - if (opt && opt.parent) { - this.parent = opt.parent - } - }, - - usesFileUpload: false, - - show: function(){ - $(".mediaDrawer").removeClass("active") - - if (! this.usesFileUpload) { - $(".fileUpload").removeClass("active") - } - if (this.fixedClose) { - $("#fixed_close").addClass("active") - $("#fixed_close").bind("click", this.hide.bind(this)) - } - - this.$el.addClass("active") + events: { + "click .close": 'close', + }, + + initialize: function(opt){ + if (opt && opt.parent) { + this.parent = opt.parent + } + }, + + usesFileUpload: false, + + show: function(){ + $(".mediaDrawer").removeClass("active") + + if (! this.usesFileUpload) { + $(".fileUpload").removeClass("active") + } + if (this.fixedClose) { + $("#fixed_close").addClass("active") + $("#fixed_close").bind("click", this.hide.bind(this)) + } + + this.$el.addClass("active") $("body").addClass("noOverflow") - }, + }, - hide: function(){ + hide: function(){ // $(".mediaDrawer, .room1").removeClass("active editing"); - if (this.fixedClose) { - $("#fixed_close").removeClass("active") - $("#fixed_close").unbind("click", this.hide.bind(this)) - } - this.$el.removeClass("active"); + if (this.fixedClose) { + $("#fixed_close").removeClass("active") + $("#fixed_close").unbind("click", this.hide.bind(this)) + } + this.$el.removeClass("active"); $("body").removeClass("noOverflow"); - }, - - close: function(){ - if (window.isModalView) { - window.location.pathname = "/" - } - else { - history.pushState(null, document.title, app.router.originalPath) - this.hide() - } - } + }, + + close: function(){ + if (window.isModalView) { + window.location.pathname = "/" + } + else { + history.pushState(null, document.title, app.router.originalPath) + this.hide() + } + } }) diff --git a/public/assets/javascripts/ui/lib/UploadView.js b/public/assets/javascripts/ui/lib/UploadView.js index 4b56828..d1e2b73 100644 --- a/public/assets/javascripts/ui/lib/UploadView.js +++ b/public/assets/javascripts/ui/lib/UploadView.js @@ -3,94 +3,94 @@ var UploadView = View.extend({ // define uploadAction - events: { - "change [type=file]": "handleFileSelect", - "submit form": "preventDefault", - }, - - initialize: function(){ - this.$file = this.$("[type=file]") - this.$upload = this.$(".upload-icon") + events: { + "change [type=file]": "handleFileSelect", + "submit form": "preventDefault", + }, + + initialize: function(){ + this.$file = this.$("[type=file]") + this.$upload = this.$(".upload-icon") }, beforeUpload: function(){ }, - + handleFileSelect: function(e) { - e.stopPropagation(); - e.preventDefault(); - - this.beforeUpload() + e.stopPropagation(); + e.preventDefault(); + + this.beforeUpload() - var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; + var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; - for (var i = 0, f; f = files[i]; i++) { - if ( ! f.type.match('image.*')) { - continue; - } - - this.getImageDimensions(f) - } - }, - - getImageDimensions: function(f){ - var base = this - - this.$upload.addClass('uploading') + for (var i = 0, f; f = files[i]; i++) { + if ( ! f.type.match('image.*')) { + continue; + } + + this.getImageDimensions(f) + } + }, + + getImageDimensions: function(f){ + var base = this + + this.$upload.addClass('uploading') - var reader = new FileReader(); + var reader = new FileReader(); - reader.onload = function(e) { - var image = new Image() - image.onload = function(){ - var width = image.naturalWidth, - height = image.naturalHeight - base.upload(f, width, height) - } - image.src = e.target.result - } - - reader.readAsDataURL(f); - }, - - upload: function(f, width, height){ - var fd = new FormData() - fd.append('image', f) - fd.append('width', width) - fd.append('height', height) - fd.append('_csrf', $("[name=_csrf]").val()) - - if (this.mediaTag) { - fd.append('tag', this.mediaTag) - } + reader.onload = function(e) { + var image = new Image() + image.onload = function(){ + var width = image.naturalWidth, + height = image.naturalHeight + base.upload(f, width, height) + } + image.src = e.target.result + } + + reader.readAsDataURL(f); + }, + + upload: function(f, width, height){ + var fd = new FormData() + fd.append('image', f) + fd.append('width', width) + fd.append('height', height) + fd.append('_csrf', $("[name=_csrf]").val()) + + if (this.mediaTag) { + fd.append('tag', this.mediaTag) + } - var request = $.ajax({ - url: this.uploadAction, - type: "post", - data: fd, - dataType: "json", - processData: false, - contentType: false, - }) - request.done(this.success.bind(this)) - }, - - success: function(media){ - if (media.error) { - // console.log(media.error) + var request = $.ajax({ + url: this.uploadAction, + type: "post", + data: fd, + dataType: "json", + processData: false, + contentType: false, + }) + request.done(this.success.bind(this)) + }, + + success: function(media){ + if (media.error) { + // console.log(media.error) this.$upload.removeClass('uploading') - this.error(media.error) - return - } - this.$upload.removeClass('uploading') - this.add(media) - }, - - add: function(media){ - console.log(media) - }, - - error: function(error){ - }, + this.error(media.error) + return + } + this.$upload.removeClass('uploading') + this.add(media) + }, + + add: function(media){ + console.log(media) + }, + + error: function(error){ + }, }) diff --git a/public/assets/javascripts/ui/lib/View.js b/public/assets/javascripts/ui/lib/View.js index 3c65131..9a8ab5b 100644 --- a/public/assets/javascripts/ui/lib/View.js +++ b/public/assets/javascripts/ui/lib/View.js @@ -1,142 +1,142 @@ var View = (function($, _){ - var View = function(options) { - this._id = _.uniqueId('view') - this.type = "view" - options || (options = {}); - _.extend(this, _.pick(options, viewOptions)) - this._ensureElement() - this.initialize.apply(this, arguments) - this.delegateEvents() - } - - var delegateEventSplitter = /^(\S+)\s*(.*)$/; - - var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; - - _.extend(View.prototype, { - - // The default `tagName` of a View's element is `"div"`. - tagName: 'div', - - $: function(selector) { - return this.$el.find(selector); - }, - - initialize: function(){}, - - setElement: function(element, delegate) { - if (this.$el) this.undelegateEvents(); - this.$el = element instanceof $ ? element : $(element); - this.el = this.$el[0]; - if (delegate !== false) this.delegateEvents(); - return this; - }, - - // Set callbacks, where `this.events` is a hash of - // - // *{"event selector": "callback"}* - // - // { - // 'mousedown .title': 'edit', - // 'click .button': 'save', - // 'click .open': function(e) { ... } - // } - // - // pairs. Callbacks will be bound to the view, with `this` set properly. - // Uses event delegation for efficiency. - // Omitting the selector binds the event to `this.el`. - // This only works for delegate-able events: not `focus`, `blur`, and - // not `change`, `submit`, and `reset` in Internet Explorer. - delegateEvents: function(events) { - if (!(events || (events = _.result(this, 'events')))) return this; - this.undelegateEvents(); - for (var key in events) { - var method = events[key]; - if (!_.isFunction(method)) method = this[events[key]]; - if (!method) continue; - - var match = key.match(delegateEventSplitter); - var eventName = match[1], selector = match[2]; - method = _.bind(method, this); - eventName += '.delegateEvents' + this._id; - if (is_mobile && (selector === 'mouseenter' || selector === 'mouseleave')) { - continue - } - else if (selector === '') { - this.$el.on(eventName, method); - } else { - this.$el.on(eventName, selector, method); - } - } - return this; - }, - - // Clears all callbacks previously bound to the view with `delegateEvents`. - undelegateEvents: function() { - this.$el.off('.delegateEvents' + this._id); - return this; - }, - - // Ensure that the View has a DOM element to render into. - // If `this.el` is a string, pass it through `$()`, take the first - // matching element, and re-assign it to `el`. Otherwise, create - // an element from the `id`, `className` and `tagName` properties. - _ensureElement: function() { - this.setElement(_.result(this, 'el'), false); - }, - - preventDefault: function(e){ - e && e.preventDefault() - }, - - stopPropagation: function(e){ - e && e.stopPropagation() - }, - - }); - - - var extend = function(protoProps, staticProps) { - var staticProps = staticProps || {} - var parent = this; - var child; - var childEvents = {}; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent's constructor. - if (protoProps && _.has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function(){ return parent.apply(this, arguments); }; - } - - // Extend events so we can subclass views - _.extend(childEvents, parent.prototype.events, protoProps.events) - - // Add static properties to the constructor function, if supplied. - _.extend(child, parent, staticProps); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function. - var Surrogate = function(){ this.constructor = child; }; - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate; - - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) _.extend(child.prototype, protoProps); - - // Set a convenience property in case the parent's prototype is needed - // later. - child.prototype.__super__ = parent.prototype; - child.prototype.events = childEvents - - return child; - }; - - View.extend = extend; - - return View; + var View = function(options) { + this._id = _.uniqueId('view') + this.type = "view" + options || (options = {}); + _.extend(this, _.pick(options, viewOptions)) + this._ensureElement() + this.initialize.apply(this, arguments) + this.delegateEvents() + } + + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + _.extend(View.prototype, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + $: function(selector) { + return this.$el.find(selector); + }, + + initialize: function(){}, + + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof $ ? element : $(element); + this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save', + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. + delegateEvents: function(events) { + if (!(events || (events = _.result(this, 'events')))) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[events[key]]; + if (!method) continue; + + var match = key.match(delegateEventSplitter); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this._id; + if (is_mobile && (selector === 'mouseenter' || selector === 'mouseleave')) { + continue + } + else if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } + } + return this; + }, + + // Clears all callbacks previously bound to the view with `delegateEvents`. + undelegateEvents: function() { + this.$el.off('.delegateEvents' + this._id); + return this; + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + this.setElement(_.result(this, 'el'), false); + }, + + preventDefault: function(e){ + e && e.preventDefault() + }, + + stopPropagation: function(e){ + e && e.stopPropagation() + }, + + }); + + + var extend = function(protoProps, staticProps) { + var staticProps = staticProps || {} + var parent = this; + var child; + var childEvents = {}; + + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent's constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } + + // Extend events so we can subclass views + _.extend(childEvents, parent.prototype.events, protoProps.events) + + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); + + // Set the prototype chain to inherit from `parent`, without calling + // `parent`'s constructor function. + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; + + // Add prototype properties (instance properties) to the subclass, + // if supplied. + if (protoProps) _.extend(child.prototype, protoProps); + + // Set a convenience property in case the parent's prototype is needed + // later. + child.prototype.__super__ = parent.prototype; + child.prototype.events = childEvents + + return child; + }; + + View.extend = extend; + + return View; })(jQuery, _) -- cgit v1.2.3-70-g09d2 From f9be43e4cce6b57f41a4e2242f019e969b081d37 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 12:43:28 -0500 Subject: view project button in settings --- public/assets/javascripts/ui/editor/EditorSettings.js | 15 +++++++++++++++ server/lib/util.js | 10 +++------- views/controls/editor/settings.ejs | 6 ++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index 026607a..b319404 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -18,6 +18,7 @@ var EditorSettings = FormView.extend({ "click [data-role='clear-project']": 'clear', "click [data-role='destroy-project']": 'destroy', "click [data-role='toggle-map']": 'toggleMap', + "click [data-role='view-project']": 'viewProject', "click #startText": "setStartPosition", "click #moveText": "confirmStartPosition", "click #confirmText": "setStartPosition", @@ -217,11 +218,25 @@ var EditorSettings = FormView.extend({ this.isVisible = true }, + viewAfterSave: false, + viewProject: function(e){ + e.preventDefault() + Minotaur.unwatch(this) + Minotaur.hide() + this.viewAfterSave = true + this.save() + }, + success: function(data){ this.$id.val(data._id) this.$name.val(data.name) this.action = this.updateAction + if (this.viewAfterSave) { + window.location.pathname = "/project/" + data.slug + return + } + Minotaur.unwatch(this) Minotaur.hide() diff --git a/server/lib/util.js b/server/lib/util.js index 273d7d1..e3fd1ed 100644 --- a/server/lib/util.js +++ b/server/lib/util.js @@ -10,8 +10,9 @@ var entities = new RegExp("[<>&]", 'g') var util = {} -util.trim = function (s){ return (s || "").replace(whitespaceHead,"").replace(whitespaceTail,"") } - +util.trim = function (s){ + return (s || "").replace(whitespaceHead,"").replace(whitespaceTail,"") +} util.slugify = function (s){ return (s || "").toLowerCase().replace(whitespace,"-").replace(nonAlphanumerics, '-').replace(consecutiveDashes,"-") } @@ -33,7 +34,6 @@ util.escapeRegExp = function (s) { util.htmlize = function(s) { return s.replace(/\n/g,"
") } - util.cleanQuery = function (query) { var update = _.extend({}, query); delete update._id; @@ -43,14 +43,10 @@ util.cleanQuery = function (query) { delete update.created_by; return update; } - util.ip2num = function(dot) { - console.log(dot); - var d = (dot || "127.0.0.1").split('.'); return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]); } - util.num2ip = function(num) { if (! num) return "" var d = num % 256; diff --git a/views/controls/editor/settings.ejs b/views/controls/editor/settings.ejs index cd17382..cd915c5 100644 --- a/views/controls/editor/settings.ejs +++ b/views/controls/editor/settings.ejs @@ -27,6 +27,12 @@ Edit map + + + + View project + +
-- cgit v1.2.3-70-g09d2 From dbdc7bf9b1922935334e44637b7bdcb534386004 Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 1 Dec 2014 13:08:48 -0500 Subject: room border issue in mobile --- public/assets/stylesheets/app.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 3c380ef..5effc00 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -3072,7 +3072,8 @@ a[data-role="forgot-password"] { } .projectList .room { width: 100%; - height: 230px; + height:230px; + height: 69vw; margin: 0; } .mediaDrawer form h2 { -- cgit v1.2.3-70-g09d2 From dc4cd71e3a0585a419898c834360f42f5bd09bd4 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 13:03:37 -0500 Subject: delete wallpaper with scissors --- .../javascripts/ui/editor/WallpaperPicker.js | 29 ++++++++++++++++---- public/assets/stylesheets/app.css | 32 ++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index e2aaeb7..3640d6d 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -5,6 +5,7 @@ var WallpaperPicker = UploadView.extend({ mediaTag: "wallpaper", createAction: "/api/media/new", uploadAction: "/api/media/upload", + destroyAction: "/api/media/destroy", events: { "contextmenu": 'contextmenu', @@ -51,8 +52,6 @@ var WallpaperPicker = UploadView.extend({ this.load() } } - // toggle the class that makes the cursor a paintbucket - // $("body").removeClass("pastePaper") }, load: function(){ @@ -78,6 +77,7 @@ var WallpaperPicker = UploadView.extend({ var swatch = document.createElement("div") swatch.className = "swatch" swatch.style.backgroundImage = "url(" + media.url + ")" + swatch.setAttribute("data-id", media._id) this.$swatches.append(swatch) this.$swatches.show() this.$(".txt").hide() @@ -104,23 +104,41 @@ var WallpaperPicker = UploadView.extend({ }, pick: function(e){ - app.tube('cancel-wallpaper') var $swatch = $(e.currentTarget) - this.follow( e, $swatch.css('background-image') ) - this.parent.presets.modified = true + if (Scenery.nextWallpaper == "none") { + var _id = $swatch[0].getAttribute("data-id") + $swatch.remove() + this.destroy(_id, function(){}) + } + else { + app.tube('cancel-wallpaper') + this.follow( e, $swatch.css('background-image') ) + this.parent.presets.modified = true + } }, remove: function(e){ if (Scenery.nextWallpaper) { + // remove red class to the wallpaper Scenery.nextWallpaper = null app.tube('cancel-wallpaper') } else { + // add red class to the wallpaper this.follow( e, "none" ) $(".floatingSwatch").addClass("scissors") + this.$el.addClass("deleteArmed") } }, + destroy: function(_id, cb){ + $.ajax({ + type: "delete", + url: this.destroyAction, + data: { _id: _id, _csrf: $("[name=_csrf]").val() } + }).complete(cb || function(){}) + }, + contextmenu: function(e){ if (Scenery.nextWallpaper) { e.preventDefault() @@ -159,6 +177,7 @@ var WallpaperPicker = UploadView.extend({ app.off('cancel-wallpaper', _hideCursor) $floatingSwatch.removeClass("scissors").hide() $(".floodMessage").hide() + base.$el.removeClass("deleteArmed") } function _floodRoom (e) { if (e.keyCode == 13) { diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 3c380ef..a488ad9 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1690,6 +1690,38 @@ border-left: 1px solid black; padding-bottom: 6px; } +.wallpaper.deleteArmed.active .swatches .swatch { + border: 1px solid #FF3B30; +} +.desktop .wallpaper.deleteArmed .swatch:hover { + background-color: #FF3B30; +} + +.wallpaper.deleteArmed .swatch:before { + content: "\f1eb"; + font-family: 'ionicons'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + -webkit-font-smoothing: antialiased; + font-size: 16px; + position: absolute; + background: #FF3B30; + border-radius: 50%; + margin-top: -8px; + margin-left: -8px; + color: white; + width: 20px; + height: 20px; + line-height: 16px; + text-align: center; + padding-top: 2px; +} + + + .vvbox .colors { max-width: 155px; margin-bottom: 5px; -- cgit v1.2.3-70-g09d2 From 0c4fe82f014e41069fe96b20ee964068bccab49c Mon Sep 17 00:00:00 2001 From: ryderr Date: Mon, 1 Dec 2014 13:27:08 -0500 Subject: mobile stuff --- public/assets/stylesheets/app.css | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 5effc00..98d97ac 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -3126,16 +3126,18 @@ a[data-role="forgot-password"] { .reader iframe { display:none; } - #threesixty { - display:inline; - } + +} + +.mobile .btn.marg, .mobile #share_embed { + display:none; } @media screen and (orientation:portrait) { - .aboutRoom { + .mobile .aboutRoom { display:none; } - .mx-scene{ + .mobile .mx-scene{ display:none; } .mobile #scene:after{ @@ -3143,15 +3145,15 @@ a[data-role="forgot-password"] { z-index: 3; position: fixed; display: inline-block; - width: 300px; - top: 55px; - left: 6px; + width: 100%; + top: 75px; + left: 0; font-size: 27px; font-weight: 300; line-height: 50px; border-top: 1px solid; border-bottom: 1px solid; - padding: 20px 0; + padding: 20px 7px; } } @@ -3163,16 +3165,21 @@ a[data-role="forgot-password"] { .projectList .projectItem { width: 55%; } + #threesixty { + display:inline; + } } +@media screen and (orientation:landscape) { + .mobile #threesixty { + display:inline; + } +} @media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (-webkit-min-device-pixel-ratio: 1) { .hero{ height: 500pt; } - #threesixty { - display:inline; - } #keyhint { display:none; } @@ -3186,9 +3193,6 @@ a[data-role="forgot-password"] { .hero{ height: 500pt; } - #threesixty { - display:inline; - } #keyhint { display:none; } -- cgit v1.2.3-70-g09d2 From 15058f6c83da00b54f676b9fafbb758ddef0be84 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 13:46:57 -0500 Subject: undo random scenery placement --- .../rectangles/engine/scenery/_scenery.js | 3 +++ .../rectangles/engine/scenery/randomize.js | 18 ++++++++++--- .../javascripts/rectangles/engine/scenery/undo.js | 30 +++++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js index d03e0e1..d52fe21 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js +++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js @@ -99,6 +99,7 @@ var Scenery = new function(){ } base.deserialize = function(scenery_data){ + var added = [] scenery_data.forEach(function(data){ var wall = Walls.lookup[data.wall_id] || Walls.first() var scene_media = base.add({ @@ -107,7 +108,9 @@ var Scenery = new function(){ media: data.media, id: data.id }) + added.push(scene_media) }) + return added } return base diff --git a/public/assets/javascripts/rectangles/engine/scenery/randomize.js b/public/assets/javascripts/rectangles/engine/scenery/randomize.js index 1c2eb56..6581f38 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/randomize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/randomize.js @@ -33,7 +33,7 @@ Scenery.randomize.get_dimensions = function (media_objs){ // Returns a lookup of walls to use, keyed by wall ID. Scenery.randomize.get_empty_walls = function(wall_list){ // get a list of all walls - var walls = {}; + var walls = {}, removed = []; (wall_list || Walls.list).forEach(function(wall){ walls[wall.id] = wall @@ -44,6 +44,7 @@ Scenery.randomize.get_empty_walls = function(wall_list){ Scenery.forEach(function(scenery){ if (scenery.was_randomly_placed) { // remove it and reuse this wall? + removed.push( scenery.serialize() ) Scenery.remove( scenery.id ) } else { @@ -52,7 +53,7 @@ Scenery.randomize.get_empty_walls = function(wall_list){ }) } - return walls + return { walls: walls, removed: removed } } // Randomly place a set of media objects on empty walls. @@ -60,7 +61,10 @@ Scenery.randomize.get_empty_walls = function(wall_list){ // Optionally takes a list of walls to use. Scenery.randomize.add = function (media_objs, wall_list) { var media_list = Scenery.randomize.get_dimensions(media_objs) - var walls = Scenery.randomize.get_empty_walls(wall_list) + var empty_data = Scenery.randomize.get_empty_walls(wall_list) + var walls = empty_data.walls + var removed = empty_data.removed + var added = [] var wall_ids = _.keys(walls) if (! wall_ids.length) { return } @@ -93,6 +97,7 @@ Scenery.randomize.add = function (media_objs, wall_list) { index: 0, }) scenery.was_randomly_placed = true + added.push(scenery.serialize()) } else { // artwork won't fit anywhere?? @@ -100,4 +105,11 @@ Scenery.randomize.add = function (media_objs, wall_list) { return false }) + + UndoStack.push({ + type: "randomize-scenery", + undo: { added: added, removed: removed }, + redo: { added: added, removed: removed }, + }) + } \ No newline at end of file diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 8b85d02..1232780 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -121,7 +121,7 @@ }) }, }, - + // { @@ -166,6 +166,34 @@ Minotaur.watch( app.router.editorView.settings ) }, }, + { + type: "randomize-scenery", + undo: function(state){ + state.added.forEach(function(_scenery){ + Scenery.remove(_scenery.id) + }) + var scenery_list = Scenery.deserialize(state.removed) + scenery_list.forEach(function(scenery){ + scenery.was_randomly_placed = true + }) + Scenery.resize.hide() + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + redo: function(state){ + state.removed.forEach(function(_scenery){ + Scenery.remove(_scenery.id) + }) + var scenery_list = Scenery.deserialize(state.added) + scenery_list.forEach(function(scenery){ + scenery.was_randomly_placed = true + }) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + }, + }, ]) })() -- cgit v1.2.3-70-g09d2 From 87ce2f24887f20cf34165f92b43bbfd33435f30a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 13:59:42 -0500 Subject: hiding floor/ceiling in ff --- public/assets/javascripts/rectangles/engine/rooms/builder.js | 6 ++++++ public/assets/javascripts/ui/editor/ColorControl.js | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index c95734b..5e09fab 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -261,6 +261,9 @@ el.rotationX = PI/2 el.rect = region el.side = FLOOR + if ($.browser.mozilla) { + el.el.style.display = "none" + } return el } this.make_ceiling = function (room, region) { @@ -277,6 +280,9 @@ el.rotationX = -PI/2 el.rect = region el.side = CEILING + if ($.browser.mozilla) { + el.el.style.display = "none" + } return el } this.make_wall = function (klass) { diff --git a/public/assets/javascripts/ui/editor/ColorControl.js b/public/assets/javascripts/ui/editor/ColorControl.js index 9ab2623..54a6a2e 100644 --- a/public/assets/javascripts/ui/editor/ColorControl.js +++ b/public/assets/javascripts/ui/editor/ColorControl.js @@ -47,7 +47,12 @@ var ColorControl = View.extend({ $swatch.css("background-color","rgb(" + color + ")") $swatch.data('color', color) this.$colors.append($swatch) - }.bind(this)) + }.bind(this)) + + if ($.browser.mozilla) { + $("#floor-color").parent().hide() + $("#ceiling-color").parent().hide() + } }, modes: [ "wall", "outline", "floor", "ceiling" ], -- cgit v1.2.3-70-g09d2 From 42144451294184225ceccbfe0ac9459c1c6cb1a9 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 14:35:02 -0500 Subject: nix trending --- public/assets/javascripts/ui/editor/MediaViewer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index 029252d..94a9d90 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -69,7 +69,7 @@ var MediaViewer = ModalView.extend({ show: function(){ if (! this.loaded) { this.load() - this.loadTrending() + // this.loadTrending() } else { this.parent.cursor.message("media") @@ -87,7 +87,8 @@ var MediaViewer = ModalView.extend({ load: function(){ $.get("/api/media/user", { offset: this.offset, limit: this.perPage }, this.populate.bind(this)) }, - + +/* loadTrending: function(){ var trending_imagery = [ 'https://d1ycxz9plii3tb.cloudfront.net/post_images/52ec0e20c9dc24f1d8000067/large.jpg', @@ -121,6 +122,7 @@ var MediaViewer = ModalView.extend({ if (img.complete && ! loaded) { img.onload() } }.bind(this)) }, +*/ randomize: function(){ var $divs = this.$(".active .container").find(".mediaContainer").toArray() -- cgit v1.2.3-70-g09d2 From 64f99d71c9ff0d419fad080751ba02afe9f6f3df Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 16:27:39 -0500 Subject: move tumblr load stuff into own modal; example tumblrs --- Gruntfile.js | 1 + .../assets/javascripts/ui/editor/EditorToolbar.js | 1 - public/assets/javascripts/ui/editor/EditorView.js | 1 + public/assets/javascripts/ui/editor/MediaTumblr.js | 53 ++++++++++++++++++++++ public/assets/javascripts/ui/editor/MediaUpload.js | 2 +- public/assets/javascripts/ui/editor/MediaViewer.js | 40 ++++++++-------- public/assets/javascripts/ui/lib/ModalView.js | 6 +-- public/assets/stylesheets/app.css | 11 ++++- views/controls/editor/media-drawer.ejs | 15 +++++- views/partials/scripts.ejs | 1 + 10 files changed, 104 insertions(+), 27 deletions(-) create mode 100644 public/assets/javascripts/ui/editor/MediaTumblr.js diff --git a/Gruntfile.js b/Gruntfile.js index 68828e0..21bbfb0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -117,6 +117,7 @@ module.exports = function(grunt) { "public/assets/javascripts/ui/editor/ColorControl.js", "public/assets/javascripts/ui/editor/Collaborators.js", "public/assets/javascripts/ui/editor/MediaEditor.js", + "public/assets/javascripts/ui/editor/MediaTumblr.js", "public/assets/javascripts/ui/editor/MediaUpload.js", "public/assets/javascripts/ui/editor/MediaViewer.js", "public/assets/javascripts/ui/editor/Presets.js", diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 277718a..a5ad2dd 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -59,7 +59,6 @@ var EditorToolbar = View.extend({ this.resetControls() this.toggleMap(false) this.parent.mediaViewer.show() - this.parent.mediaUpload.show() }, resetMode: function(){ diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index 4a2f712..50d3650 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -15,6 +15,7 @@ var EditorView = View.extend({ this.info = new BuilderInfo ({ parent: this }) this.mediaViewer = new MediaViewer ({ parent: this }) this.mediaUpload = new MediaUpload ({ parent: this }) + this.mediaTumblr = new MediaTumblr ({ parent: this }) this.mediaEditor = new MediaEditor ({ parent: this }) this.wallpaperPicker = new WallpaperPicker ({ parent: this }) this.colorControl = new ColorControl ({ parent: this }) diff --git a/public/assets/javascripts/ui/editor/MediaTumblr.js b/public/assets/javascripts/ui/editor/MediaTumblr.js new file mode 100644 index 0000000..47419ae --- /dev/null +++ b/public/assets/javascripts/ui/editor/MediaTumblr.js @@ -0,0 +1,53 @@ + +var MediaTumblr = ModalView.extend({ + el: "#tumblrUpload", + + events: { + 'mousedown': "stopPropagation", + "keydown .url": "enterSubmit", + "click .exampleTumblr": "loadExample", + }, + + initialize: function(opt){ + this.__super__.initialize.call(this) + this.parent = opt.parent + this.$url = this.$(".url") + }, + + show: function(){ + this.$el.addClass("active") + this.$url.val("") + }, + + hide: function(){ + this.$el.removeClass("active") + }, + + enterSubmit: function(e){ + e.stopPropagation() + if (e.keyCode == 13) { + e.preventDefault() + var url = this.$tumblrUrl.val() + this.loadTumblr(url) + } + }, + + loadTumblr: function(url){ + Parser.tumblr(url, function(media_list){ + console.log(media_list) + this.parent.mediaViewer.$foundMediaContainer.empty() + media_list.reverse().forEach(function(media){ + this.parent.mediaViewer.add(media, this.parent.mediaViewer.$foundMediaContainer) + }.bind(this)) + }.bind(this)) + }, + + loadExample: function(e){ + e.preventDefault() + var name = $(e.currentTarget).html() + var url = "http://" + name + ".tumblr.com/" + this.$url.val(url) + this.loadTumblr(url) + }, + +}) \ No newline at end of file diff --git a/public/assets/javascripts/ui/editor/MediaUpload.js b/public/assets/javascripts/ui/editor/MediaUpload.js index 9ae90e3..d09e38c 100644 --- a/public/assets/javascripts/ui/editor/MediaUpload.js +++ b/public/assets/javascripts/ui/editor/MediaUpload.js @@ -1,6 +1,6 @@ var MediaUpload = UploadView.extend({ - el: ".fileUpload", + el: "#fileUpload", createAction: "/api/media/new", uploadAction: "/api/media/upload", diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index 94a9d90..2ae5104 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -38,11 +38,11 @@ var MediaViewer = ModalView.extend({ this.$deleteMedia = this.$("#deleteMedia") this.$viewMore = this.$(".viewMore") this.$noMedia = this.$(".noMedia") - - this.$tumblrUrl = this.$("#tumblr-url") }, + mode: "user", wallpaperToggle: function(){ + this.mode = "wallpaper" this.$wallpaperMedia.addClass("active") this.$foundMedia.addClass("inactive") this.$myMedia.addClass("inactive").removeClass('active') @@ -51,19 +51,25 @@ var MediaViewer = ModalView.extend({ }, foundToggle: function(){ + this.mode = "found" this.$wallpaperMedia.removeClass("active") this.$foundMedia.addClass("active") this.$myMedia.addClass("inactive").removeClass('active') this.$("a").removeClass("active") this.$foundToggle.addClass("active") + this.parent.mediaUpload.hide() + this.parent.mediaTumblr.show() }, userToggle: function(){ + this.mode = "user" this.$wallpaperMedia.removeClass("active") this.$foundMedia.removeClass("active") this.$myMedia.removeClass("inactive").addClass('active') this.$("a").removeClass("active") this.$userToggle.addClass("active") + this.parent.mediaUpload.show() + this.parent.mediaTumblr.hide() }, show: function(){ @@ -72,8 +78,7 @@ var MediaViewer = ModalView.extend({ // this.loadTrending() } else { - this.parent.cursor.message("media") - this.__super__.show.call(this) + this.reallyShow() } }, @@ -81,8 +86,20 @@ var MediaViewer = ModalView.extend({ this.__super__.hide.call(this) this.deleteArmed(false) this.parent.mediaUpload.hide() + this.parent.mediaTumblr.hide() this.parent.cursor.message('start') }, + + reallyShow: function(){ + this.__super__.show.call(this) + if (this.mode == "user") { + this.userToggle() + } + else { + this.foundToggle() + } + this.parent.cursor.message("media") + }, load: function(){ $.get("/api/media/user", { offset: this.offset, limit: this.perPage }, this.populate.bind(this)) @@ -159,8 +176,7 @@ var MediaViewer = ModalView.extend({ } else { this.loaded = true - this.parent.cursor.message("media") - this.__super__.show.call(this) + this.reallyShow() } }, @@ -296,16 +312,4 @@ var MediaViewer = ModalView.extend({ _followCursor(e) }, - enterTumblrUrl: function(e){ - e.stopPropagation() - if (e.keyCode !== 13) { return } - var url = this.$tumblrUrl.val() - Parser.tumblr(url, function(media_list){ - console.log(media_list) - this.$foundMediaContainer.empty() - media_list.reverse().forEach(function(media){ - this.add(media, this.$foundMediaContainer) - }.bind(this)) - }.bind(this)) - }, }) diff --git a/public/assets/javascripts/ui/lib/ModalView.js b/public/assets/javascripts/ui/lib/ModalView.js index f70fbb3..6f1c729 100644 --- a/public/assets/javascripts/ui/lib/ModalView.js +++ b/public/assets/javascripts/ui/lib/ModalView.js @@ -14,10 +14,8 @@ var ModalView = View.extend({ show: function(){ $(".mediaDrawer").removeClass("active") - - if (! this.usesFileUpload) { - $(".fileUpload").removeClass("active") - } + $(".fileUpload").removeClass("active") + if (this.fixedClose) { $("#fixed_close").addClass("active") $("#fixed_close").bind("click", this.hide.bind(this)) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 5d69d75..07d1bbb 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1720,7 +1720,16 @@ border-left: 1px solid black; padding-top: 2px; } - +.exampleTumblrs { + display: block; + margin-top: 10px; + font-weight: 300; + font-size: 0.8em; +} +.exampleTumblrs a { + border-bottom: 1px dotted; + margin-left: 5px; +} .vvbox .colors { max-width: 155px; diff --git a/views/controls/editor/media-drawer.ejs b/views/controls/editor/media-drawer.ejs index 3db71d5..f9bce61 100644 --- a/views/controls/editor/media-drawer.ejs +++ b/views/controls/editor/media-drawer.ejs @@ -23,7 +23,6 @@
-
@@ -33,7 +32,7 @@
- +

@@ -43,3 +42,15 @@ ~ or ~
+ + + + +
+ + or try one of these: + risingtensions + fixoid + nopattern + +
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 61659f7..fc94992 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -113,6 +113,7 @@ + -- cgit v1.2.3-70-g09d2 From b4de393c30ab2540ce8961b394be1915729d8df6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 16:30:27 -0500 Subject: about.ejs --- server/lib/views/index.js | 6 +++++- views/about/about.ejs | 27 +++++++++++++++++++++++++++ views/partials/footer.ejs | 3 ++- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 views/about/about.ejs diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 145b5ac..6ceef7e 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -111,12 +111,16 @@ var views = module.exports = { }, docs: function (req, res){ - var name = req.params.name || "howto" + var name = req.params.name || "about" if (name == "howto") { res.render('about/' + name) return } + if (name == "about" || name == "index") { + res.render('about/' + name) + return + } if (name === "new") { res.render('docs', { diff --git a/views/about/about.ejs b/views/about/about.ejs new file mode 100644 index 0000000..e600a3d --- /dev/null +++ b/views/about/about.ejs @@ -0,0 +1,27 @@ + + + + vvalls + [[ include ../partials/meta ]] + + +
+ [[ include ../partials/header ]] + + +
+
+
+
+

About VValls

+ + + [[ include ../partials/confirm-modal ]] + [[ include ../projects/layouts-modal ]] + [[ include ../partials/sign-in ]] + [[ include ../partials/footer ]] + +
+ +[[ include ../partials/scripts ]] + diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index 7b01162..e3c572f 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -13,7 +13,8 @@

- How To + About + How To Terms Privacy Contact -- cgit v1.2.3-70-g09d2 From f6fa8808adc4dc20a4decea4b2480cf0efa8d25f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 16:44:59 -0500 Subject: about section --- views/about/about.ejs | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/views/about/about.ejs b/views/about/about.ejs index e600a3d..f59fe14 100644 --- a/views/about/about.ejs +++ b/views/about/about.ejs @@ -5,7 +5,7 @@ [[ include ../partials/meta ]] -
+
[[ include ../partials/header ]] @@ -15,7 +15,37 @@

About VValls

+
+
+ VValls is a platform for creating and sharing immersive web based 3D exhibitions. With VValls users can draw floor plans, and then apply media to the surfaces of the virtual space. VValls is the ideal solution for anyone creating immersive presentations of content, curators looking to plan shows, and artists looking to visualize their work in 3D space. VValls is completely HTML5 based – mobile and desktop compatible. +

+ Contact us with inquiries at hello@vvalls.com.
+ We are based in New York City. +
+
+
+ + + +

Dot Dash 3

+ VValls was conceived and prototyped by Larisa Leventon, Ph.D., MBA, founder of Dot Dash 3 and an M.I.T. + Brown University-trained visualization algorithm specialist. +
+
+
+ +
+
+ + + +

OKFocus

+ VValls was developed and designed by OKFocus, a forward thinking NYC based creative agency. The technology was spearheaded by Jules LaPlace, CTO, and the design by Ryder Ripps, ECD. +
+
+
+
+ [[ include ../partials/confirm-modal ]] [[ include ../projects/layouts-modal ]] [[ include ../partials/sign-in ]] @@ -25,3 +55,17 @@ [[ include ../partials/scripts ]] + \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f5bc4ca3b111a0be8ad0726b5b3d44936983f60a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 17:56:35 -0500 Subject: orient toward horizon if looking straight down --- public/assets/javascripts/mx/extensions/mx.movementsMobile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/assets/javascripts/mx/extensions/mx.movementsMobile.js b/public/assets/javascripts/mx/extensions/mx.movementsMobile.js index 8810649..95b61d1 100644 --- a/public/assets/javascripts/mx/extensions/mx.movementsMobile.js +++ b/public/assets/javascripts/mx/extensions/mx.movementsMobile.js @@ -163,7 +163,7 @@ MX.MobileMovements = function (cam) { dy += 360 } - destRotationX = MX.toRad(dx) + destRotationX = dx > 45 ? 0 : MX.toRad(dx) destRotationY += MX.toRad(dy) }, -- cgit v1.2.3-70-g09d2 From c423e246d4e18ce65861e384bee6c147aff79ddb Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 1 Dec 2014 19:05:33 -0500 Subject: IE/non css3d fallback --- public/assets/javascripts/app.js | 21 ++++++++++++++++----- public/assets/javascripts/ui/_router.js | 4 ++++ public/assets/stylesheets/app.css | 11 +++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index 01a2e54..41edafe 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -1,12 +1,9 @@ if (is_mobile) { - $("html").addClass("mobile"); -} -else if ($.browser.msie || ! has3d()) { - $("html").addClass("fallback"); + $("html").addClass("mobile") } else { - $("html").addClass("desktop"); + $("html").addClass("desktop") } @@ -22,6 +19,8 @@ app.init = function () { } app.launch = function () { + if ($.browser.msie || ! has3d()) { return app.fallback() } + var movements scene = new MX.Scene().addTo('#scene') @@ -74,6 +73,18 @@ app.launch = function () { window.scrollTo(0,0) } +app.fallback = function(){ + app.unsupported = true + var msg = "Sorry, your browser is not supported.

" + + "Please use Chrome or Safari or Firefox." + var $fallback = $("
") + $fallback.attr('id', 'fallback') + $fallback.html(msg) + $('body').append($fallback) + $("#keyhint").hide() + $("#editorView").hide() +} + app.on = function(){ app.tube.on.apply(app.tube, arguments) } diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 4219a28..3532428 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -89,6 +89,7 @@ var SiteRouter = Router.extend({ layoutEditor: function(e, name){ app.mode.builder = true app.launch() + if (app.unsupported) return this.builderView = app.controller = new BuilderView() this.builderView.load(name) @@ -117,6 +118,7 @@ var SiteRouter = Router.extend({ app.mode.editor = true app.launch() + if (app.unsupported) return layout = slugify(layout) @@ -137,6 +139,7 @@ var SiteRouter = Router.extend({ projectEditor: function(e, name){ app.mode.editor = true app.launch() + if (app.unsupported) return this.editorView = app.controller = new EditorView() this.editorView.load(name) @@ -145,6 +148,7 @@ var SiteRouter = Router.extend({ projectViewer: function(e, name){ app.mode.editor = true app.launch() + if (app.unsupported) return this.readerView = app.controller = new ReaderView() this.readerView.load(name) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 07d1bbb..aecd6be 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1150,6 +1150,17 @@ border-left: 1px solid black; .desktop .logo:hover svg { fill:white; } + +#fallback { + width: 400px; + margin: 10% auto; + border: 2px solid black; + padding: 30px 20px 30px 20px; +} +#fallback a { + border-bottom: 1px solid; +} + .profile{ padding:8px; float:right; -- cgit v1.2.3-70-g09d2 From 5985ae99cba8f98b678fade9e5df811deb482e9f Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Tue, 2 Dec 2014 12:48:30 -0500 Subject: no hero --- views/about/about.ejs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/views/about/about.ejs b/views/about/about.ejs index f59fe14..dd536be 100644 --- a/views/about/about.ejs +++ b/views/about/about.ejs @@ -8,11 +8,6 @@
[[ include ../partials/header ]] - -
-
-
-

About VValls

-- cgit v1.2.3-70-g09d2 From 6b665588eaf1690d6717edabe64882e091731117 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 10 Dec 2014 14:20:52 -0500 Subject: get accurate project count --- server/lib/views/index.js | 16 +++++++++++++--- views/profile.ejs | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 6ceef7e..8c3e63d 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -171,15 +171,20 @@ var views = module.exports = { if ( ! isOwnProfile ) { criteria.privacy = false } - views_middleware.fetchProjects(criteria, null, null, done) + views_middleware.fetchProjects(criteria, null, null, function(err, projects){ + views_middleware.fetchUserProjectCount(criteria, function(projectCount){ + done(err, projects, projectCount) + }) + }) } - function done(err, projects){ + function done(err, projects, projectCount){ if (! user) { return res.redirect('/') } res.render('profile', { isOwnProfile: isOwnProfile, profile: user, projects: projects || [], + projectCount: projectCount, ogTitle: "VValls: Profile of " + user.displayName, ogUrl: "http://vvalls.com/profile/" + user.username + "/", ogImage: user.photo, @@ -240,5 +245,10 @@ var views_middleware = { }) next(err, projects) }) - } + }, + fetchUserProjectCount: function(criteria, next){ + Project.count(criteria, function(err, count){ + next(count || 0) + }) + }, } diff --git a/views/profile.ejs b/views/profile.ejs index 5043df6..a62652c 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -46,7 +46,7 @@ [[ if (projects.length) { ]] -

[[- profile.username ]] has [[- projects.length ]] project[[- projects.length != 1 ? "s" : "" ]]

+

[[- profile.username ]] has [[- projectCount ]] project[[- projectCount != 1 ? "s" : "" ]]

[[ include projects/list-projects ]] [[ } else { ]] -- cgit v1.2.3-70-g09d2 From 2d4ed7d888727e1b973c2581b694d900e30c2ebd Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 7 Jan 2015 13:53:27 -0500 Subject: plan/subscription schemas --- server/lib/schemas/Plan.js | 36 +++++++++++++++++++++++++++ server/lib/schemas/Subscription.js | 25 +++++++++++++++++++ server/lib/views/index.js | 8 +----- server/lib/views/subscription.js | 51 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 server/lib/schemas/Plan.js create mode 100644 server/lib/schemas/Subscription.js create mode 100644 server/lib/views/subscription.js diff --git a/server/lib/schemas/Plan.js b/server/lib/schemas/Plan.js new file mode 100644 index 0000000..3e74997 --- /dev/null +++ b/server/lib/schemas/Plan.js @@ -0,0 +1,36 @@ +/* jshint node: true */ + +var mongoose = require('mongoose'), + _ = require('lodash'), + crypto = require('crypto'), + config = require('../../../config.json'), + util = require('../util'); + +var PlanSchema = new mongoose.Schema({ + name: { type: String }, + slug: { type: String }, + + monthly_price: { type: Number }, + yearly_price: { type: Number }, + + basic_layout_limit: { type: Number }, + pro_layout_limit: { type: Number }, + + stock_layout_project_limit: { type: Number }, + basic_layout_project_limit: { type: Number }, + pro_layout_project_limit: { type: Number }, + + permissions: { + basic_editor: { type: Boolean, default: false }, + pro_editor: { type: Boolean, default: false }, + solids: { type: Boolean, default: false }, + collaborators: { type: Boolean, default: false }, + no_logo: { type: Boolean, default: false }, + }, + + created_at: { type: Date, default: Date.now }, + updated_at: { type: Date, default: Date.now }, +}) + +module.exports = exports = mongoose.model('plan', PlanSchema); +exports.schema = PlanSchema; diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js new file mode 100644 index 0000000..8d0b10e --- /dev/null +++ b/server/lib/schemas/Subscription.js @@ -0,0 +1,25 @@ +/* jshint node: true */ + +var mongoose = require('mongoose'), + _ = require('lodash'), + crypto = require('crypto'), + config = require('../../../config.json'), + util = require('../util'); + +var SubscriptionSchema = new mongoose.Schema({ + user_id: { type: mongoose.Schema.ObjectId, index: true }, + + monthly_total: { type: Number }, + yearly_total: { type: Number }, + + plans: [{ + tier: { type: String }, + monthly: { type: Boolean }, + }] + + created_at: { type: Date, default: Date.now }, + updated_at: { type: Date, default: Date.now }, +}) + +module.exports = exports = mongoose.model('subscription', SubscriptionSchema); +exports.schema = SubscriptionSchema; diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 8c3e63d..3326499 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -21,6 +21,7 @@ marked.setOptions({ var views = module.exports = { staff: require('./staff'), + subscription: require('./subscription'), editor_new: function (req, res) { if (! req.user) { @@ -88,13 +89,6 @@ var views = module.exports = { }, home: function (req, res) { - // while in development, blank homepage if not logged in -/* - if (! req.user) { - res.send("") - return - } -*/ views_middleware.fetchProjects({ featured: true }, null, null, function(err, projects){ res.render('home', { projects: projects || [] diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js new file mode 100644 index 0000000..77db1a0 --- /dev/null +++ b/server/lib/views/subscription.js @@ -0,0 +1,51 @@ +/* jshint node: true */ + +var User = require('../schemas/User'), + Subscription = require('../schemas/Subscription'), + config = require('../../../config'), + middleware = require('../middleware'), + util = require('../util'), + _ = require('lodash'), + moment = require('moment'); + +var subscription = module.exports = { + + fields: { + user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", + project: "_id name slug user_id privacy created_at updated_at", + }, + + defaults: { + user: { + _id: "", username: "", displayName: "", + created_at: "", updated_at: "", created_ip: "", last_ip: "", + }, + }, + + middleware: { + }, + + helpers: { + project: function(project){ + project = project.toObject() + project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") + project.user = {} + return project + }, + }, + + route: function(app){ + app.get('/staff', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureRecentUsers, + staff.middleware.ensureUsersCount, + staff.middleware.ensureProjectsCount, + staff.middleware.ensureMediaCount, + + staff.index + ); + }, + +} -- cgit v1.2.3-70-g09d2 From 9c6f8f8568d20d75eb22955dbf2752ea777e59f8 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 7 Jan 2015 14:34:41 -0500 Subject: stub in brochure page --- public/assets/stylesheets/app.css | 14 +++++++ server/lib/schemas/Plan.js | 6 +++ server/lib/schemas/Subscription.js | 2 +- server/lib/views/index.js | 5 +++ server/lib/views/subscription.js | 1 - views/about/_blank.ejs | 2 +- views/about/about.ejs | 16 +------- views/about/brochure.ejs | 79 ++++++++++++++++++++++++++++++++++++++ views/about/howto.ejs | 2 +- views/builder.ejs | 2 +- views/docs.ejs | 2 +- views/editor.ejs | 2 +- views/home.ejs | 2 +- views/modal.ejs | 2 +- views/profile.ejs | 2 +- views/reader.ejs | 2 +- views/staff/_header.ejs | 2 +- 17 files changed, 116 insertions(+), 27 deletions(-) create mode 100644 views/about/brochure.ejs diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index aecd6be..0463e26 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -673,7 +673,21 @@ iframe.embed { font-weight: 300; } +.aboutintro { + text-align: center; + line-height: 43px; + font-size: 24px; + padding: 5% 0; + font-weight: 300; +} +.aboutintro .inner { + max-width: 800px; + margin: 0 auto; + text-align: center; +} + /* PROFILE PAGE */ + .profilePic { background-size: cover; background-position: center; diff --git a/server/lib/schemas/Plan.js b/server/lib/schemas/Plan.js index 3e74997..1057bb2 100644 --- a/server/lib/schemas/Plan.js +++ b/server/lib/schemas/Plan.js @@ -13,6 +13,12 @@ var PlanSchema = new mongoose.Schema({ monthly_price: { type: Number }, yearly_price: { type: Number }, + basic_layout_monthly_price: { type: Number }, + basic_layout_yearly_price: { type: Number }, + + pro_layout_monthly_price: { type: Number }, + pro_layout_yearly_price: { type: Number }, + basic_layout_limit: { type: Number }, pro_layout_limit: { type: Number }, diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index 8d0b10e..8315009 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -15,7 +15,7 @@ var SubscriptionSchema = new mongoose.Schema({ plans: [{ tier: { type: String }, monthly: { type: Boolean }, - }] + }], created_at: { type: Date, default: Date.now }, updated_at: { type: Date, default: Date.now }, diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 3326499..5f9088b 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -111,6 +111,11 @@ var views = module.exports = { res.render('about/' + name) return } + if (name == "brochure") { + // TODO: fetch plans + res.render('about/' + name) + return + } if (name == "about" || name == "index") { res.render('about/' + name) return diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js index 77db1a0..ba54bb4 100644 --- a/server/lib/views/subscription.js +++ b/server/lib/views/subscription.js @@ -12,7 +12,6 @@ var subscription = module.exports = { fields: { user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", - project: "_id name slug user_id privacy created_at updated_at", }, defaults: { diff --git a/views/about/_blank.ejs b/views/about/_blank.ejs index 0e9ea7e..3c23fa7 100644 --- a/views/about/_blank.ejs +++ b/views/about/_blank.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include ../partials/meta ]] diff --git a/views/about/about.ejs b/views/about/about.ejs index dd536be..2aec982 100644 --- a/views/about/about.ejs +++ b/views/about/about.ejs @@ -1,7 +1,7 @@ - vvalls + About VValls [[ include ../partials/meta ]] @@ -50,17 +50,3 @@ [[ include ../partials/scripts ]] - \ No newline at end of file diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs new file mode 100644 index 0000000..00083cf --- /dev/null +++ b/views/about/brochure.ejs @@ -0,0 +1,79 @@ + + + + VValls Subscriptions + [[ include ../partials/meta ]] + + +
+ [[ include ../partials/header ]] + +

Subscriptions

+ +
+
+ Want to get more out of VValls? Consider becoming a subscription user. +
+
+ +
+

[[- plans.free.name ]]

+
    +
  • One exhibition with pre-designed template floor plan +
+
+ +
+

[[- plans.premium.name ]]

+
    +
  • $[[- plans.premium.monthly_price ]]/mo or $[[- plans.premium.yearly_price ]]/year +
  • [[- plans.premium.stock_layout_project_limit ]] exhibitions included with pre-designed template floor plans +
  • Each new basic floor plan costs $[[- plans.premium.basic_layout_monthly_price ]]/mo + or $[[- plans.premium.basic_layout_yearly_price ]]/year, minimum 3 months +
  • Each new basic floor plan can have up to [[- plans.premium.basic_layout_project_limit ]] exhibitions +
  • VValls logo appears when embedding an exhibition on a web page +
+
+ +
+

[[- plans.pro.name ]]

+
    +
  • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year +
  • Comes with [[- plans.premium.pro_layout_limit ]] pro floor plan and [[- plans.premium.pro_layout_project_limit ]] exhibitions +
  • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo + or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months +
  • Each new pro floor plan can have up to [[- plans.pro.pro_layout_project_limit ]] exhibitions +
  • Includes planning for 3D objects in the room +
  • No VValls logo on embed +
+
+ +
+ Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you. +
+ +
+ Basic Floor plan: Rectangle-based design of any dimension. +
+ +
+ Pro Floor plan: Trace an arbitrary floorplan. +
+ + +
+

Custom

+ We offer many types of customizations and white-label options for business and educational uses. + Contact us for more information +
+ + + [[ include ../partials/confirm-modal ]] + [[ include ../projects/layouts-modal ]] + [[ include ../partials/sign-in ]] + [[ include ../partials/footer ]] + +
+ +[[ include ../partials/scripts ]] + diff --git a/views/about/howto.ejs b/views/about/howto.ejs index 5278a40..914c3b3 100644 --- a/views/about/howto.ejs +++ b/views/about/howto.ejs @@ -1,7 +1,7 @@ - vvalls + How to Use VValls [[ include ../partials/meta ]] diff --git a/views/builder.ejs b/views/builder.ejs index afb8c66..0ba4238 100644 --- a/views/builder.ejs +++ b/views/builder.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include partials/meta ]] diff --git a/views/docs.ejs b/views/docs.ejs index b3ead82..a1f081f 100644 --- a/views/docs.ejs +++ b/views/docs.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include partials/meta ]] diff --git a/views/editor.ejs b/views/editor.ejs index 656615c..74e4d6d 100755 --- a/views/editor.ejs +++ b/views/editor.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include partials/meta ]] diff --git a/views/home.ejs b/views/home.ejs index 36fc2fc..ffb0976 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include partials/meta ]] diff --git a/views/modal.ejs b/views/modal.ejs index 7ca869c..732953d 100644 --- a/views/modal.ejs +++ b/views/modal.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include partials/meta ]] diff --git a/views/profile.ejs b/views/profile.ejs index a62652c..88af6b0 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -1,7 +1,7 @@ - vvalls + VValls | [[- profile.displayName ]] [[ include partials/meta ]] diff --git a/views/reader.ejs b/views/reader.ejs index 6c9856a..7035356 100644 --- a/views/reader.ejs +++ b/views/reader.ejs @@ -1,7 +1,7 @@ - vvalls + VValls [[ include partials/meta ]] diff --git a/views/staff/_header.ejs b/views/staff/_header.ejs index 3bbf4f1..a73c12e 100644 --- a/views/staff/_header.ejs +++ b/views/staff/_header.ejs @@ -1,7 +1,7 @@ - vvalls | staff + VValls | staff [[ include ../partials/meta ]] -- cgit v1.2.3-70-g09d2 From 5dd9742da846e8db863a951f1502d0edf5a3f90b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 7 Jan 2015 18:02:13 -0500 Subject: forms for editing plans --- server/lib/schemas/Plan.js | 6 +-- server/lib/views/staff.js | 22 ++++++++ views/about/brochure.ejs | 4 +- views/staff/_nav.ejs | 6 +++ views/staff/media/index.ejs | 7 +-- views/staff/media/show.ejs | 7 +-- views/staff/media/show_404.ejs | 9 +--- views/staff/plans/_form.ejs | 109 ++++++++++++++++++++++++++++++++++++++ views/staff/plans/edit.ejs | 13 +++++ views/staff/plans/index.ejs | 54 +++++++++++++++++++ views/staff/plans/new.ejs | 15 ++++++ views/staff/projects/index.ejs | 7 +-- views/staff/projects/show.ejs | 9 +--- views/staff/projects/show_404.ejs | 7 +-- views/staff/users/index.ejs | 7 +-- views/staff/users/media.ejs | 13 ++--- views/staff/users/show.ejs | 7 +-- views/staff/users/show_404.ejs | 16 +++--- 18 files changed, 244 insertions(+), 74 deletions(-) create mode 100644 views/staff/_nav.ejs create mode 100644 views/staff/plans/_form.ejs create mode 100644 views/staff/plans/edit.ejs create mode 100644 views/staff/plans/index.ejs create mode 100644 views/staff/plans/new.ejs diff --git a/server/lib/schemas/Plan.js b/server/lib/schemas/Plan.js index 1057bb2..1208672 100644 --- a/server/lib/schemas/Plan.js +++ b/server/lib/schemas/Plan.js @@ -22,9 +22,9 @@ var PlanSchema = new mongoose.Schema({ basic_layout_limit: { type: Number }, pro_layout_limit: { type: Number }, - stock_layout_project_limit: { type: Number }, - basic_layout_project_limit: { type: Number }, - pro_layout_project_limit: { type: Number }, + stock_project_limit: { type: Number }, + basic_project_limit: { type: Number }, + pro_project_limit: { type: Number }, permissions: { basic_editor: { type: Boolean, default: false }, diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 49f492b..c3739e9 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -4,6 +4,8 @@ var User = require('../schemas/User'), Project = require('../schemas/Project'), Media = require('../schemas/Media'), Collaborator = require('../schemas/Collaborator'), + Plan = require('../schemas/Plan'), + Subscription = require('../schemas/Subscription'), config = require('../../../config'), middleware = require('../middleware'), util = require('../util'), @@ -540,6 +542,26 @@ var staff = module.exports = { res.render('staff/media/show_404') } }, + }, + + plans: { + index: function(req, res){ + res.locals.fields = ( + "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit" + ).split(" ") + + res.locals.permissions = "basic_editor pro_editor solids collaborators no_logo".split(" ") + + res.render('staff/plans/index') + }, + new: function(req, res){ + res.render('staff/plans/new') + }, + edit: function(req, res){ + res.render('staff/plans/edit') + }, } } diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index 00083cf..d816dc4 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -35,7 +35,7 @@
-
+

[[- plans.pro.name ]]

  • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year @@ -57,7 +57,7 @@
- Pro Floor plan: Trace an arbitrary floorplan. + Pro Floor plan: Trace an arbitrary floor plan.
diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs new file mode 100644 index 0000000..2115e9f --- /dev/null +++ b/views/staff/_nav.ejs @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/views/staff/media/index.ejs b/views/staff/media/index.ejs index 516af2d..3805c8e 100644 --- a/views/staff/media/index.ejs +++ b/views/staff/media/index.ejs @@ -2,12 +2,7 @@

Media

- +[[ include ../_nav ]]
diff --git a/views/staff/media/show.ejs b/views/staff/media/show.ejs index 76dcd32..9d05cb9 100644 --- a/views/staff/media/show.ejs +++ b/views/staff/media/show.ejs @@ -2,12 +2,7 @@

Media: [[- media.type ]]

- +[[ include ../_nav ]]
diff --git a/views/staff/media/show_404.ejs b/views/staff/media/show_404.ejs index f07cef2..c6bac6f 100644 --- a/views/staff/media/show_404.ejs +++ b/views/staff/media/show_404.ejs @@ -2,13 +2,8 @@

Media not found

- - +[[ include ../_nav ]] +
[[ include ../_footer ]] diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs new file mode 100644 index 0000000..b97716f --- /dev/null +++ b/views/staff/plans/_form.ejs @@ -0,0 +1,109 @@ + +
+ + +
+ +
+ + +
+ + + +
+ + +
+ +
+ + +
+ + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+ + +
+ +
+ + +
+ + + +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ + + + diff --git a/views/staff/plans/edit.ejs b/views/staff/plans/edit.ejs new file mode 100644 index 0000000..503c97d --- /dev/null +++ b/views/staff/plans/edit.ejs @@ -0,0 +1,13 @@ +[[ include ../_header ]] + +

Edit Plan

+ +[[ include ../_nav ]] + +
+ + +[[- include form ]] + + +[[ include ../_footer ]] diff --git a/views/staff/plans/index.ejs b/views/staff/plans/index.ejs new file mode 100644 index 0000000..aa6c35a --- /dev/null +++ b/views/staff/plans/index.ejs @@ -0,0 +1,54 @@ +[[ include ../_header ]] + +

Plans

+ +[[ include ../_nav ]] + +
+ + + + + [[ plans.forEach(function(plan){ ]] + + [[ }) ]] + + + + + [[ plans.forEach(function(plan){ ]] + + [[ }) ]] + + + [[ fields.forEach(function(field){ ]] + + + [[ plans.forEach(function(plan){ ]] + + [[ }) ]] + + [[ }) ]] + + [[ permissions.forEach(function(permission){ ]] + + + [[ plans.forEach(function(plan){ ]] + + [[ }) ]] + + [[ }) ]] + +
+ [[- plan.name ]] +
+ edit +
[[- field.replace(/_/," ") ]] + [[- plan[field] ]] +
[[- permission.replace(/_/," ") ]] + [[- plan.permissions[permission] ? "x" : " " ]] +
+ +
+ +[[ include ../_footer ]] diff --git a/views/staff/plans/new.ejs b/views/staff/plans/new.ejs new file mode 100644 index 0000000..d56a1c3 --- /dev/null +++ b/views/staff/plans/new.ejs @@ -0,0 +1,15 @@ +[[ include ../_header ]] + +

New Plan

+ +[[ include ../_nav ]] + +
+ +
+[[- include form ]] +
+ +[[ include ../_footer ]] + + diff --git a/views/staff/projects/index.ejs b/views/staff/projects/index.ejs index 482ea25..e4ba469 100644 --- a/views/staff/projects/index.ejs +++ b/views/staff/projects/index.ejs @@ -2,12 +2,7 @@

Projects

- +[[ include ../_nav ]]
diff --git a/views/staff/projects/show.ejs b/views/staff/projects/show.ejs index 1034b31..b090a41 100644 --- a/views/staff/projects/show.ejs +++ b/views/staff/projects/show.ejs @@ -2,13 +2,8 @@

[[- project.name ]]

- - +[[ include ../_nav ]] +
diff --git a/views/staff/projects/show_404.ejs b/views/staff/projects/show_404.ejs index 70320c0..f5e1658 100644 --- a/views/staff/projects/show_404.ejs +++ b/views/staff/projects/show_404.ejs @@ -2,12 +2,7 @@

Project not found

- +[[ include ../_nav ]]
diff --git a/views/staff/users/index.ejs b/views/staff/users/index.ejs index f14d666..1795dde 100644 --- a/views/staff/users/index.ejs +++ b/views/staff/users/index.ejs @@ -2,12 +2,7 @@

Users

- +[[ include ../_nav ]]
diff --git a/views/staff/users/media.ejs b/views/staff/users/media.ejs index c1097dd..8927c00 100644 --- a/views/staff/users/media.ejs +++ b/views/staff/users/media.ejs @@ -1,15 +1,10 @@ [[ include ../_header ]] -

User Media: [[- profile.username ]]

+

User Media: [[- profile.username ]]

- - -
+[[ include ../_nav ]] + +
[[ include ../_pagination ]] [[ include ../_gallery ]] diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index 8e9b447..4ce1d9a 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -1,12 +1,7 @@ [[ include ../_header ]]

User: [[- profile.username ]]

- +[[ include ../_nav ]]
diff --git a/views/staff/users/show_404.ejs b/views/staff/users/show_404.ejs index bcd0271..11663fa 100644 --- a/views/staff/users/show_404.ejs +++ b/views/staff/users/show_404.ejs @@ -1,13 +1,9 @@ [[ include ../_header ]] -

User not found

- - - -
+ +

User not found

+ +[[ include ../_nav ]] + +
[[ include ../_footer ]] -- cgit v1.2.3-70-g09d2 From 190a145cf1433fde570df1ac9784d4c5cea77d3d Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 7 Jan 2015 18:28:46 -0500 Subject: everything but saving --- server/lib/middleware.js | 2 +- server/lib/views/staff.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 4848ab0..797d677 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -75,7 +75,7 @@ var middleware = { } next() }) - } + } else { req.project = null next() diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index c3739e9..ce676ed 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -120,6 +120,31 @@ var staff = module.exports = { next() }) }, + + ensurePlans: function(req, res, next){ + Plan.exec(function (err, plans) { + res.locals.plans = plans.map(staff.helpers.plan) + next() + }) + }, + ensurePlan: function (req, res, next) { + if (req.params.slug) { + Plan.findOne({ slug: req.params.slug }, function(err, plan){ + if (err || ! plan) { + console.error(err) + req.plan = null + } + else { + req.plan = plan + } + next() + }) + } + else { + req.plan = null + next() + } + }, ensureRecentProjects: function(req, res, next){ var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } @@ -424,7 +449,43 @@ var staff = module.exports = { staff.media.show ); + + // + // plans + app.get('/staff/plans/', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + staff.middleware.ensurePlans, + + staff.plans.index + ); + app.get('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.new + ); + app.post('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.create + ); + app.get('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.edit + ); + app.post('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.update + ); }, paginate: function(req, res){ @@ -557,11 +618,18 @@ var staff = module.exports = { res.render('staff/plans/index') }, new: function(req, res){ + res.locals.plan = new Plan () res.render('staff/plans/new') }, edit: function(req, res){ res.render('staff/plans/edit') }, + create: function(req, res){ + res.redirect("/staff/plans/") + }, + update: function(req, res){ + res.redirect("/staff/plans/") + }, } } -- cgit v1.2.3-70-g09d2 From 664099f91ae3ed2d667d331b19c2e41dec60124c Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 06:43:31 -0500 Subject: fix up plans form --- public/assets/stylesheets/app.css | 6 +- public/assets/stylesheets/staff.css | 16 ++++ server/lib/views/staff.js | 70 ++++++++++++---- server/repl.js | 2 + views/staff/_nav.ejs | 1 + views/staff/index.ejs | 6 +- views/staff/plans/_form.ejs | 160 ++++++++++++++++++++++-------------- views/staff/plans/edit.ejs | 2 +- views/staff/plans/index.ejs | 11 ++- views/staff/plans/new.ejs | 4 +- 10 files changed, 186 insertions(+), 92 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 0463e26..9e86ac3 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -2478,7 +2478,7 @@ form li { form label { float:left; } -form input[type="text"],form input[type="password"] { +form input[type="text"],form input[type="password"],form input[type="number"] { border: 1px solid; font-size: 20px; padding: 5px; @@ -3048,8 +3048,8 @@ a[data-role="forgot-password"] { form li { font-size: 16px; } - form input[type="text"], form input[type="password"] { - font-size: 15px; + form input[type="text"],form input[type="password"],form input[type="number"] { + font-size: 15px; } .page h1 { font-size: 26px; diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index de31571..e5cafa2 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -71,6 +71,22 @@ hr { color: #00f; border-bottom: 1px solid; } +.staff form { + max-width: none; + width: 600px; + padding: 20px; +} +.staff form label { + float: none; +} +.staff form p { + width: 350px; + margin: 5px 0; + color: #444; +} +.staff form div li { + width: 180px; +} #iframe-embed, #iframe-embed tr, #iframe-embed td { width: 79vw; } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index ce676ed..6639137 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -18,6 +18,10 @@ var staff = module.exports = { fields: { user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", project: "_id name slug user_id privacy created_at updated_at", + plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", + plans_permissions: "basic_editor pro_editor solids collaborators no_logo", }, defaults: { @@ -122,8 +126,8 @@ var staff = module.exports = { }, ensurePlans: function(req, res, next){ - Plan.exec(function (err, plans) { - res.locals.plans = plans.map(staff.helpers.plan) + Plan.find(function (err, plans) { + res.locals.plans = (plans || []).map(staff.helpers.plan) next() }) }, @@ -132,17 +136,16 @@ var staff = module.exports = { Plan.findOne({ slug: req.params.slug }, function(err, plan){ if (err || ! plan) { console.error(err) - req.plan = null + res.redirect("/staff/plans/") } else { req.plan = plan + next() } - next() }) } else { - req.plan = null - next() + res.redirect("/staff/plans/") } }, @@ -326,7 +329,14 @@ var staff = module.exports = { media.user = {} media.shortUrl = media.url.replace(/^http.:\/\//,"") return media - } + }, + + plan: function(plan){ + plan = plan.toObject() + plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") + plan.user = {} + return plan + }, }, route: function(app){ @@ -452,7 +462,8 @@ var staff = module.exports = { // // plans - app.get('/staff/plans/', + + app.get('/staff/plans', middleware.ensureAuthenticated, middleware.ensureIsStaff, @@ -484,6 +495,8 @@ var staff = module.exports = { middleware.ensureAuthenticated, middleware.ensureIsStaff, + staff.middleware.ensurePlan, + staff.plans.update ); }, @@ -607,14 +620,8 @@ var staff = module.exports = { plans: { index: function(req, res){ - res.locals.fields = ( - "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + - "pro_layout_monthly_price pro_layout_yearly_price " + - "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit" - ).split(" ") - - res.locals.permissions = "basic_editor pro_editor solids collaborators no_logo".split(" ") - + res.locals.fields = staff.fields.plans.split(" ") + res.locals.permissions = staff.fields.plans_permissions.split(" ") res.render('staff/plans/index') }, new: function(req, res){ @@ -625,10 +632,37 @@ var staff = module.exports = { res.render('staff/plans/edit') }, create: function(req, res){ - res.redirect("/staff/plans/") + var plan = new Plan () + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + permissions.forEach(function(field){ + data[field] = data["permissions_" + field] + }) + + new Plan (data).save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + res.redirect("/staff/plans/") + }) }, update: function(req, res){ - res.redirect("/staff/plans/") + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + _.extend(req.plan, data) + permissions.forEach(function(field){ + req.plan[field] = data["permissions_" + field] + }) + + req.plan.save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + res.redirect("/staff/plans/") + }) }, } diff --git a/server/repl.js b/server/repl.js index ba94d45..353d8c5 100644 --- a/server/repl.js +++ b/server/repl.js @@ -9,6 +9,8 @@ mongoose.connect('mongodb://' + DB_HOST + '/vvalls', {}, function(){ "./lib/schemas/Layout", "./lib/schemas/Media", "./lib/schemas/Project", + "./lib/schemas/Plan", + "./lib/schemas/Subscription", ].forEach(function(modName){ // console.log(name, modName) var namez = modName.split("/"), name = namez[namez.length-1]; diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs index 2115e9f..db7bedb 100644 --- a/views/staff/_nav.ejs +++ b/views/staff/_nav.ejs @@ -3,4 +3,5 @@ users projects media + plans \ No newline at end of file diff --git a/views/staff/index.ejs b/views/staff/index.ejs index 5ca7269..1b73641 100644 --- a/views/staff/index.ejs +++ b/views/staff/index.ejs @@ -2,11 +2,7 @@

Staff Area

- + [[ include _nav ]]
diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index b97716f..fc86516 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -1,109 +1,149 @@ + -
+
    + +
  • +

    New Plan

    +
  • + +
  • - -
+
+ -
+
  • - -
  • +
    + -
    +
  • +

    Plan Pricing

    +
  • + +
  • - -
  • +
    + -
    +
  • - -
  • +
    + + +

    + Note: Pricing should be in cents, i.e. a price of $10.00 should be entered as 1000. +

    -
    - - -
    +
  • +

    Additional Template Pricing

    +
  • -
    - - -
    +
  • + +
    +
  • -
    - - -
    +
  • + +
    +
  • -
    - - -
    +
  • + +
    +
  • + +
  • + +
    +
  • -
    - - -
    +
  • +

    Per-Plan Template Limits

    +
  • -
    - - -
    +
  • + +
    +
  • + +
  • + +
    +
  • -
    +
  • +

    Per-Plan Project Limits

    +
  • + +
  • - -
  • +
    + -
    +
  • - -
  • +
    + -
    +
  • - -
  • +
    + +
  • +

    Permissions

    +
  • +
    - +
  • -
  • + + -
    - +
  • -
  • + + -
    - +
  • -
  • + + -
    - +
  • -
  • + + -
    - +
  • -
  • + + + +

    + These permissions should harmonize with the restrictions on layouts set above. +

    + - +
  • + +
  • + diff --git a/views/staff/plans/edit.ejs b/views/staff/plans/edit.ejs index 503c97d..9848873 100644 --- a/views/staff/plans/edit.ejs +++ b/views/staff/plans/edit.ejs @@ -7,7 +7,7 @@
    -[[- include form ]] +[[- include _form ]] [[ include ../_footer ]] diff --git a/views/staff/plans/index.ejs b/views/staff/plans/index.ejs index aa6c35a..121a2fc 100644 --- a/views/staff/plans/index.ejs +++ b/views/staff/plans/index.ejs @@ -6,6 +6,7 @@
    +[[ if (plans.length) { ]]
    @@ -30,7 +31,11 @@ [[ plans.forEach(function(plan){ ]] [[ }) ]] @@ -46,8 +51,10 @@ [[ }) ]] [[ }) ]] -
    [[- field.replace(/_/," ") ]] - [[- plan[field] ]] + [[ if (field.indexOf("_price") != -1) { ]] + [[- plan[field] == 0 ? "" : "$" + (plan[field]/100).toFixed(2) ]] + [[ } else { ]] + [[- plan[field] ]] + [[ } ]]
    +
    +[[ } ]] + New Plan
    diff --git a/views/staff/plans/new.ejs b/views/staff/plans/new.ejs index d56a1c3..297d3d6 100644 --- a/views/staff/plans/new.ejs +++ b/views/staff/plans/new.ejs @@ -7,9 +7,7 @@
    -[[- include form ]] +[[- include _form ]]
    [[ include ../_footer ]] - - -- cgit v1.2.3-70-g09d2 From b386c3b88034e4e372f147ffd368c2de1d23a865 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 07:28:43 -0500 Subject: saving plans --- public/assets/stylesheets/staff.css | 2 +- server/lib/views/staff.js | 6 +++++- views/staff/plans/_form.ejs | 10 +++++----- views/staff/plans/index.ejs | 34 +++++++++++++++++++--------------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index e5cafa2..fffadbf 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -67,7 +67,7 @@ hr { .staff .body a { border-bottom: 1px dotted; } -.staff .editLinks a { +.staff .editLinks a, .staff a.bluelink { color: #00f; border-bottom: 1px solid; } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 6639137..2fdc2c3 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -629,6 +629,7 @@ var staff = module.exports = { res.render('staff/plans/new') }, edit: function(req, res){ + res.locals.plan = req.plan res.render('staff/plans/edit') }, create: function(req, res){ @@ -650,13 +651,16 @@ var staff = module.exports = { }) }, update: function(req, res){ + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + var data = util.cleanQuery(req.body) data.name = util.sanitize(data.name) data.slug = util.sanitize(data.slug.toLowerCase()) _.extend(req.plan, data) permissions.forEach(function(field){ - req.plan[field] = data["permissions_" + field] + req.plan.permissions[field] = data["permissions_" + field].length == 2 }) req.plan.save(function(err, doc){ diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index fc86516..ae5ca5a 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -107,31 +107,31 @@
  • - +
  • - +
  • - +
  • - +
  • - +
  • diff --git a/views/staff/plans/index.ejs b/views/staff/plans/index.ejs index 121a2fc..16fcf14 100644 --- a/views/staff/plans/index.ejs +++ b/views/staff/plans/index.ejs @@ -6,31 +6,33 @@
    -[[ if (plans.length) { ]] - - [[ plans.forEach(function(plan){ ]] + [[ plans.forEach(function(plan){ ]] + [[ }) ]] - - - [[ plans.forEach(function(plan){ ]] + + [[ plans.forEach(function(plan){ ]] + [[ }) ]] [[ fields.forEach(function(field){ ]] - + [[ plans.forEach(function(plan){ ]] - [[ }) ]] + + + + [[ permissions.forEach(function(permission){ ]] - + [[ plans.forEach(function(plan){ ]] - [[ }) ]] [[ }) ]]
    - [[- plan.name ]] + + [[- plan.name ]]
    [[- field.replace(/_/," ") ]][[- field.replace(/_/g," ") ]] + [[ if (field.indexOf("_price") != -1) { ]] [[- plan[field] == 0 ? "" : "$" + (plan[field]/100).toFixed(2) ]] [[ } else { ]] @@ -41,20 +43,22 @@
    [[- permission.replace(/_/," ") ]][[- permission.replace(/_/g," ") ]] - [[- plan.permissions[permission] ? "x" : " " ]] + + [[- plan.permissions[permission] ? "x" : " " ]]

    -[[ } ]] - New Plan
    -- cgit v1.2.3-70-g09d2 From 372b8eb7f2a34902c72f5a831404070b5bd761c1 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 07:53:23 -0500 Subject: edit brochure --- server/lib/views/index.js | 20 ++++++++++++++++++-- views/about/brochure.ejs | 12 ++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 5f9088b..2a8f921 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -4,6 +4,7 @@ var User = require('../schemas/User'), Project = require('../schemas/Project'), Documentation = require('../schemas/Documentation'), Collaborator = require('../schemas/Collaborator'), + Plan = require('../schemas/Plan'), config = require('../../../config'), marked = require('marked'), util = require('../util'), @@ -111,9 +112,11 @@ var views = module.exports = { res.render('about/' + name) return } - if (name == "brochure") { + if (name == "brochure" || name == "plans") { // TODO: fetch plans - res.render('about/' + name) + views_middleware.ensurePlans(req, res, function(){ + res.render('about/' + name) + }) return } if (name == "about" || name == "index") { @@ -224,6 +227,19 @@ var views = module.exports = { } var views_middleware = { + ensurePlans: function(req, res, next){ + Plan.find(function (err, plans) { + res.locals.plans = {} + plans.forEach(function(plan){ + res.locals.plans[ plan.slug ] = plan + "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price pro_layout_monthly_price pro_layout_yearly_price".split(" ").forEach(function(key){ + plan[key] = (plan[key]/100).toFixed(2)+"" + }) + }) + next() + }) + }, + fetchProjects: function (criteria, limit, offset, next) { limit = limit || 7 offset = offset || 0 diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index d816dc4..4ce558a 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -19,7 +19,7 @@

    [[- plans.free.name ]]

      -
    • One exhibition with pre-designed template floor plan +
    • [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan
    @@ -27,10 +27,10 @@

    [[- plans.premium.name ]]

    • $[[- plans.premium.monthly_price ]]/mo or $[[- plans.premium.yearly_price ]]/year -
    • [[- plans.premium.stock_layout_project_limit ]] exhibitions included with pre-designed template floor plans +
    • [[- plans.premium.stock_project_limit ]] exhibitions included with pre-designed template floor plans
    • Each new basic floor plan costs $[[- plans.premium.basic_layout_monthly_price ]]/mo or $[[- plans.premium.basic_layout_yearly_price ]]/year, minimum 3 months -
    • Each new basic floor plan can have up to [[- plans.premium.basic_layout_project_limit ]] exhibitions +
    • Each new basic floor plan can have up to [[- plans.premium.basic_project_limit ]] exhibitions
    • VValls logo appears when embedding an exhibition on a web page
    @@ -39,10 +39,10 @@

    [[- plans.pro.name ]]

    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year -
    • Comes with [[- plans.premium.pro_layout_limit ]] pro floor plan and [[- plans.premium.pro_layout_project_limit ]] exhibitions +
    • Comes with [[- plans.premium.pro_layout_limit ]] pro floor plan and [[- plans.premium.pro_project_limit ]] exhibitions
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months -
    • Each new pro floor plan can have up to [[- plans.pro.pro_layout_project_limit ]] exhibitions +
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions
    • Includes planning for 3D objects in the room
    • No VValls logo on embed
    @@ -57,7 +57,7 @@
    - Pro Floor plan: Trace an arbitrary floor plan. + Pro Floor plan: Trace an arbitrary floor plan from image.
    -- cgit v1.2.3-70-g09d2 From 63d8dd85a47c20d3c9bad963d7845d4d5b1c2e2e Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 08:23:35 -0500 Subject: very light styling on brochure page --- server/lib/views/staff.js | 1 + views/about/brochure.ejs | 122 +++++++++++++++++++++++++++++----------------- 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 2fdc2c3..97ecde6 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -128,6 +128,7 @@ var staff = module.exports = { ensurePlans: function(req, res, next){ Plan.find(function (err, plans) { res.locals.plans = (plans || []).map(staff.helpers.plan) + res.locals.plans.sort(function(a,b){ return a.monthly_price }) next() }) }, diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index 4ce558a..75e7b60 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -13,58 +13,54 @@
    Want to get more out of VValls? Consider becoming a subscription user. +

    -
    -
    -

    [[- plans.free.name ]]

    -
      -
    • [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan -
    -
    +
    +

    [[- plans.free.name ]]

    +
      +
    • [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan +
    +
    -
    -

    [[- plans.premium.name ]]

    -
      -
    • $[[- plans.premium.monthly_price ]]/mo or $[[- plans.premium.yearly_price ]]/year -
    • [[- plans.premium.stock_project_limit ]] exhibitions included with pre-designed template floor plans -
    • Each new basic floor plan costs $[[- plans.premium.basic_layout_monthly_price ]]/mo - or $[[- plans.premium.basic_layout_yearly_price ]]/year, minimum 3 months -
    • Each new basic floor plan can have up to [[- plans.premium.basic_project_limit ]] exhibitions -
    • VValls logo appears when embedding an exhibition on a web page -
    -
    +
    +

    [[- plans.basic.name ]]

    +
      +
    • $[[- plans.basic.monthly_price ]]/mo or $[[- plans.basic.yearly_price ]]/year +
    • [[- plans.basic.stock_project_limit ]] exhibitions included with pre-designed template floor plans +
    • Each new basic floor plan costs $[[- plans.basic.basic_layout_monthly_price ]]/mo + or $[[- plans.basic.basic_layout_yearly_price ]]/year, minimum 3 months +
    • Each new basic floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions +
    • VValls logo appears when embedding an exhibition on a web page +
    +
    -
    -

    [[- plans.pro.name ]]

    -
      -
    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year -
    • Comes with [[- plans.premium.pro_layout_limit ]] pro floor plan and [[- plans.premium.pro_project_limit ]] exhibitions -
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo - or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months -
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions -
    • Includes planning for 3D objects in the room -
    • No VValls logo on embed -
    -
    +
    +

    [[- plans.pro.name ]]

    +
      +
    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year +
    • Comes with [[- plans.pro.pro_layout_limit ]] pro floor plan and [[- plans.pro.pro_project_limit ]] exhibitions +
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo + or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months +
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions +
    • Includes planning for 3D objects in the room +
    • No VValls logo on embed +
    +
    -
    - Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you. -
    - -
    - Basic Floor plan: Rectangle-based design of any dimension. -
    - -
    - Pro Floor plan: Trace an arbitrary floor plan from image. -
    - +
    +
      +
    • Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you. +
    • Basic Floor plan: Rectangle-based design of any dimension. +
    • Pro Floor plan: Trace an arbitrary floor plan from image. +
    +
    -
    -

    Custom

    - We offer many types of customizations and white-label options for business and educational uses. - Contact us for more information +
    +

    Custom

    +
  • We offer customized white-label options for business and educational uses. +
  • Contact us for more information. +
  • @@ -77,3 +73,37 @@ [[ include ../partials/scripts ]] + \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c5ab88deba82c4b4a149b3df594162351157483a Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 9 Jan 2015 10:51:24 -0500 Subject: buy buttons --- public/assets/stylesheets/app.css | 4 +++- views/about/_blank.ejs | 2 +- views/about/about.ejs | 2 +- views/about/brochure.ejs | 45 +++++++++++++++++++++++++++------------ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 9e86ac3..a149166 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -604,7 +604,9 @@ iframe.embed { .page h1:nth-child(2) { margin-top: 40px; } - +.page h1.leader { + margin-top: 60px; +} .page p { margin: 20px; } diff --git a/views/about/_blank.ejs b/views/about/_blank.ejs index 3c23fa7..732ea3f 100644 --- a/views/about/_blank.ejs +++ b/views/about/_blank.ejs @@ -8,7 +8,7 @@
    [[ include ../partials/header ]] - +

    Hallo

    diff --git a/views/about/about.ejs b/views/about/about.ejs index 2aec982..6d5f011 100644 --- a/views/about/about.ejs +++ b/views/about/about.ejs @@ -8,7 +8,7 @@
    [[ include ../partials/header ]] -

    About VValls

    +

    About VValls

    diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index 75e7b60..e75f8c6 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -8,7 +8,7 @@
    [[ include ../partials/header ]] -

    Subscriptions

    +

    Subscriptions

    @@ -27,11 +27,14 @@

    [[- plans.basic.name ]]

    • $[[- plans.basic.monthly_price ]]/mo or $[[- plans.basic.yearly_price ]]/year -
    • [[- plans.basic.stock_project_limit ]] exhibitions included with pre-designed template floor plans +
    • Comes with [[- plans.basic.basic_layout_limit ]] basic floor plan and [[- plans.basic.basic_project_limit ]] exhibitions
    • Each new basic floor plan costs $[[- plans.basic.basic_layout_monthly_price ]]/mo or $[[- plans.basic.basic_layout_yearly_price ]]/year, minimum 3 months -
    • Each new basic floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions +
    • Each new floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions
    • VValls logo appears when embedding an exhibition on a web page +
    • + +
    @@ -45,10 +48,13 @@
  • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions
  • Includes planning for 3D objects in the room
  • No VValls logo on embed +
  • + +
  • -
    +
    • Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you.
    • Basic Floor plan: Rectangle-based design of any dimension. @@ -56,10 +62,10 @@
    -
    -

    Custom

    +
    +

    Want Something Custom?

  • We offer customized white-label options for business and educational uses. -
  • Contact us for more information. +
  • Contact us for more information.
  • @@ -74,13 +80,23 @@ [[ include ../partials/scripts ]] \ No newline at end of file -- cgit v1.2.3-70-g09d2 From afce400c65f362f7dd6307a5670dc3873d74ab79 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Sun, 11 Jan 2015 21:42:45 -0500 Subject: stub in subscriptions admin pages --- server/lib/views/staff.js | 34 +++++++++++++++++++++++++++++++++- views/staff/_nav.ejs | 1 + views/staff/subscriptions/index.ejs | 36 ++++++++++++++++++++++++++++++++++++ views/staff/subscriptions/show.ejs | 12 ++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 views/staff/subscriptions/index.ejs create mode 100644 views/staff/subscriptions/show.ejs diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 97ecde6..4351ef0 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -500,6 +500,27 @@ var staff = module.exports = { staff.plans.update ); + + // + // subscriptions + app.get('/staff/subscriptions', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscriptions, + staff.middleware.ensureSubscriptionsUsers, + + staff.subscriptions.index + ); + app.get('/staff/subscriptions/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscription, + staff.middleware.ensureSubscriptionUser, + + staff.subscriptions.edit + ); }, paginate: function(req, res){ @@ -669,6 +690,17 @@ var staff = module.exports = { res.redirect("/staff/plans/") }) }, - } + }, + + subscriptions: { + index: function(req, res){ + res.locals.subscriptions = req.subscriptions + res.render('staff/plans/index') + }, + show: function(req, res){ + res.locals.subscription = req.subscription + res.render('staff/plans/show') + }, + }, } diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs index db7bedb..e79ff69 100644 --- a/views/staff/_nav.ejs +++ b/views/staff/_nav.ejs @@ -4,4 +4,5 @@ projects media plans + subscriptions \ No newline at end of file diff --git a/views/staff/subscriptions/index.ejs b/views/staff/subscriptions/index.ejs new file mode 100644 index 0000000..d1c0588 --- /dev/null +++ b/views/staff/subscriptions/index.ejs @@ -0,0 +1,36 @@ +[[ include ../_header ]] + +

    Users

    + +[[ include ../_nav ]] + +
    + +[[ include ../_pagination ]] + + +[[ subscriptions.forEach(function(subscription){ ]] + + + + + + + +[[ }) ]] +
    +
    +
    + [[- subscription.user.username ]] + + [[- subscription.user.displayName ]] + + [[- subscription.user.last_seen ]] +
    + + +[[ include ../_pagination ]] + +[[ include ../_footer ]] diff --git a/views/staff/subscriptions/show.ejs b/views/staff/subscriptions/show.ejs new file mode 100644 index 0000000..e2839a6 --- /dev/null +++ b/views/staff/subscriptions/show.ejs @@ -0,0 +1,12 @@ +[[ include ../_header ]] +

    User: [[- subscription.user.username ]]

    + +[[ include ../_nav ]] + +
    + +
    +info to show..
    +- link to recurly profile
    +- link to vvalls profile
    +- subscription tier + add-ons
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From a1c9bdecff30d72eeaef54c66c7211966a97d4e4 Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Sun, 11 Jan 2015 21:57:17 -0500
    Subject: crud
    
    ---
     server/lib/views/staff.js | 69 ++++++++++++++++++++++++++++++++++++++++++++---
     1 file changed, 66 insertions(+), 3 deletions(-)
    
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 4351ef0..39a8dca 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -124,7 +124,35 @@ var staff = module.exports = {
             next()
           })
         },
    -    
    +
    +    ensureSubscriptions: function(req, res, next){
    +      var paginationInfo = res.locals.pagination = {}
    +      var criteria = req.criteria || {}
    +      var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 )
    +      var offset = paginationInfo.offset = Number(req.query.offset) || 0
    +      var sort
    +      paginationInfo.sort = req.query.sort
    +      paginationInfo.sortOptions = ["date", "name"]
    +      switch (req.query.sort) {
    +        case 'created':
    +          sort = {'created_at': -1}
    +          break
    +        default:
    +        case 'date':
    +          sort = {'updated_at': -1}
    +          break
    +      }
    +      Subscription.find(criteria)
    +          .select(staff.fields.project)
    +          .sort(sort)
    +          .skip(offset)
    +          .limit(limit)
    +          .exec(function (err, subscriptions) {
    +        res.locals.subscriptions = subscriptions.map(staff.helpers.subscription)
    +        next()
    +      })
    +    },
    +
         ensurePlans: function(req, res, next){
           Plan.find(function (err, plans) {
             res.locals.plans = (plans || []).map(staff.helpers.plan)
    @@ -150,6 +178,24 @@ var staff = module.exports = {
           }
         },
     
    +    ensureSubscription: function (req, res, next) {
    +      if (req.params.id) {
    +        Subscription.findOne({ _id: req.params.id }, function(err, subscription){
    +          if (err || ! subscription) {
    +            console.error(err)
    +            res.redirect("/staff/subscriptions/")
    +          }
    +          else {
    +            req.subscription = subscription
    +            next()
    +          }
    +        })
    +      }
    +      else {
    +        res.redirect("/staff/subscriptions/")
    +      }
    +    },
    +
         ensureRecentProjects: function(req, res, next){
           var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } }
           staff.middleware.ensureProjects(dreq, res, next)
    @@ -160,11 +206,23 @@ var staff = module.exports = {
           staff.middleware.ensureObjectsUsers(res.locals.projects, next)
         },
     
    +    ensureSubscriptionsUsers: function(req, res, next){
    +      if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() }
    +      staff.middleware.ensureObjectsUsers(res.locals.subscriptions, next)
    +    },
    +
         ensureMediaUsers: function(req, res, next){
           if (! res.locals.media || ! res.locals.media.length) { return next() }
           staff.middleware.ensureObjectsUsers(res.locals.media, next)
         },
     
    +    ensureSubscriptionUser: function(req, res, next){
    +      if (! res.locals.subscription) { return next() }
    +      staff.middleware.ensureObjectsUsers([ res.locals.subscription ], function(){
    +        next()
    +      })
    +    },
    +
         ensureMediaUser: function(req, res, next){
           if (! res.locals.media) { return next() }
           staff.middleware.ensureObjectsUsers([ res.locals.media ], function(){
    @@ -338,6 +396,13 @@ var staff = module.exports = {
           plan.user = {}
           return plan
     	  },
    +
    +	  subscription: function(subscription){
    +      subscription = subscription.toObject()
    +      subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a")
    +      subscription.user = {}
    +      return subscription
    +	  },
     	},
     
     	route: function(app){
    @@ -694,11 +759,9 @@ var staff = module.exports = {
       
       subscriptions: {
         index: function(req, res){
    -      res.locals.subscriptions = req.subscriptions
           res.render('staff/plans/index')
         },
         show: function(req, res){
    -      res.locals.subscription = req.subscription
           res.render('staff/plans/show')
         },
       },
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From ffdee0615c775466053daff3ce4afd1d11c83e33 Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Sun, 11 Jan 2015 22:37:07 -0500
    Subject: pagination
    
    ---
     server/lib/views/staff.js | 7 +++++--
     1 file changed, 5 insertions(+), 2 deletions(-)
    
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 39a8dca..64cfe77 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -759,10 +759,13 @@ var staff = module.exports = {
       
       subscriptions: {
         index: function(req, res){
    -      res.render('staff/plans/index')
    +      res.locals.pagination.count = res.locals.subscriptions.length
    +      res.locals.pagination.max = res.locals.subscriptionCount
    +      staff.paginate(req, res)
    +      res.render('staff/subscriptions/index')
         },
         show: function(req, res){
    -      res.render('staff/plans/show')
    +      res.render('staff/subscriptions/show')
         },
       },
     
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 77c4c8d066611ad651af8df7290fb3e54d074081 Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Sun, 11 Jan 2015 23:37:49 -0500
    Subject: fix
    
    ---
     server/lib/views/staff.js | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index 64cfe77..d4abf1f 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -584,7 +584,7 @@ var staff = module.exports = {
           staff.middleware.ensureSubscription,
           staff.middleware.ensureSubscriptionUser,
     
    -      staff.subscriptions.edit
    +      staff.subscriptions.show
         );
       },
       
    @@ -765,7 +765,7 @@ var staff = module.exports = {
           res.render('staff/subscriptions/index')
         },
         show: function(req, res){
    -      res.render('staff/subscriptions/show')
    +      res.render('staff/subscriptions /show')
         },
       },
     
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From dcfbf734436fad76f5ca2e1cecadf4051118d56f Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Mon, 12 Jan 2015 12:24:57 -0500
    Subject: stubbing webhook
    
    ---
     server/index.js                  |  2 ++
     server/lib/views/staff.js        |  2 +-
     server/lib/views/subscription.js | 21 ++++++---------------
     3 files changed, 9 insertions(+), 16 deletions(-)
    
    diff --git a/server/index.js b/server/index.js
    index 9a9323c..a14eaab 100644
    --- a/server/index.js
    +++ b/server/index.js
    @@ -70,6 +70,8 @@ site.setup = function(){
     	app.all('*', middleware.ensureLocals);
     	app.all('*', middleware.ensureIP);
     
    +  app.get('/subscribe/webhook', views.subscription.webhook);
    +
     	server = http.createServer(app)
     	server.listen(app.get('port'), function () {
     		console.log('Express server listening on port ' + app.get('port'));
    diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js
    index d4abf1f..74dd7cd 100644
    --- a/server/lib/views/staff.js
    +++ b/server/lib/views/staff.js
    @@ -765,7 +765,7 @@ var staff = module.exports = {
           res.render('staff/subscriptions/index')
         },
         show: function(req, res){
    -      res.render('staff/subscriptions /show')
    +      res.render('staff/subscriptions/show')
         },
       },
     
    diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js
    index ba54bb4..e29e40d 100644
    --- a/server/lib/views/subscription.js
    +++ b/server/lib/views/subscription.js
    @@ -32,19 +32,10 @@ var subscription = module.exports = {
           return project
     	  },
     	},
    -
    -	route: function(app){
    -    app.get('/staff',
    -      middleware.ensureAuthenticated,
    -      middleware.ensureIsStaff,
    -      
    -      staff.middleware.ensureRecentUsers,
    -      staff.middleware.ensureUsersCount,
    -      staff.middleware.ensureProjectsCount,
    -      staff.middleware.ensureMediaCount,
    -
    -      staff.index
    -    );
    -  },
    -
    +	
    +  // need a route for the webhook,
    +  // then calls to get appropriate info from the recurly api
    +	webhook: function(req, res){
    +    res.status(200).end()
    +	},
     }
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 5229023137d5d929db5ef7dcc8fd27d59676a99f Mon Sep 17 00:00:00 2001
    From: Jules Laplace 
    Date: Mon, 12 Jan 2015 14:14:29 -0500
    Subject: bump year
    
    ---
     Gruntfile.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Gruntfile.js b/Gruntfile.js
    index 21bbfb0..f62cc82 100644
    --- a/Gruntfile.js
    +++ b/Gruntfile.js
    @@ -140,7 +140,7 @@ module.exports = function(grunt) {
     		},
     		uglify: {
     			options: {
    -				banner: '/* vvalls by okfocus 2014 */\n'
    +				banner: '/* vvalls by okfocus 2015 */\n'
     			},
     			js: {
     				src: 'public/assets/javascripts/app.concat.js',
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 034f8343f2d194c2b1e3dbb20cfb8658e2795ce0 Mon Sep 17 00:00:00 2001
    From: Jules Laplace 
    Date: Mon, 12 Jan 2015 18:38:42 -0500
    Subject: parsing some xml for webhooks
    
    ---
     package.json                     | 37 +++++++++---------
     server/index.js                  |  1 +
     server/lib/views/subscription.js | 81 +++++++++++++++++++++++++++++++++++-----
     3 files changed, 92 insertions(+), 27 deletions(-)
    
    diff --git a/package.json b/package.json
    index adefb82..34e0c4c 100644
    --- a/package.json
    +++ b/package.json
    @@ -6,32 +6,33 @@
         "url": "git://github.com/okfocus/vvalls.git"
       },
       "dependencies": {
    -    "express": "~3.4.8",
    -    "monk": "~0.7.1",
    -    "socket.io": "~0.9.16",
    +    "body-parser": "1.3.0",
         "connect-mongo": "~0.4.1",
    -    "passport": "~0.2.0",
    -    "passport-local": "~1.0.0",
    -    "passport-twitter": "~1.0.2",
    -    "passport-facebook": "~1.0.3",
    -    "passport.socketio": "~3.0.1",
    -    "node-restful": "~0.1.14",
         "ejs": "^0.8.8",
    -    "useful-string": "0.0.1",
    +    "emailjs": "~0.3.6",
    +    "express": "~3.4.8",
         "express-subdomain-handler": "~0.1.0",
         "express-subdomains": "0.0.5",
    +    "html-entities": "~1.0.10",
    +    "intro.js": "^0.9.0",
    +    "knox": "~0.8.10",
         "lodash": "~2.4.1",
    +    "marked": "~0.3.2",
    +    "moment": "~2.6.0",
         "mongoose": "~3.8.8",
    -    "mongoose-unique-validator": "~0.3.0",
         "mongoose-lifecycle": "~1.0.0",
    -    "knox": "~0.8.10",
    -    "moment": "~2.6.0",
    -    "html-entities": "~1.0.10",
    +    "mongoose-unique-validator": "~0.3.0",
    +    "monk": "~0.7.1",
         "multer": "~0.1.0",
    -    "body-parser": "1.3.0",
    -    "marked": "~0.3.2",
    -    "emailjs": "~0.3.6",
    -    "intro.js": "^0.9.0"
    +    "node-restful": "~0.1.14",
    +    "passport": "~0.2.0",
    +    "passport-facebook": "~1.0.3",
    +    "passport-local": "~1.0.0",
    +    "passport-twitter": "~1.0.2",
    +    "passport.socketio": "~3.0.1",
    +    "socket.io": "~0.9.16",
    +    "useful-string": "0.0.1",
    +    "xml2js": "^0.4.4"
       },
       "devDependencies": {
         "grunt": "~0.4.1",
    diff --git a/server/index.js b/server/index.js
    index a14eaab..0f4941a 100644
    --- a/server/index.js
    +++ b/server/index.js
    @@ -70,6 +70,7 @@ site.setup = function(){
     	app.all('*', middleware.ensureLocals);
     	app.all('*', middleware.ensureIP);
     
    +	// where should this live?
       app.get('/subscribe/webhook', views.subscription.webhook);
     
     	server = http.createServer(app)
    diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js
    index e29e40d..251e217 100644
    --- a/server/lib/views/subscription.js
    +++ b/server/lib/views/subscription.js
    @@ -6,7 +6,15 @@ var User = require('../schemas/User'),
     	middleware = require('../middleware'),
     	util = require('../util'),
     	_ = require('lodash'),
    -	moment = require('moment');
    +	moment = require('moment'),
    +	xml2js = require('xml2js');
    +
    +var parser = new xml2js.Parser();
    +// fs.readFile('./foo.xml', function(err, data) {
    +// 	parser.parseString(data, function (err, result) {
    +// 		console.log(inspect(result, { colors: true, depth: Infinity }));
    +// 	});
    +// });
     
     var subscription = module.exports = {
     	
    @@ -24,18 +32,73 @@ var subscription = module.exports = {
     	middleware: {
       },
     
    -	helpers: {
    -	  project: function(project){
    -      project = project.toObject()
    -      project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a")
    -      project.user = {}
    -      return project
    -	  },
    -	},
    +	fields: [
    +		"new_account_notification",
    +		"canceled_account_notification",
    +		"billing_info_updated_notification",
    +		"reactivated_account_notification",
    +		"new_invoice_notification",
    +		"closed_invoice_notification",
    +		"past_due_invoice_notification",
    +		"new_subscription_notification",
    +		"updated_subscription_notification",
    +		"canceled_subscription_notification",
    +		"expired_subscription_notification",
    +		"renewed_subscription_notification",
    +		"successful_payment_notification",
    +		"failed_payment_notification",
    +		"successful_refund_notification",
    +		"void_payment_notification",
    +	],  
    +
    +  callbacks: {
    +		// accounts
    +		new_account_notification: function(data){
    +		},
    +		canceled_account_notification: function(data){
    +		},
    +		billing_info_updated_notification: function(data){
    +		},
    +		reactivated_account_notification: function(data){
    +		},
    +		
    +		// invoices
    +		new_invoice_notification: function(data){
    +		},
    +		closed_invoice_notification: function(data){
    +		},
    +		past_due_invoice_notification: function(data){
    +		},
    +		
    +		// subscriptions
    +		new_subscription_notification: function(data){
    +		},
    +		updated_subscription_notification: function(data){
    +		},
    +		canceled_subscription_notification: function(data){
    +		},
    +		expired_subscription_notification: function(data){
    +		},
    +		renewed_subscription_notification: function(data){
    +		},
    +		
    +		// payments
    +		successful_payment_notification: function(data){
    +		},
    +		failed_payment_notification: function(data){
    +		},
    +		successful_refund_notification: function(data){
    +		},
    +		void_payment_notification: function(data){
    +		},
    +  },
     	
       // need a route for the webhook,
       // then calls to get appropriate info from the recurly api
     	webhook: function(req, res){
         res.status(200).end()
    +		parser.parseString(data, function (err, result) {
    +			console.log(inspect(result, { colors: true, depth: Infinity }));
    +		});
     	},
     }
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From ffa627b1032f9244df8c685c86fd24f3e7c2881a Mon Sep 17 00:00:00 2001
    From: Julie Lala 
    Date: Mon, 12 Jan 2015 23:35:57 -0500
    Subject: etc
    
    ---
     server/lib/views/subscription.js | 29 +++++++++++++++--------------
     1 file changed, 15 insertions(+), 14 deletions(-)
    
    diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js
    index 251e217..b9c79cb 100644
    --- a/server/lib/views/subscription.js
    +++ b/server/lib/views/subscription.js
    @@ -18,39 +18,35 @@ var parser = new xml2js.Parser();
     
     var subscription = module.exports = {
     	
    -	fields: {
    -	  user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip",
    -	},
    -	
    -	defaults: {
    -	  user: {
    -	    _id: "", username: "", displayName: "",
    -      created_at: "", updated_at: "", created_ip: "", last_ip: "",
    -	  },
    -	},
    -
    -	middleware: {
    -  },
    -
     	fields: [
    +	  // accounts
     		"new_account_notification",
     		"canceled_account_notification",
     		"billing_info_updated_notification",
     		"reactivated_account_notification",
    +
    +		// invoices
     		"new_invoice_notification",
     		"closed_invoice_notification",
     		"past_due_invoice_notification",
    +		
    +		// subscriptions
     		"new_subscription_notification",
     		"updated_subscription_notification",
     		"canceled_subscription_notification",
     		"expired_subscription_notification",
     		"renewed_subscription_notification",
    +		
    +		// payments
     		"successful_payment_notification",
     		"failed_payment_notification",
     		"successful_refund_notification",
     		"void_payment_notification",
     	],  
     
    +	middleware: {
    +  },
    +
       callbacks: {
     		// accounts
     		new_account_notification: function(data){
    @@ -99,6 +95,11 @@ var subscription = module.exports = {
         res.status(200).end()
     		parser.parseString(data, function (err, result) {
     			console.log(inspect(result, { colors: true, depth: Infinity }));
    +			for (var i in data) {
    +			  if (subscription.callbacks[i]) {
    +			    subscription.callbacks[i](data)
    +			  }
    +			}
     		});
     	},
     }
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 904a18b763889c9f85d874388fdff9daaefb89cd Mon Sep 17 00:00:00 2001
    From: Jules Laplace 
    Date: Wed, 14 Jan 2015 15:44:34 -0500
    Subject: roll back devicePixelRatio fix on desktop
    
    ---
     public/assets/javascripts/app.js   |  4 +++-
     public/assets/javascripts/mx/mx.js | 14 +++++++-------
     public/assets/stylesheets/app.css  |  4 ++++
     3 files changed, 14 insertions(+), 8 deletions(-)
    
    diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js
    index 41edafe..a146325 100644
    --- a/public/assets/javascripts/app.js
    +++ b/public/assets/javascripts/app.js
    @@ -3,7 +3,7 @@ if (is_mobile) {
     	$("html").addClass("mobile")
     }
     else {
    - $("html").addClass("desktop")
    +  $("html").addClass("desktop")
     }
     
     
    @@ -23,6 +23,8 @@ app.launch = function () {
       
     	var movements
     
    +	app.devicePixelRatio = is_mobile ? devicePixelRatio : 1
    +
     	scene = new MX.Scene().addTo('#scene')
     	scene.width = window.innerWidth
     	scene.height = window.innerHeight
    diff --git a/public/assets/javascripts/mx/mx.js b/public/assets/javascripts/mx/mx.js
    index d59a551..ab9a9a0 100644
    --- a/public/assets/javascripts/mx/mx.js
    +++ b/public/assets/javascripts/mx/mx.js
    @@ -162,24 +162,24 @@ var MX = MX || (function (undefined) {
             Object.defineProperty(this, 'width', {
                 get: function () {
                     return width
    -                    || parseInt(self.el.style.width*devicePixelRatio, 10)
    +                    || parseInt(self.el.style.width, 10) * app.devicePixelRatio
                         || 0
                 },
                 set: function (val) {
                     width = val
    -                this.el.style.width = (width/devicePixelRatio) + 'px'
    +                this.el.style.width = (width/app.devicePixelRatio) + 'px'
                 }
             })
     
             Object.defineProperty(this, 'height', {
                 get: function () {
                     return height
    -                    || parseInt(self.el.style.height*devicePixelRatio, 10)
    +                    || parseInt(self.el.style.height, 10) * app.devicePixelRatio
                         || 0
                 },
                 set: function (val) {
                     height = val
    -                this.el.style.height = (height/devicePixelRatio) + 'px'
    +                this.el.style.height = (height/app.devicePixelRatio) + 'px'
                 }
             })
         }
    @@ -302,9 +302,9 @@ var MX = MX || (function (undefined) {
                             + (-this.y).toFixed(floatPrecision) + 'px,'
                             + (-this.z).toFixed(floatPrecision) + 'px) '
                         + 'scale3d('
    -                        + (devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ','
    -                        + (devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ','
    -                        + (devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') '
    +                        + (app.devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ','
    +                        + (app.devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ','
    +                        + (app.devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') '
     
                     if (rotationTranslation) {
                         transformString += rotationTranslation.before
    diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css
    index a149166..0ce2c5e 100755
    --- a/public/assets/stylesheets/app.css
    +++ b/public/assets/stylesheets/app.css
    @@ -929,6 +929,9 @@ border-left: 1px solid black;
     .no-templates {
     	display: none;
     }
    +.no-templates a {
    +	border-bottom: 1px solid;
    +}
     
     .templates span {
     	display: block;
    @@ -2373,6 +2376,7 @@ button {
       font-weight: 500;
       width: 100%;
     	font-size:14px;
    +	font-family:'Lato', sans-serif;
     }
     
     #builder-units {
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 717e87b7422db8e1eda655fbf04e45fe5f877c9b Mon Sep 17 00:00:00 2001
    From: Jules Laplace 
    Date: Tue, 20 Jan 2015 00:10:23 -0500
    Subject: combining webhook stuff
    
    ---
     package.json                       |   1 +
     server/index.js                    |   3 --
     server/lib/api/profile.js          |   1 +
     server/lib/schemas/Subscription.js |   1 +
     server/lib/schemas/User.js         |   4 +-
     server/lib/views/index.js          |   1 -
     server/lib/views/subscription.js   | 105 -------------------------------------
     server/lib/webhook/config.js       |   6 +++
     server/lib/webhook/index.js        |  88 +++++++++++++++++++++++++++++++
     9 files changed, 100 insertions(+), 110 deletions(-)
     delete mode 100644 server/lib/views/subscription.js
     create mode 100644 server/lib/webhook/config.js
     create mode 100644 server/lib/webhook/index.js
    
    diff --git a/package.json b/package.json
    index 34e0c4c..8afb96e 100644
    --- a/package.json
    +++ b/package.json
    @@ -24,6 +24,7 @@
         "mongoose-unique-validator": "~0.3.0",
         "monk": "~0.7.1",
         "multer": "~0.1.0",
    +    "node-recurly": "^2.1.0",
         "node-restful": "~0.1.14",
         "passport": "~0.2.0",
         "passport-facebook": "~1.0.3",
    diff --git a/server/index.js b/server/index.js
    index 0f4941a..9a9323c 100644
    --- a/server/index.js
    +++ b/server/index.js
    @@ -70,9 +70,6 @@ site.setup = function(){
     	app.all('*', middleware.ensureLocals);
     	app.all('*', middleware.ensureIP);
     
    -	// where should this live?
    -  app.get('/subscribe/webhook', views.subscription.webhook);
    -
     	server = http.createServer(app)
     	server.listen(app.get('port'), function () {
     		console.log('Express server listening on port ' + app.get('port'));
    diff --git a/server/lib/api/profile.js b/server/lib/api/profile.js
    index 996505f..d72a2c3 100644
    --- a/server/lib/api/profile.js
    +++ b/server/lib/api/profile.js
    @@ -32,6 +32,7 @@ var profile = {
     		delete data.old_password
     		delete data.new_password
     		delete data.isStaff
    +		delete data.plan_level
     		data.updated_at = new Date ()
     		
     		if (req.files.avatar) {
    diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js
    index 8315009..7f2579b 100644
    --- a/server/lib/schemas/Subscription.js
    +++ b/server/lib/schemas/Subscription.js
    @@ -15,6 +15,7 @@ var SubscriptionSchema = new mongoose.Schema({
     	plans: [{
         tier: { type: String },
         monthly: { type: Boolean },
    +    projects: [{ type: mongoose.Schema.ObjectId }],
     	}],
     	
     	created_at: { type: Date, default: Date.now },
    diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js
    index 180a140..ae1d912 100644
    --- a/server/lib/schemas/User.js
    +++ b/server/lib/schemas/User.js
    @@ -54,7 +54,9 @@ var UserSchema = new mongoose.Schema({
     		type: String,
     		default: "",
     	},
    -
    +	
    +	plan_level: { type: Number, default: 0 },
    +	
     	location: { type: String, default: "" },
     	photo: { type: String, default: "" },
     	bio: { type: String, default: "" },
    diff --git a/server/lib/views/index.js b/server/lib/views/index.js
    index 2a8f921..0ce0357 100644
    --- a/server/lib/views/index.js
    +++ b/server/lib/views/index.js
    @@ -22,7 +22,6 @@ marked.setOptions({
     var views = module.exports = {
     
     	staff: require('./staff'),
    -	subscription: require('./subscription'),
     
     	editor_new: function (req, res) {
     		if (! req.user) {
    diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js
    deleted file mode 100644
    index b9c79cb..0000000
    --- a/server/lib/views/subscription.js
    +++ /dev/null
    @@ -1,105 +0,0 @@
    -/* jshint node: true */
    -
    -var User = require('../schemas/User'),
    -	Subscription = require('../schemas/Subscription'),
    -	config = require('../../../config'),
    -	middleware = require('../middleware'),
    -	util = require('../util'),
    -	_ = require('lodash'),
    -	moment = require('moment'),
    -	xml2js = require('xml2js');
    -
    -var parser = new xml2js.Parser();
    -// fs.readFile('./foo.xml', function(err, data) {
    -// 	parser.parseString(data, function (err, result) {
    -// 		console.log(inspect(result, { colors: true, depth: Infinity }));
    -// 	});
    -// });
    -
    -var subscription = module.exports = {
    -	
    -	fields: [
    -	  // accounts
    -		"new_account_notification",
    -		"canceled_account_notification",
    -		"billing_info_updated_notification",
    -		"reactivated_account_notification",
    -
    -		// invoices
    -		"new_invoice_notification",
    -		"closed_invoice_notification",
    -		"past_due_invoice_notification",
    -		
    -		// subscriptions
    -		"new_subscription_notification",
    -		"updated_subscription_notification",
    -		"canceled_subscription_notification",
    -		"expired_subscription_notification",
    -		"renewed_subscription_notification",
    -		
    -		// payments
    -		"successful_payment_notification",
    -		"failed_payment_notification",
    -		"successful_refund_notification",
    -		"void_payment_notification",
    -	],  
    -
    -	middleware: {
    -  },
    -
    -  callbacks: {
    -		// accounts
    -		new_account_notification: function(data){
    -		},
    -		canceled_account_notification: function(data){
    -		},
    -		billing_info_updated_notification: function(data){
    -		},
    -		reactivated_account_notification: function(data){
    -		},
    -		
    -		// invoices
    -		new_invoice_notification: function(data){
    -		},
    -		closed_invoice_notification: function(data){
    -		},
    -		past_due_invoice_notification: function(data){
    -		},
    -		
    -		// subscriptions
    -		new_subscription_notification: function(data){
    -		},
    -		updated_subscription_notification: function(data){
    -		},
    -		canceled_subscription_notification: function(data){
    -		},
    -		expired_subscription_notification: function(data){
    -		},
    -		renewed_subscription_notification: function(data){
    -		},
    -		
    -		// payments
    -		successful_payment_notification: function(data){
    -		},
    -		failed_payment_notification: function(data){
    -		},
    -		successful_refund_notification: function(data){
    -		},
    -		void_payment_notification: function(data){
    -		},
    -  },
    -	
    -  // need a route for the webhook,
    -  // then calls to get appropriate info from the recurly api
    -	webhook: function(req, res){
    -    res.status(200).end()
    -		parser.parseString(data, function (err, result) {
    -			console.log(inspect(result, { colors: true, depth: Infinity }));
    -			for (var i in data) {
    -			  if (subscription.callbacks[i]) {
    -			    subscription.callbacks[i](data)
    -			  }
    -			}
    -		});
    -	},
    -}
    diff --git a/server/lib/webhook/config.js b/server/lib/webhook/config.js
    new file mode 100644
    index 0000000..ecafeb3
    --- /dev/null
    +++ b/server/lib/webhook/config.js
    @@ -0,0 +1,6 @@
    +module.exports = {
    +	API_KEY: require('process').env['VVALLS_RECURLY_SECRET'],
    +	SUBDOMAIN: 'vvalls',
    +	ENVIRONMENT: 'sandbox',
    +	DEBUG: true,
    +};
    diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js
    new file mode 100644
    index 0000000..c4b4b76
    --- /dev/null
    +++ b/server/lib/webhook/index.js
    @@ -0,0 +1,88 @@
    +// // where should this live?
    +// app.get('/subscribe/webhook', views.subscription.webhook);
    +
    +/* jshint node: true */
    +
    +var User = require('../schemas/User'),
    +	Subscription = require('../schemas/Subscription'),
    +	config = require('../../../config'),
    +	middleware = require('../middleware'),
    +	util = require('../util'),
    +	_ = require('lodash'),
    +	moment = require('moment'),
    +	xml2js = require('xml2js'),
    +	Recurly = require('node-recurly'),
    +	recurly = new Recurly(require('./config'));
    +
    +var parser = new xml2js.Parser();
    +// fs.readFile('./foo.xml', function(err, data) {
    +// 	parser.parseString(data, function (err, result) {
    +// 		console.log(inspect(result, { colors: true, depth: Infinity }));
    +// 	});
    +// });
    +
    +/*
    +app.use(express.basicAuth(function(user, pass, callback) {
    + var result = (user === 'testUser' && pass === 'testPass');
    + callback(null, result);
    +}));
    +*/
    +
    +var subscription = module.exports = {
    +	
    +  callbacks: {
    +		// accounts
    +		new_account_notification: function(data){
    +		},
    +		canceled_account_notification: function(data){
    +		},
    +		billing_info_updated_notification: function(data){
    +		},
    +		reactivated_account_notification: function(data){
    +		},
    +		
    +		// invoices
    +		new_invoice_notification: function(data){
    +		},
    +		closed_invoice_notification: function(data){
    +		},
    +		past_due_invoice_notification: function(data){
    +		},
    +		
    +		// subscriptions
    +		new_subscription_notification: function(data){
    +		},
    +		updated_subscription_notification: function(data){
    +		},
    +		canceled_subscription_notification: function(data){
    +		},
    +		expired_subscription_notification: function(data){
    +		},
    +		renewed_subscription_notification: function(data){
    +		},
    +		
    +		// payments
    +		successful_payment_notification: function(data){
    +		},
    +		failed_payment_notification: function(data){
    +		},
    +		successful_refund_notification: function(data){
    +		},
    +		void_payment_notification: function(data){
    +		},
    +  },
    +	
    +  // need a route for the webhook,
    +  // then calls to get appropriate info from the recurly api
    +	webhook: function(req, res){
    +    res.status(200).end()
    +		parser.parseString(data, function (err, result) {
    +			console.log(inspect(result, { colors: true, depth: Infinity }));
    +			for (var i in data) {
    +			  if (subscription.callbacks[i]) {
    +			    subscription.callbacks[i](data[i])
    +			  }
    +			}
    +		});
    +	},
    +}
    -- 
    cgit v1.2.3-70-g09d2
    
    
    From 3eee6a15ee44a75f6deedd073f60b88d342d56ef Mon Sep 17 00:00:00 2001
    From: Jules Laplace 
    Date: Thu, 22 Jan 2015 16:54:08 -0500
    Subject: recurly links on brochure
    
    ---
     server/lib/schemas/Plan.js  |  2 ++
     server/lib/schemas/User.js  |  1 +
     server/lib/webhook/index.js |  1 +
     views/about/brochure.ejs    | 19 +++++++++++++++----
     4 files changed, 19 insertions(+), 4 deletions(-)
    
    diff --git a/server/lib/schemas/Plan.js b/server/lib/schemas/Plan.js
    index 1208672..8a19b99 100644
    --- a/server/lib/schemas/Plan.js
    +++ b/server/lib/schemas/Plan.js
    @@ -10,6 +10,8 @@ var PlanSchema = new mongoose.Schema({
       name: { type: String },
       slug: { type: String },
     
    +  level: { type: Number },
    +
       monthly_price: { type: Number },
       yearly_price: { type: Number },
     
    diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js
    index ae1d912..867939e 100644
    --- a/server/lib/schemas/User.js
    +++ b/server/lib/schemas/User.js
    @@ -56,6 +56,7 @@ var UserSchema = new mongoose.Schema({
     	},
     	
     	plan_level: { type: Number, default: 0 },
    +	subscription_id: { type: mongoose.Schema.ObjectId },
     	
     	location: { type: String, default: "" },
     	photo: { type: String, default: "" },
    diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js
    index c4b4b76..ebbd01a 100644
    --- a/server/lib/webhook/index.js
    +++ b/server/lib/webhook/index.js
    @@ -33,6 +33,7 @@ var subscription = module.exports = {
       callbacks: {
     		// accounts
     		new_account_notification: function(data){
    +			// 
     		},
     		canceled_account_notification: function(data){
     		},
    diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs
    index e75f8c6..cffa51f 100644
    --- a/views/about/brochure.ejs
    +++ b/views/about/brochure.ejs
    @@ -33,8 +33,14 @@
             
  • Each new floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions
  • VValls logo appears when embedding an exhibition on a web page
  • - - + [[ if (! logged_in) { ]] + + [[ } else if (! profile.plan_level || profile.plan_level < plan.level) { ]] + + [[ } else if (profile.plan_level == plan.level) { ]] + Current Level + [[ } else { ]] + [[ } ]]
  • @@ -49,8 +55,13 @@
  • Includes planning for 3D objects in the room
  • No VValls logo on embed
  • - - + [[ if (! logged_in) { ]] + + [[ } else if (! profile.plan_level || profile.plan_level < plan.level) { ]] + + [[ } else if (profile.plan_level == plan.level) { ]] + Current Level + [[ } ]]
  • -- cgit v1.2.3-70-g09d2 From e0debd761bc24cd42f4140d2b6cc32a4271fe975 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Fri, 23 Jan 2015 02:35:46 -0500 Subject: getting webhooks in order.. didnt need as many as i thought --- Procfile | 3 +- config.json.example | 1 + server/index.js | 2 +- server/lib/schemas/User.js | 2 + server/lib/webhook/config.js | 2 +- server/lib/webhook/index.js | 119 +++++++++++++----------------------------- server/lib/webhook/webhook.js | 118 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 86 deletions(-) create mode 100644 server/lib/webhook/webhook.js diff --git a/Procfile b/Procfile index 983db91..bab08fb 100644 --- a/Procfile +++ b/Procfile @@ -1 +1,2 @@ -web: node server \ No newline at end of file +web: node server +webhook: node server/lib/webhook \ No newline at end of file diff --git a/config.json.example b/config.json.example index 6028021..b8c310c 100644 --- a/config.json.example +++ b/config.json.example @@ -3,6 +3,7 @@ "hostName": "lvh.me", "port": 3000, "socketPort": 1337, + "webhookPort": 5000, "databaseHost": "lvh.me", "pageSize": 10, "env": { "development": 1 } diff --git a/server/index.js b/server/index.js index 9a9323c..02fea3c 100644 --- a/server/index.js +++ b/server/index.js @@ -72,7 +72,7 @@ site.setup = function(){ server = http.createServer(app) server.listen(app.get('port'), function () { - console.log('Express server listening on port ' + app.get('port')); + console.log('Vvalls server listening on port ' + app.get('port')); }); // var io = websocket.listen(server) diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 867939e..77de2d4 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -56,6 +56,8 @@ var UserSchema = new mongoose.Schema({ }, plan_level: { type: Number, default: 0 }, + plan_type: { type: String, default: "free" }, + last_charged: { type: Date, default: null }, subscription_id: { type: mongoose.Schema.ObjectId }, location: { type: String, default: "" }, diff --git a/server/lib/webhook/config.js b/server/lib/webhook/config.js index ecafeb3..3d7e1c5 100644 --- a/server/lib/webhook/config.js +++ b/server/lib/webhook/config.js @@ -1,5 +1,5 @@ module.exports = { - API_KEY: require('process').env['VVALLS_RECURLY_SECRET'], + API_KEY: process.env['VVALLS_RECURLY_SECRET'], SUBDOMAIN: 'vvalls', ENVIRONMENT: 'sandbox', DEBUG: true, diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js index ebbd01a..7dd68e6 100644 --- a/server/lib/webhook/index.js +++ b/server/lib/webhook/index.js @@ -1,89 +1,42 @@ -// // where should this live? -// app.get('/subscribe/webhook', views.subscription.webhook); +var config = require('../../../config.json'), + http = require('http'), + express = require('express'), + bodyParser = require('body-parser'), + mongoose = require('mongoose'); -/* jshint node: true */ +var http = require('http'), + express = require('express'), + bodyParser = require('body-parser'), + multer = require('multer'), + MongoStore = require('connect-mongo')(express), + passport = require('passport'), + path = require('path'), + mongoose = require('mongoose'); -var User = require('../schemas/User'), - Subscription = require('../schemas/Subscription'), - config = require('../../../config'), - middleware = require('../middleware'), - util = require('../util'), - _ = require('lodash'), - moment = require('moment'), - xml2js = require('xml2js'), - Recurly = require('node-recurly'), - recurly = new Recurly(require('./config')); +var app = express() +var server +var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://' + config.databaseHost + '/vvalls') -var parser = new xml2js.Parser(); -// fs.readFile('./foo.xml', function(err, data) { -// parser.parseString(data, function (err, result) { -// console.log(inspect(result, { colors: true, depth: Infinity })); -// }); -// }); +var site = {} -/* -app.use(express.basicAuth(function(user, pass, callback) { - var result = (user === 'testUser' && pass === 'testPass'); - callback(null, result); -})); -*/ +site.init = function(){ + mongoose.connect(DATABASE_URI, {}, site.ready); +} + +site.ready = function(){ + app.set('port', config.webhookPort); + app.use(bodyParser()); + app.use(express.query()); + app.set('env', config.env.production ? "production" : "development") + app.get('env') === 'development' && app.use(express.errorHandler()); -var subscription = module.exports = { - - callbacks: { - // accounts - new_account_notification: function(data){ - // - }, - canceled_account_notification: function(data){ - }, - billing_info_updated_notification: function(data){ - }, - reactivated_account_notification: function(data){ - }, - - // invoices - new_invoice_notification: function(data){ - }, - closed_invoice_notification: function(data){ - }, - past_due_invoice_notification: function(data){ - }, - - // subscriptions - new_subscription_notification: function(data){ - }, - updated_subscription_notification: function(data){ - }, - canceled_subscription_notification: function(data){ - }, - expired_subscription_notification: function(data){ - }, - renewed_subscription_notification: function(data){ - }, - - // payments - successful_payment_notification: function(data){ - }, - failed_payment_notification: function(data){ - }, - successful_refund_notification: function(data){ - }, - void_payment_notification: function(data){ - }, - }, - - // need a route for the webhook, - // then calls to get appropriate info from the recurly api - webhook: function(req, res){ - res.status(200).end() - parser.parseString(data, function (err, result) { - console.log(inspect(result, { colors: true, depth: Infinity })); - for (var i in data) { - if (subscription.callbacks[i]) { - subscription.callbacks[i](data[i]) - } - } - }); - }, + server = http.createServer(app) + server.listen(app.get('port'), function () { + console.log('Webhook server listening on port ' + app.get('port')); + }); + + app.get('/', function(req,res){ res.send('HI THERE') }) + app.get('/subscribe/webhook', require('./webhook').webhook); } + +site.init() diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js new file mode 100644 index 0000000..067af30 --- /dev/null +++ b/server/lib/webhook/webhook.js @@ -0,0 +1,118 @@ +// // where should this live? +// app.get('/subscribe/webhook', views.subscription.webhook); + +/* +app.use(express.basicAuth(function(user, pass, callback) { + var result = (user === 'testUser' && pass === 'testPass'); + callback(null, result); +})); +*/ + + +/* jshint node: true */ + +var User = require('../schemas/User'), + Subscription = require('../schemas/Subscription'), + config = require('../../../config'), + middleware = require('../middleware'), + util = require('../util'), + _ = require('lodash'), + moment = require('moment'), + xml2js = require('xml2js'), + Recurly = require('node-recurly'), + recurly = new Recurly(require('./config')); + +var parser = new xml2js.Parser(); + +var subscription = module.exports = { + plan_level: { + free: 0, + basic: 1, + pro: 2, + }, + + callbacks: { + // accounts + new_account_notification: function(data){ + // fires on successful signup + // use the account_code to find the user, + }, + canceled_account_notification: function(data){ + }, + billing_info_updated_notification: function(data){ + }, + reactivated_account_notification: function(data){ + }, + + // invoices + new_invoice_notification: function(data){ + }, + closed_invoice_notification: function(data){ + }, + past_due_invoice_notification: function(data){ + }, + + // subscriptions + new_subscription_notification: function(data){ + var account = data.account + User.findOne({ _id: account.account_code }, function(err, user){ + if (err) return; + var subscription = data.subscription + + var plan = subscription.plan.plan_code.split("_") + var plan_type = plan[0] + var plan_period = plan[1] + + user.plan_type = plan_type + user.plan_level = subscription.plan_level[plan_type] + + // subscription.uuid + // subscription.subscription_add_ons[] + // subscription.subscription_add_ons[0].quantity + user.save(function(){ + }) + + }) + }, + updated_subscription_notification: function(data){ + }, + canceled_subscription_notification: function(data){ + }, + expired_subscription_notification: function(data){ + }, + renewed_subscription_notification: function(data){ + }, + + // payments + successful_payment_notification: function(data){ + var account = data.account + User.findOne({ _id: account.account_code }, function(err, user){ + if (err) return; + user.last_charged = new Date(data.transaction.date) + user.save(function(){ + }) + }) + }, + failed_payment_notification: function(data){ + }, + successful_refund_notification: function(data){ + }, + void_payment_notification: function(data){ + }, + + }, + + // need a route for the webhook, + // then calls to get appropriate info from the recurly api + webhook: function(req, res){ + res.status(200).end() + parser.parseString(data, function (err, result) { + console.log(inspect(result, { colors: true, depth: Infinity })); + for (var i in data) { + if (subscription.callbacks[i]) { + subscription.callbacks[i](data[i]) + } + } + }); + }, +} -- cgit v1.2.3-70-g09d2 From 74fb7a313b4d9ad3517e97133febff9cada96fe0 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 23 Jan 2015 14:46:44 -0500 Subject: handle subscribe and payment events with webhook --- server/lib/schemas/Subscription.js | 17 +++--- server/lib/schemas/User.js | 1 - server/lib/webhook/index.js | 4 +- server/lib/webhook/webhook.js | 108 ++++++++++++++++++++++--------------- 4 files changed, 76 insertions(+), 54 deletions(-) diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index 7f2579b..99e4ebf 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -8,14 +8,15 @@ var mongoose = require('mongoose'), var SubscriptionSchema = new mongoose.Schema({ user_id: { type: mongoose.Schema.ObjectId, index: true }, - - monthly_total: { type: Number }, - yearly_total: { type: Number }, - - plans: [{ - tier: { type: String }, - monthly: { type: Boolean }, - projects: [{ type: mongoose.Schema.ObjectId }], + + plan_level: { type: Number, default: 0 }, + plan_type: { type: String, default: "free" }, + last_charged: { type: Date, default: null }, + + subscription_uuid: { type: String }, + subscription_add_ons: [{ + name: { type: String }, + quantity: { type: Number }, }], created_at: { type: Date, default: Date.now }, diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 77de2d4..06ad33d 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -58,7 +58,6 @@ var UserSchema = new mongoose.Schema({ plan_level: { type: Number, default: 0 }, plan_type: { type: String, default: "free" }, last_charged: { type: Date, default: null }, - subscription_id: { type: mongoose.Schema.ObjectId }, location: { type: String, default: "" }, photo: { type: String, default: "" }, diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js index 7dd68e6..11419c2 100644 --- a/server/lib/webhook/index.js +++ b/server/lib/webhook/index.js @@ -13,6 +13,8 @@ var http = require('http'), path = require('path'), mongoose = require('mongoose'); +var webhook = require('./webhook'); + var app = express() var server var DATABASE_URI = process.env.MONGOLAB_URI || ('mongodb://' + config.databaseHost + '/vvalls') @@ -36,7 +38,7 @@ site.ready = function(){ }); app.get('/', function(req,res){ res.send('HI THERE') }) - app.get('/subscribe/webhook', require('./webhook').webhook); + webhook.route(app) } site.init() diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 067af30..2e5e627 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -24,7 +24,7 @@ var User = require('../schemas/User'), var parser = new xml2js.Parser(); -var subscription = module.exports = { +var subscribe = module.exports = { plan_level: { free: 0, basic: 1, @@ -32,87 +32,107 @@ var subscription = module.exports = { }, callbacks: { +/* // accounts - new_account_notification: function(data){ + new_account_notification: function(data, user){ // fires on successful signup - // use the account_code to find the user, }, - canceled_account_notification: function(data){ + canceled_account_notification: function(data, user){ }, - billing_info_updated_notification: function(data){ + billing_info_updated_notification: function(data, user){ }, - reactivated_account_notification: function(data){ + reactivated_account_notification: function(data, user){ }, // invoices - new_invoice_notification: function(data){ + new_invoice_notification: function(data, user){ }, - closed_invoice_notification: function(data){ + closed_invoice_notification: function(data, user){ }, - past_due_invoice_notification: function(data){ + past_due_invoice_notification: function(data, user){ }, - +*/ + // subscriptions - new_subscription_notification: function(data){ + new_subscription_notification: function(data, user){ var account = data.account - User.findOne({ _id: account.account_code }, function(err, user){ - if (err) return; - var subscription = data.subscription - - var plan = subscription.plan.plan_code.split("_") + Subscription.findOne({ "uuid": data.subscription.uuid }, function(err, subscription){ + if (err || subscription) return; + + var plan = data.subscription.plan.plan_code.split("-") var plan_type = plan[0] var plan_period = plan[1] user.plan_type = plan_type - user.plan_level = subscription.plan_level[plan_type] - - // subscription.uuid - // subscription.subscription_add_ons[] - // subscription.subscription_add_ons[0].quantity - user.save(function(){ - }) + user.plan_period = plan_period + user.plan_level = subscribe.plan_level[plan_type] + var subscriber = new Subscription () + subscriber.user_id = user._id + subscriber.uuid = data.subscription.uuid + subscriber.add_ons = subscription.add_ons.map(function(add_on){ + return { + name: add_on.plan, + quantity: add_on.quantity, + } + }) + subscriber.save(function(err, data){ + if (err) return; + user.save(function(err){ + // saved! + }) + }) }) }, - updated_subscription_notification: function(data){ + +/* + updated_subscription_notification: function(data, user){ }, - canceled_subscription_notification: function(data){ + canceled_subscription_notification: function(data, user){ }, - expired_subscription_notification: function(data){ + expired_subscription_notification: function(data, user){ }, - renewed_subscription_notification: function(data){ + renewed_subscription_notification: function(data, user){ }, - +*/ // payments - successful_payment_notification: function(data){ + successful_payment_notification: function(data, user){ var account = data.account - User.findOne({ _id: account.account_code }, function(err, user){ - if (err) return; - user.last_charged = new Date(data.transaction.date) - user.save(function(){ - }) - }) + user.last_charged = new Date(data.transaction.date) + user.save(function(){ + }) }, - failed_payment_notification: function(data){ +/* + failed_payment_notification: function(data, user){ }, - successful_refund_notification: function(data){ + successful_refund_notification: function(data, user){ }, - void_payment_notification: function(data){ + void_payment_notification: function(data, user){ }, - +*/ }, - // need a route for the webhook, + execute: function(action, data){ + User.findOne({ _id: data.account.account_code }, function(err, user){ + if (err) { return } + subscribe.callbacks[action](data, user) + }) + }, + // then calls to get appropriate info from the recurly api - webhook: function(req, res){ + handle: function(req, res){ res.status(200).end() parser.parseString(data, function (err, result) { console.log(inspect(result, { colors: true, depth: Infinity })); - for (var i in data) { - if (subscription.callbacks[i]) { - subscription.callbacks[i](data[i]) + for (var action in result) { + if (subscribe.callbacks[action]) { + subscribe.execute(action, result[action]); } } }); }, + + route: function(app){ + app.post('/subscribe/webhook', subscribe.handle); + }, } -- cgit v1.2.3-70-g09d2 From 5efb0ed941ed80136e63014c4f615574b2b613d7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 23 Jan 2015 17:58:41 -0500 Subject: edit subscription partial stub --- server/lib/api/index.js | 1 + server/lib/api/subscription.js | 22 ++++++++++ server/lib/schemas/Subscription.js | 3 +- server/lib/webhook/config.js | 6 --- server/lib/webhook/recurly-config.js | 6 +++ server/lib/webhook/webhook.js | 8 ++-- views/about/brochure.ejs | 12 +++--- views/partials/edit-subscription.ejs | 33 +++++++++++++++ views/profile.ejs | 82 ++++++++++++++++++++---------------- 9 files changed, 119 insertions(+), 54 deletions(-) create mode 100644 server/lib/api/subscription.js delete mode 100644 server/lib/webhook/config.js create mode 100644 server/lib/webhook/recurly-config.js create mode 100644 views/partials/edit-subscription.ejs diff --git a/server/lib/api/index.js b/server/lib/api/index.js index 11e13fc..9478d9b 100644 --- a/server/lib/api/index.js +++ b/server/lib/api/index.js @@ -8,6 +8,7 @@ var api = { projects: require('./projects'), rooms: require('./rooms'), collaborator: require('./collaborator'), + subscription: require('./subscription'), } module.exports = api diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js new file mode 100644 index 0000000..6fe8c61 --- /dev/null +++ b/server/lib/api/subscription.js @@ -0,0 +1,22 @@ +/* jshint node: true */ + +var _ = require('lodash'), + util = require('../util'), + upload = require('../upload'), + config = require('../../../config.json'), + User = require('../schemas/User'), + Project = require('../schemas/Project'), + Layout = require('../schemas/Layout'), + Subscription = require('../schemas/Subscription'); + +var subscription = module.exports = { + +/* + index: function(req, res){ + Project.find({ user_id: req.user._id }, function(err, docs){ + res.json(docs) + }) + }, +*/ + +}; \ No newline at end of file diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index 99e4ebf..2f49ea1 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -9,9 +9,8 @@ var mongoose = require('mongoose'), var SubscriptionSchema = new mongoose.Schema({ user_id: { type: mongoose.Schema.ObjectId, index: true }, - plan_level: { type: Number, default: 0 }, plan_type: { type: String, default: "free" }, - last_charged: { type: Date, default: null }, + plan_period: { type: String, default: "monthly" }, subscription_uuid: { type: String }, subscription_add_ons: [{ diff --git a/server/lib/webhook/config.js b/server/lib/webhook/config.js deleted file mode 100644 index 3d7e1c5..0000000 --- a/server/lib/webhook/config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - API_KEY: process.env['VVALLS_RECURLY_SECRET'], - SUBDOMAIN: 'vvalls', - ENVIRONMENT: 'sandbox', - DEBUG: true, -}; diff --git a/server/lib/webhook/recurly-config.js b/server/lib/webhook/recurly-config.js new file mode 100644 index 0000000..3d7e1c5 --- /dev/null +++ b/server/lib/webhook/recurly-config.js @@ -0,0 +1,6 @@ +module.exports = { + API_KEY: process.env['VVALLS_RECURLY_SECRET'], + SUBDOMAIN: 'vvalls', + ENVIRONMENT: 'sandbox', + DEBUG: true, +}; diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 2e5e627..e9a7925 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -20,7 +20,7 @@ var User = require('../schemas/User'), moment = require('moment'), xml2js = require('xml2js'), Recurly = require('node-recurly'), - recurly = new Recurly(require('./config')); + recurly = new Recurly(require('./recurly-config')); var parser = new xml2js.Parser(); @@ -64,12 +64,14 @@ var subscribe = module.exports = { var plan_period = plan[1] user.plan_type = plan_type - user.plan_period = plan_period user.plan_level = subscribe.plan_level[plan_type] var subscriber = new Subscription () - subscriber.user_id = user._id subscriber.uuid = data.subscription.uuid + subscriber.user_id = user._id + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = subscribe.plan_level[plan_type] subscriber.add_ons = subscription.add_ons.map(function(add_on){ return { name: add_on.plan, diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index cffa51f..1c808f8 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -35,9 +35,9 @@
  • [[ if (! logged_in) { ]] - [[ } else if (! profile.plan_level || profile.plan_level < plan.level) { ]] - - [[ } else if (profile.plan_level == plan.level) { ]] + [[ } else if (! user.plan_level || user.plan_level < plan.level) { ]] + + [[ } else if (user.plan_level == plan.level) { ]] Current Level [[ } else { ]] [[ } ]] @@ -57,9 +57,9 @@
  • [[ if (! logged_in) { ]] - [[ } else if (! profile.plan_level || profile.plan_level < plan.level) { ]] - - [[ } else if (profile.plan_level == plan.level) { ]] + [[ } else if (! user.plan_level || user.plan_level < plan.level) { ]] + + [[ } else if (user.plan_level == plan.level) { ]] Current Level [[ } ]] diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs new file mode 100644 index 0000000..0aa5281 --- /dev/null +++ b/views/partials/edit-subscription.ejs @@ -0,0 +1,33 @@ +
    + X +
    +
    + +
      +
    • +

      Edit Subscription

      +
    • +
    • + [[ if (! user.plan_level) { ]] + You are currently using the free plan. For access to all of Vvalls features, + consider upgrading to a paid plan. +

      + View the Plans + [[ } else { ]] + Your current plan level is XXX + You have been a member since XXX + $cost/month OR $cost/year + + You are using N basic layouts + Buy more + + You are using N pro layouts + Buy more / Upgrade your account + + Cancel your subscription + [[ } ]] +

    • +
    +
    +
    +
    diff --git a/views/profile.ejs b/views/profile.ejs index 88af6b0..e149847 100644 --- a/views/profile.ejs +++ b/views/profile.ejs @@ -9,48 +9,53 @@ [[- include partials/header ]]
    - [[ if (profile.photo && profile.photo.length) { ]] -
    -
    - [[ } else { ]] -
    - - - [[ if (isOwnProfile) { ]] -
    click to add profile pic
    - - [[ } ]] -
    -
    + [[ if (profile.photo && profile.photo.length) { ]] +
    +
    + [[ } else { ]] +
    + + + [[ if (isOwnProfile) { ]] +
    click to add profile pic
    + [[ } ]] -
    -
    -

    [[- profile.displayName ]]

    - [[ if (profile.location) { ]] - - [[- profile.location ]] - - [[ } ]] - [[ if (profile.website && profile.website.length) { ]] - - [[- profile.website ]] - - [[ } ]] - [[ if (profile.twitterName && profile.twitterName.length) { ]] - - @[[- profile.twitterName ]] - - [[ } ]] -
    -
    - +
    +
    + [[ } ]] +
    +
    +

    [[- profile.displayName ]]

    + [[ if (profile.location) { ]] + + [[- profile.location ]] + + [[ } ]] + [[ if (profile.website && profile.website.length) { ]] + + [[- profile.website ]] + + [[ } ]] + [[ if (profile.twitterName && profile.twitterName.length) { ]] + + @[[- profile.twitterName ]] + + [[ } ]] + [[ if (profile.plan_level == 1) { ]] + PREMIUM + [[ } else if (profile.plan_level == 2) { ]] + PRO + [[ } ]] +
    +
    [[ if (projects.length) { ]] +

    [[- profile.username ]] has [[- projectCount ]] project[[- projectCount != 1 ? "s" : "" ]]

    - [[ include projects/list-projects ]] + [[ } else { ]] - +

    Welcome to VVALLS

    @@ -69,8 +74,11 @@

    This person has no projects.

    [[ } ]]
    + [[ } ]] -
    + +
  • + [[ include partials/edit-subscription ]] [[ include partials/edit-profile ]] [[ include projects/layouts-modal ]] [[ include projects/edit-project ]] -- cgit v1.2.3-70-g09d2 From 29e0f23c5ade5072851aaa74314166b0c7281272 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 23 Jan 2015 19:28:53 -0500 Subject: stub subscription modal js --- .../javascripts/ui/site/EditSubscriptionModal.js | 21 ++++++++++ views/partials/edit-subscription.ejs | 45 +++++++++++++++------- 2 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 public/assets/javascripts/ui/site/EditSubscriptionModal.js diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js new file mode 100644 index 0000000..1b3b859 --- /dev/null +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -0,0 +1,21 @@ + +var EditSubscriptionModal = ModalFormView.extend({ + el: ".mediaDrawer.editSubscription", + action: "/api/subscription", + method: "put", + + fixedClose: true, + + events: { + "click [data-role='changePasswordToggle']": 'togglePasswordFields' + }, + + load: function(){ + this.reset() + $.get("/api/subscription", function(data){ + + this.show() + }.bind(this)) + }, + +}) diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 0aa5281..1f8db62 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -7,24 +7,43 @@
  • Edit Subscription

  • -
  • - [[ if (! user.plan_level) { ]] +
    You are currently using the free plan. For access to all of Vvalls features, consider upgrading to a paid plan.

    View the Plans - [[ } else { ]] - Your current plan level is XXX - You have been a member since XXX - $cost/month OR $cost/year +

    +
    + Your current plan level is + + + + + + + + + + + + + + + + + + + + + + + + +
    Basic plan@ $/
    Additional basic layouts@ $/Buy more
    Additional PRO layouts$/Buy more
    Total$/
    + + - You are using N basic layouts - Buy more - - You are using N pro layouts - Buy more / Upgrade your account - - Cancel your subscription + [[ } ]]
  • -- cgit v1.2.3-70-g09d2 From b60055ee8c77eb9bb035f72147ce6c710ab4347c Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 14 Jan 2015 15:44:34 -0500 Subject: roll back devicePixelRatio fix on desktop --- public/assets/javascripts/app.js | 4 +++- public/assets/javascripts/mx/mx.js | 14 +++++++------- public/assets/stylesheets/app.css | 4 ++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index 41edafe..a146325 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -3,7 +3,7 @@ if (is_mobile) { $("html").addClass("mobile") } else { - $("html").addClass("desktop") + $("html").addClass("desktop") } @@ -23,6 +23,8 @@ app.launch = function () { var movements + app.devicePixelRatio = is_mobile ? devicePixelRatio : 1 + scene = new MX.Scene().addTo('#scene') scene.width = window.innerWidth scene.height = window.innerHeight diff --git a/public/assets/javascripts/mx/mx.js b/public/assets/javascripts/mx/mx.js index d59a551..ab9a9a0 100644 --- a/public/assets/javascripts/mx/mx.js +++ b/public/assets/javascripts/mx/mx.js @@ -162,24 +162,24 @@ var MX = MX || (function (undefined) { Object.defineProperty(this, 'width', { get: function () { return width - || parseInt(self.el.style.width*devicePixelRatio, 10) + || parseInt(self.el.style.width, 10) * app.devicePixelRatio || 0 }, set: function (val) { width = val - this.el.style.width = (width/devicePixelRatio) + 'px' + this.el.style.width = (width/app.devicePixelRatio) + 'px' } }) Object.defineProperty(this, 'height', { get: function () { return height - || parseInt(self.el.style.height*devicePixelRatio, 10) + || parseInt(self.el.style.height, 10) * app.devicePixelRatio || 0 }, set: function (val) { height = val - this.el.style.height = (height/devicePixelRatio) + 'px' + this.el.style.height = (height/app.devicePixelRatio) + 'px' } }) } @@ -302,9 +302,9 @@ var MX = MX || (function (undefined) { + (-this.y).toFixed(floatPrecision) + 'px,' + (-this.z).toFixed(floatPrecision) + 'px) ' + 'scale3d(' - + (devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ',' - + (devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ',' - + (devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') ' + + (app.devicePixelRatio * this.scaleX).toFixed(floatPrecision) + ',' + + (app.devicePixelRatio * this.scaleY).toFixed(floatPrecision) + ',' + + (app.devicePixelRatio * this.scaleZ).toFixed(floatPrecision) + ') ' if (rotationTranslation) { transformString += rotationTranslation.before diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index aecd6be..62a5682 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -913,6 +913,9 @@ border-left: 1px solid black; .no-templates { display: none; } +.no-templates a { + border-bottom: 1px solid; +} .templates span { display: block; @@ -2357,6 +2360,7 @@ button { font-weight: 500; width: 100%; font-size:14px; + font-family:'Lato', sans-serif; } #builder-units { -- cgit v1.2.3-70-g09d2 From 0a8849bc0abea10fa0d53207159c09f433c25555 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Mon, 26 Jan 2015 20:37:06 -0500 Subject: methodz --- server/lib/api/subscription.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 6fe8c61..bd19127 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -18,5 +18,17 @@ var subscription = module.exports = { }) }, */ + show: function(req,res){ + // fetch from recurly + }, + + update: function(req,res){ + // update plan_type on recurly + // update add_ons on recurly + }, + + destroy: function(req,res){ + // destroy on recurly + }, }; \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 3059c3203d2cec4e2e745be8c21c6d3fbddb0c14 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Wed, 28 Jan 2015 01:39:28 -0500 Subject: rigging EditSubscriptionModal --- Gruntfile.js | 1 + config.json.example | 1 - public/assets/javascripts/ui/_router.js | 10 ++++++++++ server/index.js | 1 + server/lib/api/subscription.js | 19 ++++++++++++++++--- server/lib/webhook/webhook.js | 14 ++++++++++++++ views/about/brochure.ejs | 3 +++ views/partials/edit-subscription.ejs | 1 - views/partials/scripts.ejs | 1 + 9 files changed, 46 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index f62cc82..ed236c5 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -99,6 +99,7 @@ module.exports = function(grunt) { "public/assets/javascripts/ui/site/LayoutsModal.js", "public/assets/javascripts/ui/site/EditProjectModal.js", "public/assets/javascripts/ui/site/EditProfileModal.js", + "public/assets/javascripts/ui/site/EditSubscriptionModal.js", "public/assets/javascripts/ui/site/DocumentModal.js", "public/assets/javascripts/ui/site/HomeView.js", diff --git a/config.json.example b/config.json.example index b8c310c..dc79edd 100644 --- a/config.json.example +++ b/config.json.example @@ -5,6 +5,5 @@ "socketPort": 1337, "webhookPort": 5000, "databaseHost": "lvh.me", - "pageSize": 10, "env": { "development": 1 } } diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 3532428..9e7ce75 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -9,6 +9,7 @@ var SiteRouter = Router.extend({ "click [data-role='new-project-modal']": 'newProject', "click [data-role='edit-project-modal']": 'editProject', "click [data-role='edit-profile-modal']": 'editProfile', + "click [data-role='edit-subscription-modal']": 'editSubscription', "click [data-role='new-document-modal']": 'newDocument', "click [data-role='edit-document-modal']": 'editDocument', "click [data-role='destroy-document-modal']": 'destroyDocument', @@ -29,6 +30,7 @@ var SiteRouter = Router.extend({ "/profile": 'profile', "/profile/edit": 'editProfile', + "/profile/billing": 'editSubscription', "/profile/:name": 'profile', "/about/:name/edit": 'editDocument', "/about/new": 'newDocument', @@ -56,6 +58,7 @@ var SiteRouter = Router.extend({ "/profile": 'profile', "/profile/edit": 'editProfile', + "/profile/billing": 'editSubscription', "/profile/:name": 'profile', "/project/:name": 'projectViewer', @@ -69,6 +72,7 @@ var SiteRouter = Router.extend({ this.newProjectModal = new NewProjectModal() this.editProjectModal = new EditProjectModal() this.editProfileModal = new EditProfileModal() + this.editSubscriptionModal = new EditSubscriptionModal() this.passwordForgotModal = new PasswordForgot() this.documentModal = new DocumentModal() this.profileView = new ProfileView() @@ -195,6 +199,12 @@ var SiteRouter = Router.extend({ this.editProfileModal.load() }, + editSubscription: function(e){ + e && e.preventDefault() + window.history.pushState(null, document.title, "/profile/billing") + + this.editSubscriptionModal.load() + }, newDocument: function(e){ diff --git a/server/index.js b/server/index.js index 02fea3c..475054d 100644 --- a/server/index.js +++ b/server/index.js @@ -102,6 +102,7 @@ site.route = function () { app.get('/profile', views.profile) app.get('/profile/edit', views.profile) + app.get('/profile/billing', views.profile) app.get('/profile/:username', views.profile) app.get('/about', views.docs); diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index bd19127..83644cf 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -18,16 +18,29 @@ var subscription = module.exports = { }) }, */ - show: function(req,res){ + middleware: { + fetchAccount: function(req, res, next){ + recurly.subscriptions.listByAccount(req.user._id, function(data){ + }) + }, + }, + + // synchronise an account with recurly.. + // useful when testing locally (if webhooks do not fire) + sync: function(req, res){ + // fetch req.user._id + }, + + show: function(req, res){ // fetch from recurly }, - update: function(req,res){ + update: function(req, res){ // update plan_type on recurly // update add_ons on recurly }, - destroy: function(req,res){ + destroy: function(req, res){ // destroy on recurly }, diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index e9a7925..4f23d0b 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -134,7 +134,21 @@ var subscribe = module.exports = { }); }, + list: function(req, res){ + recurly.subscriptions.listByAccount(req.params.id, function(data){ + if (data.data != 404) { + res.json(data) + return + } + else { + res.json(data) + return + } + }) + }, + route: function(app){ app.post('/subscribe/webhook', subscribe.handle); + app.get('/subscribe/list/:id', subscribe.list); }, } diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index 1c808f8..49b03db 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -123,6 +123,9 @@ text-align: center; margin-bottom: 10px; } +.about_plan ul { + margin-bottom: 60px; +} .planbox li { list-style-type: none; margin-bottom: 5px; diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 1f8db62..adc3f71 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -44,7 +44,6 @@ - [[ } ]] diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index fc94992..04bd945 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -95,6 +95,7 @@ + -- cgit v1.2.3-70-g09d2 From 79fee7f24d43873fc35295eab1d2a089d373e133 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 28 Jan 2015 11:49:08 -0500 Subject: merge --- server/lib/schemas/Subscription.js | 6 +++++ server/lib/schemas/User.js | 1 + server/lib/views/subscription.js | 50 -------------------------------------- 3 files changed, 7 insertions(+), 50 deletions(-) delete mode 100644 server/lib/views/subscription.js diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index 8315009..8ec557d 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -17,6 +17,12 @@ var SubscriptionSchema = new mongoose.Schema({ monthly: { type: Boolean }, }], + history: [{ + action: { type: String }, + plan_id: { type: String }, + created_at: { type: Date, default: Date.now }, + }], + created_at: { type: Date, default: Date.now }, updated_at: { type: Date, default: Date.now }, }) diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 180a140..19b5ede 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -62,6 +62,7 @@ var UserSchema = new mongoose.Schema({ twitterName: { type: String, default: "" }, facebookUrl: { type: String, default: "" }, isStaff: { type: Boolean, default: false }, + subscription_id: { type: mongoose.Schema.ObjectId }, created_at: { type: Date }, updated_at: { type: Date }, last_seen: { type: Date }, diff --git a/server/lib/views/subscription.js b/server/lib/views/subscription.js deleted file mode 100644 index ba54bb4..0000000 --- a/server/lib/views/subscription.js +++ /dev/null @@ -1,50 +0,0 @@ -/* jshint node: true */ - -var User = require('../schemas/User'), - Subscription = require('../schemas/Subscription'), - config = require('../../../config'), - middleware = require('../middleware'), - util = require('../util'), - _ = require('lodash'), - moment = require('moment'); - -var subscription = module.exports = { - - fields: { - user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", - }, - - defaults: { - user: { - _id: "", username: "", displayName: "", - created_at: "", updated_at: "", created_ip: "", last_ip: "", - }, - }, - - middleware: { - }, - - helpers: { - project: function(project){ - project = project.toObject() - project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") - project.user = {} - return project - }, - }, - - route: function(app){ - app.get('/staff', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureRecentUsers, - staff.middleware.ensureUsersCount, - staff.middleware.ensureProjectsCount, - staff.middleware.ensureMediaCount, - - staff.index - ); - }, - -} -- cgit v1.2.3-70-g09d2 From 5adac681bdb43b8b709795fa501689fb9ae8a4e1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 28 Jan 2015 19:18:27 -0500 Subject: many methods --- package.json | 1 + server/lib/api/subscription.js | 124 ++++++++++++++++++++++++++++++++---- server/lib/middleware.js | 2 +- server/lib/schemas/Subscription.js | 6 +- server/lib/views/staff.js | 2 +- server/lib/webhook/webhook.js | 2 +- views/about/brochure.ejs | 15 +++-- views/partials/header.ejs | 1 + views/staff/_users.ejs | 1 + views/staff/plans/_form.ejs | 5 ++ views/staff/subscriptions/index.ejs | 2 +- views/staff/users/show.ejs | 1 + 12 files changed, 135 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 8afb96e..e89fcd9 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "express-subdomains": "0.0.5", "html-entities": "~1.0.10", "intro.js": "^0.9.0", + "js2xml": "^1.0.0", "knox": "~0.8.10", "lodash": "~2.4.1", "marked": "~0.3.2", diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 83644cf..40aa715 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -9,7 +9,22 @@ var _ = require('lodash'), Layout = require('../schemas/Layout'), Subscription = require('../schemas/Subscription'); +var plan_levels = { + free: 0, + basic: 1, + pro: 2, +} + var subscription = module.exports = { + middleware: { + ensureSubscription: function(req, res, next){ + Subscription.findOne({ user_id: req.user._id }, function(err, data){ + if (err) { return next() } + req.subscription = data + next() + }) + }, + } /* index: function(req, res){ @@ -18,30 +33,115 @@ var subscription = module.exports = { }) }, */ - middleware: { - fetchAccount: function(req, res, next){ - recurly.subscriptions.listByAccount(req.user._id, function(data){ - }) - }, - }, // synchronise an account with recurly.. - // useful when testing locally (if webhooks do not fire) + // useful when testing locally (where webhooks cannot be received) sync: function(req, res){ - // fetch req.user._id + var subscriber = req.subscription || new Subscription () + var user = req.user + recurly.subscriptions.listByAccount(req.user._id, function(data){ + if (data.description !== 200) { + res.json({ error: "no account" }) + return + } + if (! data.subscriptions.subscription) { + res.json({ error: "account error" }) + return + } + + var plan = data.subscriptions.subscription.plan.plan_code.split("-") + var plan_type = plan[0] + var plan_period = plan[1] + + user.plan_type = plan_type + user.plan_level = plan_levels[plan_type] + + subscriber.uuid = data.subscriptions.subscription.uuid + subscriber.user_id = user._id + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = plan_levels[plan_type] + + var add_ons = data.subscriptions.subscription.subscription_add_ons.subscription_add_on + if (add_ons) { + if (add_ons.add_on_code) { + add_ons = [ add_ons ] + } + // TODO: handle multiple add-ons.. presumably this will work + add_ons.forEach(function(add_on){ + var add_on_type = add_on.add_on_code.split("-")[1] + if (add_on_type == "basic") { + subscriber.basic_layouts = parseInt( add_on.quantity._ ) + } + if (add_on_type == "pro") { + subscriber.pro_layouts = parseInt( add_on.quantity._ ) + } + }) + } + else { + subscriber.basic_layouts = 0 + subscriber.pro_layouts = 0 + } + + subscriber.save(function(){ + user.save(function(){ + res.render(subscriber) + }) + }) + }) }, show: function(req, res){ - // fetch from recurly + res.json(req.subscription || { error: "no subscription" }) }, update: function(req, res){ - // update plan_type on recurly - // update add_ons on recurly + if (! req.subscription ) { + return res.json({ error: "no subscription" }) + } + if (! (req.body.plan_type in plan_levels)) { + return res.json({ error: "bad input" }) + } + var subscriber = req.subscription + + // change.. + // data.plan_code + // data.subscription_add_ons = [] + // add_on.add_on_code + // add_on.quantity + var basic_layouts = max(0, parseInt(req.body.basic_layouts)) + var pro_layouts = max(0, parseInt(req.body.pro_layouts)) + + var data = {} + data.plan_code = req.body.plan_type + "_monthly" + data.subscription_add_ons = [] + + if (plan_levels[req.body.plan_type]) { + data.subscription_add_ons.push({ add_on_code: "extra-basic-layout", quantity: basic_layouts }) + } + + if (req.body.plan_type == "pro") { + data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts }) + } + + + recurly.subscriptions.update(subscriber.uuid, data, function(){ + return res.json(subscriber) + }) }, destroy: function(req, res){ - // destroy on recurly + if (! req.subscription ) { + return res.json({ error: "no subscription" }) + } + var subscriber = req.subscription + + recurly.subscriptions.cancel(subscriber.uuid, function(){ + subscriber.remove(function(){ + req.user.plan_code = 0 + req.user.plan_type = "free" + }) + }) }, }; \ No newline at end of file diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 797d677..7dfe821 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -59,7 +59,7 @@ var middleware = { res.locals.opt = {} next() }, - + ensureProject: function (req, res, next) { if (req.params.slug) { Project.findOne({ slug: req.params.slug }, function(err, project){ diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index b766555..24c5096 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -13,10 +13,8 @@ var SubscriptionSchema = new mongoose.Schema({ plan_period: { type: String, default: "monthly" }, subscription_uuid: { type: String }, - subscription_add_ons: [{ - name: { type: String }, - quantity: { type: Number }, - }], + basic_layouts: { type: Number, default: 0 }, + pro_layouts: { type: Number, default: 0 }, history: [{ action: { type: String }, diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 74dd7cd..67193fe 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -154,7 +154,7 @@ var staff = module.exports = { }, ensurePlans: function(req, res, next){ - Plan.find(function (err, plans) { + Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { res.locals.plans = (plans || []).map(staff.helpers.plan) res.locals.plans.sort(function(a,b){ return a.monthly_price }) next() diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 4f23d0b..a871a3a 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -149,6 +149,6 @@ var subscribe = module.exports = { route: function(app){ app.post('/subscribe/webhook', subscribe.handle); - app.get('/subscribe/list/:id', subscribe.list); + app.get('/subscribe/list/:id', subscribe.middleware.ensureSubscription, subscribe.list); }, } diff --git a/views/about/brochure.ejs b/views/about/brochure.ejs index 49b03db..1dad763 100644 --- a/views/about/brochure.ejs +++ b/views/about/brochure.ejs @@ -34,12 +34,11 @@
  • VValls logo appears when embedding an exhibition on a web page
  • [[ if (! logged_in) { ]] - - [[ } else if (! user.plan_level || user.plan_level < plan.level) { ]] - + + [[ } else if (! user.plan_level) { ]] + [[ } else if (user.plan_level == plan.level) { ]] Current Level - [[ } else { ]] [[ } ]]
  • @@ -56,11 +55,13 @@
  • No VValls logo on embed
  • [[ if (! logged_in) { ]] - - [[ } else if (! user.plan_level || user.plan_level < plan.level) { ]] - + + [[ } else if (! user.plan_level) { ]] + [[ } else if (user.plan_level == plan.level) { ]] Current Level + [[ } else if (user.plan_level < plan.level) { ]] + [[ } ]]
  • diff --git a/views/partials/header.ejs b/views/partials/header.ejs index ce5bab9..2acf2bc 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -64,6 +64,7 @@ [[ if (profile && String(user._id) == String(profile._id)) { ]] Settings + Subscription [[ } else if (! profile) { ]] Profile [[ } ]] diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index d46058f..053e289 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -12,6 +12,7 @@ [view profile] + [recurly] [[- user.last_seen ]] diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index ae5ca5a..b55c5cd 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -16,6 +16,11 @@
    +
  • + +
    +
  • +
  • diff --git a/views/staff/subscriptions/index.ejs b/views/staff/subscriptions/index.ejs index d1c0588..3efffb5 100644 --- a/views/staff/subscriptions/index.ejs +++ b/views/staff/subscriptions/index.ejs @@ -1,6 +1,6 @@ [[ include ../_header ]] -

    Users

    +

    Subscriptions

    [[ include ../_nav ]] diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index 4ce1d9a..d6a21d5 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -19,6 +19,7 @@ [view profile] [view media] + [view on recurly] -- cgit v1.2.3-70-g09d2 From ccfb71101d8f87e4c1dce9eb477d164707ee02ff Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 28 Jan 2015 20:22:13 -0500 Subject: comma --- server/lib/api/subscription.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 40aa715..140bd12 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -24,7 +24,7 @@ var subscription = module.exports = { next() }) }, - } + }, /* index: function(req, res){ @@ -124,7 +124,6 @@ var subscription = module.exports = { data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts }) } - recurly.subscriptions.update(subscriber.uuid, data, function(){ return res.json(subscriber) }) -- cgit v1.2.3-70-g09d2 From fdcc335d7e95139b71083928602713b82f29aba1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 28 Jan 2015 20:22:53 -0500 Subject: lol --- server/lib/webhook/webhook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index a871a3a..4f23d0b 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -149,6 +149,6 @@ var subscribe = module.exports = { route: function(app){ app.post('/subscribe/webhook', subscribe.handle); - app.get('/subscribe/list/:id', subscribe.middleware.ensureSubscription, subscribe.list); + app.get('/subscribe/list/:id', subscribe.list); }, } -- cgit v1.2.3-70-g09d2 From f55d634b7b24b6af0fb7dd017544a79672bb1bc7 Mon Sep 17 00:00:00 2001 From: Julie Lala Date: Wed, 28 Jan 2015 22:23:03 -0500 Subject: routez --- server/index.js | 5 +++++ server/lib/api/subscription.js | 10 +--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/server/index.js b/server/index.js index 475054d..53da448 100644 --- a/server/index.js +++ b/server/index.js @@ -151,6 +151,11 @@ site.route = function () { app.post('/api/media/upload', middleware.ensureAuthenticated, api.media.upload) app.delete('/api/media/destroy', middleware.ensureAuthenticated, api.media.destroy) + app.get('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.sync) + app.get('/api/subscription', middleware.ensureAuthenticated, api.subscription.show) + app.put('/api/subscription', middleware.ensureAuthenticated, api.subscription.update) + app.delete('/api/subscription', middleware.ensureAuthenticated, api.subscription.destroy) + app.get('/test/*', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.modal) views.staff.route(app) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 140bd12..e7cd8f4 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -26,14 +26,6 @@ var subscription = module.exports = { }, }, -/* - index: function(req, res){ - Project.find({ user_id: req.user._id }, function(err, docs){ - res.json(docs) - }) - }, -*/ - // synchronise an account with recurly.. // useful when testing locally (where webhooks cannot be received) sync: function(req, res){ @@ -128,7 +120,7 @@ var subscription = module.exports = { return res.json(subscriber) }) }, - + destroy: function(req, res){ if (! req.subscription ) { return res.json({ error: "no subscription" }) -- cgit v1.2.3-70-g09d2 From 1d88890a988b255c915d0472297b18a2635f6433 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 30 Jan 2015 01:26:46 -0500 Subject: ui boilerplate --- .../javascripts/ui/site/EditSubscriptionModal.js | 40 ++++++++++++++++++++-- views/partials/edit-subscription.ejs | 28 +++++++-------- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 1b3b859..342e8be 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -7,15 +7,51 @@ var EditSubscriptionModal = ModalFormView.extend({ fixedClose: true, events: { - "click [data-role='changePasswordToggle']": 'togglePasswordFields' + "click [data-role='']": 'togglePasswordFields' + }, + + initialize: function(){ + this.$freePlan = this.$("#free_plan") + this.$paidPlan = this.$("#paid_plan") + this.$proLayoutRow = this.$("#proLayoutRow") + + this.$billingInterval = this.$("[data-role=billingInterval]") + + this.$planType = this.$("[data-role=planType]") + this.$planName = this.$("[data-role=planName]") + this.$planCost = this.$("[data-role=planCost]") + + this.$basicLayoutCost = this.$("[data-role=basicLayoutCost]") + this.$basicLayoutQuantity = this.$("[data-role=basicLayoutQuantity]") + + this.$proLayoutCost = this.$("[data-role=proLayoutCost]") + this.$proLayoutQuantity = this.$("[data-role=proLayoutQuantity]") + + this.$upgradeSubscription = this.$("[data-role=upgradeSubscription]") + this.$cancelSubscription = this.$("[data-role=cancelSubscription]") }, load: function(){ this.reset() $.get("/api/subscription", function(data){ - + if (data.error) { + this.$freePlan.show() + this.$paidPlan.hide() + this.show() + return + } + this.$freePlan.show() + this.$paidPlan.hide() + + var plan = data.plans[ data.subscription.plan_name ] + this.show() + + // layouts }.bind(this)) }, + + updateTotals: function(){ + }, }) diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index adc3f71..f49d791 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -13,37 +13,37 @@

    View the Plans

  • -
    - Your current plan level is + -
    -

    [[- plans.free.name ]]

    -
      -
    • [[- plans.free.stock_project_limit ]] exhibition with pre-designed template floor plan -
    -
    - -
    -

    [[- plans.basic.name ]]

    -
      -
    • $[[- plans.basic.monthly_price ]]/mo or $[[- plans.basic.yearly_price ]]/year -
    • Comes with [[- plans.basic.basic_layout_limit ]] basic floor plan and [[- plans.basic.basic_project_limit ]] exhibitions -
    • Each new basic floor plan costs $[[- plans.basic.basic_layout_monthly_price ]]/mo - or $[[- plans.basic.basic_layout_yearly_price ]]/year, minimum 3 months -
    • Each new floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions -
    • VValls logo appears when embedding an exhibition on a web page -
    • - [[ if (! logged_in) { ]] - - [[ } else if (! user.plan_level) { ]] - - [[ } else if (user.plan_level == plan.level) { ]] - Current Level - [[ } ]] -
    -
    - -
    -

    [[- plans.pro.name ]]

    -
      -
    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year -
    • Comes with [[- plans.pro.pro_layout_limit ]] pro floor plan and [[- plans.pro.pro_project_limit ]] exhibitions -
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo - or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months -
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions -
    • Includes planning for 3D objects in the room -
    • No VValls logo on embed -
    • - [[ if (! logged_in) { ]] - - [[ } else if (! user.plan_level) { ]] - - [[ } else if (user.plan_level == plan.level) { ]] - Current Level - [[ } else if (user.plan_level < plan.level) { ]] - - [[ } ]] -
    -
    - -
    -
      -
    • Buying any extra floor plan unlocks collaboration. Invite an artist or curator to work on the exhibition with you. -
    • Basic Floor plan: Rectangle-based design of any dimension. -
    • Pro Floor plan: Trace an arbitrary floor plan from image. -
    -
    - -
    -

    Want Something Custom?

    -
  • We offer customized white-label options for business and educational uses. -
  • Contact us for more information. -
  • + [[ include _plans ]]
    - [[ include ../partials/confirm-modal ]] [[ include ../projects/layouts-modal ]] [[ include ../partials/sign-in ]] @@ -91,51 +28,3 @@ [[ include ../partials/scripts ]] - \ No newline at end of file diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index bb7cc27..2f6e4c1 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -7,15 +7,14 @@
  • Edit Subscription

  • -
    - You are currently using the free plan. For access to all of Vvalls features, +
  • + You are currently using the free version of Vvalls. For access to all of Vvalls features, consider upgrading to a paid plan. -

    - View the Plans -

  • - + +
    +

    [[- plans.basic.name ]]

    +
      +
    • $[[- plans.basic.monthly_price ]]/mo or $[[- plans.basic.yearly_price ]]/year +
    • Comes with [[- plans.basic.basic_layout_limit ]] basic floor plan and [[- plans.basic.basic_project_limit ]] exhibitions +
    • Each new basic floor plan costs $[[- plans.basic.basic_layout_monthly_price ]]/mo + or $[[- plans.basic.basic_layout_yearly_price ]]/year, minimum 3 months +
    • Each new floor plan can have up to [[- plans.basic.basic_project_limit ]] exhibitions +
    • VValls logo appears when embedding an exhibition on a web page +
    • + [[ if (! logged_in) { ]] + + [[ } else if (! user.plan_level) { ]] + + [[ } else if (user.plan_level == plan.level) { ]] + Current Level + [[ } ]] +
    +
    + +
    +

    [[- plans.pro.name ]]

    +
      +
    • $[[- plans.pro.monthly_price ]]/mo or $[[- plans.pro.yearly_price ]]/year +
    • Comes with [[- plans.pro.pro_layout_limit ]] pro floor plan and [[- plans.pro.pro_project_limit ]] exhibitions +
    • Each new pro floor plan costs $[[- plans.pro.pro_layout_monthly_price ]]/mo + or $[[- plans.pro.pro_layout_yearly_price ]]/year, minimum 3 months +
    • Each new pro floor plan can have up to [[- plans.pro.pro_project_limit ]] exhibitions +
    • Includes planning for 3D objects in the room +
    • No VValls logo on embed +
    • + [[ if (! logged_in) { ]] + + [[ } else if (! user.plan_level) { ]] + + [[ } else if (user.plan_level == plan.level) { ]] + Current Level + [[ } else if (user.plan_level < plan.level) { ]] + + [[ } ]] +
    +
    + +
    +
      +
    • Buying any extra floor plan unlocks collaboration.
      Invite an artist or curator to work on the exhibition with you. +
    • Basic Floor plan: Rectangle-based design of any dimension. +
    • Pro Floor plan: Trace an arbitrary floor plan from image. +
    +
    + +
    +

    Want Something Custom?

    +
  • We offer customized white-label options for business and educational uses. +
  • Contact us for more information. +
  • diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 2f6e4c1..cc296f6 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -1,19 +1,19 @@
    X
    -
    +
    • Edit Subscription

    • -
    • +
    • You are currently using the free version of Vvalls. For access to all of Vvalls features, consider upgrading to a paid plan.

      - +
    • -
    • Your current plan level is diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index 053e289..46811b6 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -12,7 +12,8 @@ - - @@ -44,7 +42,8 @@
      [[- user.last_seen ]] -- cgit v1.2.3-70-g09d2 From a3f3f4d370da5d38c039f6cdb36223b396eeeb77 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 30 Jan 2015 17:59:29 -0500 Subject: sync gear for test purposes --- .../javascripts/ui/site/EditSubscriptionModal.js | 20 +++++++++++++++----- public/assets/stylesheets/app.css | 14 ++++++++++++++ server/index.js | 2 +- server/lib/api/subscription.js | 4 +++- views/partials/edit-subscription.ejs | 2 ++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index e7e1fa5..1637e18 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -2,6 +2,7 @@ var EditSubscriptionModal = ModalFormView.extend({ el: ".mediaDrawer.editSubscription", action: "/api/subscription", + syncAction: "/api/subscription/sync", updateAction: "/api/subscription", destroyAction: "/api/subscription/destroy", @@ -11,6 +12,7 @@ var EditSubscriptionModal = ModalFormView.extend({ events: { "click [data-role='upgradeSubscription']": 'upgradeSubscription', "click [data-role='cancelSubscription']": 'cancelSubscription', + "click .gear": 'sync', }, initialize: function(){ @@ -41,6 +43,7 @@ var EditSubscriptionModal = ModalFormView.extend({ this.$upgradeSubscription = this.$("[data-role=upgradeSubscription]") this.$cancelSubscription = this.$("[data-role=cancelSubscription]") + this.$gear = this.$(".gear") }, plan_levels: { @@ -48,10 +51,6 @@ var EditSubscriptionModal = ModalFormView.extend({ basic: 1, pro: 2, }, - - sync: function(){ - $.put(this.syncAction, this.didLoad.bind(this)) - }, loaded: false, load: function(){ @@ -74,6 +73,7 @@ var EditSubscriptionModal = ModalFormView.extend({ show: function(){ + this.$gear.removeClass("turning") if (! this.subscriber) { this.$freePlan.show() this.$paidPlan.hide() @@ -88,7 +88,7 @@ var EditSubscriptionModal = ModalFormView.extend({ this.$paidPlan.show() this.updateTotals() - + this.__super__.show.call(this) }, @@ -127,6 +127,16 @@ var EditSubscriptionModal = ModalFormView.extend({ this.$planTotal.toDollars ( totals.plan_total ) }, + sync: function(){ + this.$gear.addClass("turning") + $.ajax({ + url: this.syncAction, + type: "put", + data: { _csrf: $("[name=_csrf]").val() }, + success: this.didLoad.bind(this) + }) + }, + update: function(){ $.ajax({ url: this.updateAction, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 8184032..981869b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -979,6 +979,20 @@ iframe.embed { .about_custom a { border-bottom: 1px solid; } +.editSubscription .gear { + position: absolute; + top: 10px; + left: 10px; + opacity: 0.1; + cursor: pointer; + transition: all 0.3s; +} +.editSubscription .gear.turning { + opacity: 0.3; + -webkit-transform: rotate(360deg); + transform: rotate(360deg); +} + /* LAYOUTS MODAL */ diff --git a/server/index.js b/server/index.js index fa7044b..5c14d9d 100644 --- a/server/index.js +++ b/server/index.js @@ -151,9 +151,9 @@ site.route = function () { app.post('/api/media/upload', middleware.ensureAuthenticated, api.media.upload) app.delete('/api/media/destroy', middleware.ensureAuthenticated, api.media.destroy) - app.get('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.sync) app.get('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.show) app.put('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.update) + app.put('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.sync) app.delete('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.destroy) app.get('/partials/plans', views.partials.plans) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 9c77dfc..4ec7709 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -8,7 +8,9 @@ var _ = require('lodash'), Project = require('../schemas/Project'), Layout = require('../schemas/Layout'), Plan = require('../schemas/Plan'); - Subscription = require('../schemas/Subscription'); + Subscription = require('../schemas/Subscription'), + Recurly = require('node-recurly'), + recurly = new Recurly(require('../webhook/recurly-config')); var plan_levels = { free: 0, diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index cc296f6..cfd5728 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -12,6 +12,7 @@ consider upgrading to a paid plan.

      +


    • Your current plan level is @@ -43,6 +44,7 @@
    • +
      -- cgit v1.2.3-70-g09d2 From 682b96ebb7210858e26157d1367b75efde9119e2 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 30 Jan 2015 18:11:55 -0500 Subject: follow links in profile brochure --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 9 ++++++--- public/assets/stylesheets/app.css | 12 ++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 1637e18..b38894d 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -1,5 +1,5 @@ -var EditSubscriptionModal = ModalFormView.extend({ +var EditSubscriptionModal = ModalView.extend({ el: ".mediaDrawer.editSubscription", action: "/api/subscription", syncAction: "/api/subscription/sync", @@ -13,6 +13,7 @@ var EditSubscriptionModal = ModalFormView.extend({ "click [data-role='upgradeSubscription']": 'upgradeSubscription', "click [data-role='cancelSubscription']": 'cancelSubscription', "click .gear": 'sync', + "click .planList button": 'followLink', }, initialize: function(){ @@ -54,7 +55,6 @@ var EditSubscriptionModal = ModalFormView.extend({ loaded: false, load: function(){ - this.reset() if (this.loaded) { return this.show() } $.get(this.action, this.didLoad.bind(this)) }, @@ -70,7 +70,10 @@ var EditSubscriptionModal = ModalFormView.extend({ } return this.show() }, - + followLink: function(e){ + e.preventDefault(); + window.location.href = $(e.target).closest("a").attr("href") + }, show: function(){ this.$gear.removeClass("turning") diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 981869b..4826aef 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -989,8 +989,16 @@ iframe.embed { } .editSubscription .gear.turning { opacity: 0.3; - -webkit-transform: rotate(360deg); - transform: rotate(360deg); + -webkit-animation: gear 1s; + animation: gear 1s; +} +@-webkit-keyframes gear { + from { transform: rotate(0deg); } + to { transform: rotate(720deg); } +} +@keyframes gear { + from { transform: rotate(0deg); } + to { transform: rotate(720deg); } } -- cgit v1.2.3-70-g09d2 From 9e8364dd574c02c8a5605c3b09c0230a5476f9b1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 30 Jan 2015 18:30:37 -0500 Subject: sync working --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 1 + server/index.js | 2 +- server/lib/api/subscription.js | 9 +++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index b38894d..28d699c 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -60,6 +60,7 @@ var EditSubscriptionModal = ModalView.extend({ }, didLoad: function(data){ this.loaded = true + console.log("didLoad", data) this.plans = data.plans if (data.subscription) { this.subscriber = data.subscription diff --git a/server/index.js b/server/index.js index 5c14d9d..9f28f59 100644 --- a/server/index.js +++ b/server/index.js @@ -153,7 +153,7 @@ site.route = function () { app.get('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.show) app.put('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.update) - app.put('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.sync) + app.put('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.sync) app.delete('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.destroy) app.get('/partials/plans', views.partials.plans) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 4ec7709..0801204 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -41,8 +41,9 @@ var subscription = module.exports = { sync: function(req, res){ var subscriber = req.subscription || new Subscription () var user = req.user - recurly.subscriptions.listByAccount(req.user._id, function(data){ - if (data.description !== 200) { + recurly.subscriptions.listByAccount(req.user._id, function(recurlyRes){ + var data = recurlyRes.data + if (recurlyRes.description !== 200) { res.json({ error: "no account" }) return } @@ -87,8 +88,8 @@ var subscription = module.exports = { subscriber.save(function(){ user.save(function(){ - res.render({ - subscription: req.subscription, + res.json({ + subscription: subscriber, plans: res.locals.plans }) }) -- cgit v1.2.3-70-g09d2 From 18c81b8a5c8ac4b6d9cbc16e370fcc37e9138cd6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 30 Jan 2015 19:04:31 -0500 Subject: styling form --- .../javascripts/ui/site/EditSubscriptionModal.js | 4 ++-- public/assets/stylesheets/app.css | 27 ++++++++++++++++++++++ views/partials/edit-subscription.ejs | 27 ++++++++++++---------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 28d699c..0d54d8f 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -30,7 +30,7 @@ var EditSubscriptionModal = ModalView.extend({ this.$billingInterval = this.$("[data-role=billingInterval]") - this.$planType = this.$("[data-role=planType]") + this.$planName = this.$("[data-role=planName]") this.$planCost = this.$("[data-role=planCost]") this.$planTotal = this.$("[data-role=planTotal]") @@ -114,7 +114,7 @@ var EditSubscriptionModal = ModalView.extend({ var plan = this.plans[ this.plan_levels[ subscriber.plan_type ] ] var totals = this.calculateTotals(subscriber, plan) - this.$planType.html ( plan.name ) + this.$planName.html ( plan.name ) this.$planCost.toDollars ( totals.plan_price ) this.$billingInterval.html ( totals.is_monthly ? "mo." : "yr." ) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 4826aef..bedf2c4 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1000,6 +1000,33 @@ iframe.embed { from { transform: rotate(0deg); } to { transform: rotate(720deg); } } +.paidPlan { + text-align: left; + font-size: 14px; +} +.planInfo { + margin: 10px 0; + width: 100%; + padding: 0; +} +.planInfo td, .planInfo th { + text-align: left; + padding: 10px 3px; + margin: 0; +} +.planInfo td:nth-child(2), +.planInfo th:nth-child(2), +.planInfo td:nth-child(3), +.planInfo td:nth-child(4), +.planInfo th:nth-child(3) { + text-align: right; +} +.planInfo [data-role="billingInterval"] { + font-size: 10px; +} +.totalRow td:nth-child(4) { + border-top: 1px solid; +} /* LAYOUTS MODAL */ diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index cfd5728..266d43b 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -16,29 +16,32 @@
    • Your current plan level is - +
      - + - + + - + - - + + - + - - + + + - - - + + + +
      @ $/$/
      Additional Basic layoutsAdditional Basic layouts @ $/$each $/$/ Buy more
      Additional Pro layoutsAdditional Pro layouts @ $/$@ $ ...$/Buy more
      Total$Total$/
      -- cgit v1.2.3-70-g09d2 From 6a9418a4256c04c327262947f0fee3b615c93029 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 30 Jan 2015 20:27:42 -0500 Subject: buttonz --- .../javascripts/ui/site/EditSubscriptionModal.js | 7 ++++--- public/assets/stylesheets/app.css | 23 ++++++++++++++++++++-- views/partials/edit-subscription.ejs | 5 ++--- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 0d54d8f..6823740 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -10,7 +10,8 @@ var EditSubscriptionModal = ModalView.extend({ subscriber: null, events: { - "click [data-role='upgradeSubscription']": 'upgradeSubscription', + "click [data-role='addLayouts']": 'addLayouts', + "click [data-role='changePlan']": 'changePlan', "click [data-role='cancelSubscription']": 'cancelSubscription', "click .gear": 'sync', "click .planList button": 'followLink', @@ -141,11 +142,11 @@ var EditSubscriptionModal = ModalView.extend({ }) }, - update: function(){ + update: function(data){ $.ajax({ url: this.updateAction, type: "put", - data: { _csrf: this.$csrf.val() }, + data: { _csrf: $("[name=_csrf]").val() }, success: function(data){ } }) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index bedf2c4..2570bb2 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -985,12 +985,15 @@ iframe.embed { left: 10px; opacity: 0.1; cursor: pointer; + -webkit-transition: all 0.3s; + -webkit-transform-origin: 49% 53%; transition: all 0.3s; + transform-origin: 49% 53%; } .editSubscription .gear.turning { opacity: 0.3; - -webkit-animation: gear 1s; - animation: gear 1s; + -webkit-animation: gear 1s infinite linear; + animation: gear 1s infinite linear; } @-webkit-keyframes gear { from { transform: rotate(0deg); } @@ -1027,6 +1030,22 @@ iframe.embed { .totalRow td:nth-child(4) { border-top: 1px solid; } +.paidPlan button { + width: 200px; + float: none; + margin: 5px 7px; +} +.paidPlan [data-role="cancelSubscription"] { + color: red; + width: 200px; + float: none; +} +.paidPlan [data-role="cancelSubscription"]:hover { + color: white; + background: red; + border-color: red; +} + /* LAYOUTS MODAL */ diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 266d43b..8599fb5 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -28,14 +28,12 @@
    • each $/ $/Buy more
      Additional Pro layouts @ $ ... $/Buy more
      $/
      - + +
    • -- cgit v1.2.3-70-g09d2 From d08c86d68ceb22665b735054fc3bc316f85f84c1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 08:51:55 -0500 Subject: billing link in footer --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 12 ++++++++++-- server/lib/auth/index.js | 4 ++-- views/partials/footer.ejs | 6 ++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 6823740..82f6903 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -12,7 +12,7 @@ var EditSubscriptionModal = ModalView.extend({ events: { "click [data-role='addLayouts']": 'addLayouts', "click [data-role='changePlan']": 'changePlan', - "click [data-role='cancelSubscription']": 'cancelSubscription', + "click [data-role='cancelSubscription']": 'destroy', "click .gear": 'sync', "click .planList button": 'followLink', }, @@ -132,6 +132,13 @@ var EditSubscriptionModal = ModalView.extend({ this.$planTotal.toDollars ( totals.plan_total ) }, + addLayouts: function(e){ + e.preventDefault() + }, + changePlan: function(e){ + e.preventDefault() + }, + sync: function(){ this.$gear.addClass("turning") $.ajax({ @@ -152,7 +159,8 @@ var EditSubscriptionModal = ModalView.extend({ }) }, - destroy: function(){ + destroy: function(e){ + e.preventDefault() var msg = "Are you sure you want to cancel your subscription?" ConfirmModal.confirm(msg, function(){ $.ajax({ diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js index a9a2400..199377d 100644 --- a/server/lib/auth/index.js +++ b/server/lib/auth/index.js @@ -135,12 +135,12 @@ var auth = { deserializeUser: function (id, done) { try { var _id = mongoose.Types.ObjectId(id) - User.findOne({ _id: _id }, "_id displayName username photo isStaff", function (err, user) { + User.findOne({ _id: _id }, "_id displayName username photo isStaff plan_level", function (err, user) { done(err, user); }); } catch (e) { - User.findOne({ twitter_id: id }, "_id displayName username photo isStaff", function (err, user) { + User.findOne({ twitter_id: id }, "_id displayName username photo isStaff plan_level", function (err, user) { done(err, user); }); } diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index e3c572f..8a95fc4 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -15,6 +15,12 @@ About How To + + [[ if (logged_in && user.plan_level > 0) { ]] + Billing + [[ } else { ]] + Subscribe + [[ } ]] Terms Privacy Contact -- cgit v1.2.3-70-g09d2 From af230e59ec431c9b617b0caf94dc7c37bb5e81af Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 09:16:27 -0500 Subject: handle cancelled subscription --- .../javascripts/ui/site/EditSubscriptionModal.js | 5 +- server/index.js | 2 +- server/lib/api/subscription.js | 78 +++++++++++++--------- server/lib/schemas/Subscription.js | 2 +- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 82f6903..7dd527a 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -61,7 +61,6 @@ var EditSubscriptionModal = ModalView.extend({ }, didLoad: function(data){ this.loaded = true - console.log("didLoad", data) this.plans = data.plans if (data.subscription) { this.subscriber = data.subscription @@ -163,11 +162,13 @@ var EditSubscriptionModal = ModalView.extend({ e.preventDefault() var msg = "Are you sure you want to cancel your subscription?" ConfirmModal.confirm(msg, function(){ + this.__super__.show.call(this) $.ajax({ url: this.destroyAction, type: "delete", - data: { _csrf: this.$csrf.val() }, + data: { _csrf: $("[name=_csrf]").val() }, success: function(data){ + window.location.href = "/" } }) }.bind(this)) diff --git a/server/index.js b/server/index.js index 9f28f59..3572675 100644 --- a/server/index.js +++ b/server/index.js @@ -154,7 +154,7 @@ site.route = function () { app.get('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.show) app.put('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.update) app.put('/api/subscription/sync', middleware.ensureAuthenticated, api.subscription.middleware.ensurePlans, api.subscription.middleware.ensureSubscription, api.subscription.sync) - app.delete('/api/subscription', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.destroy) + app.delete('/api/subscription/destroy', middleware.ensureAuthenticated, api.subscription.middleware.ensureSubscription, api.subscription.destroy) app.get('/partials/plans', views.partials.plans) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 0801204..285ce8b 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -51,40 +51,51 @@ var subscription = module.exports = { res.json({ error: "account error" }) return } + if (subscriber.state != "active") { + user.plan_type = "free" + user.plan_level = plan_levels["free"] - var plan = data.subscriptions.subscription.plan.plan_code.split("-") - var plan_type = plan[0] - var plan_period = plan[1] - - user.plan_type = plan_type - user.plan_level = plan_levels[plan_type] + return subscriber.remove(function(){ + user.save(function(){ + res.json({ error: "account cancelled" }) + }) + }) + } + else { + var plan = data.subscriptions.subscription.plan.plan_code.split("-") + var plan_type = plan[0] + var plan_period = plan[1] + + user.plan_type = plan_type + user.plan_level = plan_levels[plan_type] - subscriber.uuid = data.subscriptions.subscription.uuid - subscriber.user_id = user._id - subscriber.plan_type = plan_type - subscriber.plan_period = plan_period - subscriber.plan_level = plan_levels[plan_type] - - var add_ons = data.subscriptions.subscription.subscription_add_ons.subscription_add_on - if (add_ons) { - if (add_ons.add_on_code) { - add_ons = [ add_ons ] - } - // TODO: handle multiple add-ons.. presumably this will work - add_ons.forEach(function(add_on){ - var add_on_type = add_on.add_on_code.split("-")[1] - if (add_on_type == "basic") { - subscriber.basic_layouts = parseInt( add_on.quantity._ ) - } - if (add_on_type == "pro") { - subscriber.pro_layouts = parseInt( add_on.quantity._ ) - } - }) - } - else { - subscriber.basic_layouts = 0 - subscriber.pro_layouts = 0 - } + subscriber.uuid = data.subscriptions.subscription.uuid + subscriber.user_id = user._id + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = plan_levels[plan_type] + + var add_ons = data.subscriptions.subscription.subscription_add_ons.subscription_add_on + if (add_ons) { + if (add_ons.add_on_code) { + add_ons = [ add_ons ] + } + // TODO: handle multiple add-ons.. presumably this will work + add_ons.forEach(function(add_on){ + var add_on_type = add_on.add_on_code.split("-")[1] + if (add_on_type == "basic") { + subscriber.basic_layouts = parseInt( add_on.quantity._ ) + } + if (add_on_type == "pro") { + subscriber.pro_layouts = parseInt( add_on.quantity._ ) + } + }) + } + else { + subscriber.basic_layouts = 0 + subscriber.pro_layouts = 0 + } + } subscriber.save(function(){ user.save(function(){ @@ -156,6 +167,9 @@ var subscription = module.exports = { subscriber.remove(function(){ req.user.plan_code = 0 req.user.plan_type = "free" + req.user.save(function(){ + res.json({ status: "OK" }) + }) }) }) }, diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index 44455a9..355bbe2 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -12,7 +12,7 @@ var SubscriptionSchema = new mongoose.Schema({ plan_type: { type: String, default: "free" }, plan_period: { type: String, default: "monthly" }, - subscription_uuid: { type: String }, + uuid: { type: String }, basic_layouts: { type: Number, default: 0 }, pro_layouts: { type: Number, default: 0 }, -- cgit v1.2.3-70-g09d2 From 8a2125b84b04335920b91eed03ecdb38a9f9e3c0 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 09:48:35 -0500 Subject: should terminate to get rid of the old subscription --- server/lib/api/subscription.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 285ce8b..a3baf34 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -163,7 +163,7 @@ var subscription = module.exports = { } var subscriber = req.subscription - recurly.subscriptions.cancel(subscriber.uuid, function(){ + recurly.subscriptions.terminate(subscriber.uuid, "partial", function(){ subscriber.remove(function(){ req.user.plan_code = 0 req.user.plan_type = "free" -- cgit v1.2.3-70-g09d2 From 6113063fa350114af8f39b87e96cc2c321bc2629 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 10:10:27 -0500 Subject: handle syncing when an account has been cancelled and recreated --- server/lib/api/subscription.js | 109 +++++++++++++++++++---------------- views/partials/edit-subscription.ejs | 2 +- 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index a3baf34..b8853e6 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -47,65 +47,72 @@ var subscription = module.exports = { res.json({ error: "no account" }) return } - if (! data.subscriptions.subscription) { - res.json({ error: "account error" }) - return - } - if (subscriber.state != "active") { - user.plan_type = "free" - user.plan_level = plan_levels["free"] + var subscriptions = data.subscriptions.subscription.length ? data.subscriptions.subscription : [data.subscriptions.subscription] + var is_active = subscriptions.some(function(subscription_data){ + if (subscription_data.state == "active") { + set_active(subscription_data) + return true + } + return false + }) + console.log(data.subscriptions) + if (! is_active) { + set_cancelled() + } + }) + function set_cancelled(){ + user.plan_type = "free" + user.plan_level = plan_levels["free"] - return subscriber.remove(function(){ - user.save(function(){ - res.json({ error: "account cancelled" }) - }) + return subscriber.remove(function(){ + user.save(function(){ + res.json({ error: "account cancelled" }) }) - } - else { - var plan = data.subscriptions.subscription.plan.plan_code.split("-") - var plan_type = plan[0] - var plan_period = plan[1] - - user.plan_type = plan_type - user.plan_level = plan_levels[plan_type] + }) + } + function set_active(data){ + var plan = data.plan.plan_code.split("-") + var plan_type = plan[0] + var plan_period = plan[1] + + user.plan_type = plan_type + user.plan_level = plan_levels[plan_type] - subscriber.uuid = data.subscriptions.subscription.uuid - subscriber.user_id = user._id - subscriber.plan_type = plan_type - subscriber.plan_period = plan_period - subscriber.plan_level = plan_levels[plan_type] - - var add_ons = data.subscriptions.subscription.subscription_add_ons.subscription_add_on - if (add_ons) { - if (add_ons.add_on_code) { - add_ons = [ add_ons ] - } - // TODO: handle multiple add-ons.. presumably this will work - add_ons.forEach(function(add_on){ - var add_on_type = add_on.add_on_code.split("-")[1] - if (add_on_type == "basic") { - subscriber.basic_layouts = parseInt( add_on.quantity._ ) - } - if (add_on_type == "pro") { - subscriber.pro_layouts = parseInt( add_on.quantity._ ) - } - }) - } - else { - subscriber.basic_layouts = 0 - subscriber.pro_layouts = 0 + subscriber.uuid = data.uuid + subscriber.user_id = user._id + subscriber.plan_type = plan_type + subscriber.plan_period = plan_period + subscriber.plan_level = plan_levels[plan_type] + + var add_ons = data.subscription_add_ons.subscription_add_on + if (add_ons) { + if (add_ons.add_on_code) { + add_ons = [ add_ons ] } + // TODO: handle multiple add-ons.. presumably this will work + add_ons.forEach(function(add_on){ + var add_on_type = add_on.add_on_code.split("-")[1] + if (add_on_type == "basic") { + subscriber.basic_layouts = parseInt( add_on.quantity._ ) + } + if (add_on_type == "pro") { + subscriber.pro_layouts = parseInt( add_on.quantity._ ) + } + }) + } + else { + subscriber.basic_layouts = 0 + subscriber.pro_layouts = 0 } - - subscriber.save(function(){ - user.save(function(){ - res.json({ + subscriber.save(function(){ + user.save(function(){ + res.json({ subscription: subscriber, plans: res.locals.plans }) - }) - }) - }) + }) + }) + } }, show: function(req, res){ diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 8599fb5..69ec88d 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -42,7 +42,7 @@ $/ - + -- cgit v1.2.3-70-g09d2 From 85728db4898e88592d9e89510bf121de91e59a6f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 10:17:12 -0500 Subject: .. --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 5 ++--- server/lib/api/subscription.js | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 7dd527a..0f72995 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -162,14 +162,13 @@ var EditSubscriptionModal = ModalView.extend({ e.preventDefault() var msg = "Are you sure you want to cancel your subscription?" ConfirmModal.confirm(msg, function(){ - this.__super__.show.call(this) $.ajax({ url: this.destroyAction, type: "delete", data: { _csrf: $("[name=_csrf]").val() }, success: function(data){ - window.location.href = "/" - } + this.didLoad(data) + }.bind(this) }) }.bind(this)) }, diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index b8853e6..3a8403f 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -55,7 +55,6 @@ var subscription = module.exports = { } return false }) - console.log(data.subscriptions) if (! is_active) { set_cancelled() } -- cgit v1.2.3-70-g09d2 From 4d0a9b9402b0ba1b5d50ba27106541e4e4dbe19f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 15:29:37 -0500 Subject: css --- public/assets/stylesheets/app.css | 56 ++++++++++++++++++++++----------------- views/about/_plans.ejs | 2 +- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 2570bb2..082a2d4 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -904,30 +904,6 @@ iframe.embed { /* PLANS BROCHURE */ /* nb these styles should be fixed for narrower screens/mobile layout */ -.planList { - position: absolute; - left: 50%; - transform: translateX(-48%); -} -.planList .about_custom { - width: 56vw; - margin: 1vw 4vw; -} -.planList .planbox { - padding: 0; -} -.mediaDrawer .planList h3 { - margin-top: 3px; - font-size: 21px; - font-weight: bold -} -.freePlan { - text-align: left; -} -.planList .planbox li:first-child { - font-size: 1.9vw; - padding: 0; -} .about_plan { width: 28vw; margin: 2vw; @@ -979,6 +955,38 @@ iframe.embed { .about_custom a { border-bottom: 1px solid; } + +/* Billing / Subscription Settings */ +.planList { + position: absolute; + left: 50%; + transform: translateX(-48%); +} +.planList .about_custom { + width: 56vw; + margin: 1vw 4vw; +} +.planList .planbox { + padding: 0; +} +.planList .custombox { + margin: 2vw 4vw 4vw 4vw; +} +.planList .miscbox { + line-height: 2.7vw; +} +.mediaDrawer .planList h3 { + margin-top: 3px; + font-size: 21px; + font-weight: bold +} +.freePlan { + text-align: left; +} +.planList .planbox li:first-child { + font-size: 1.9vw; + padding: 0; +} .editSubscription .gear { position: absolute; top: 10px; diff --git a/views/about/_plans.ejs b/views/about/_plans.ejs index 1536ac3..abd6aaa 100644 --- a/views/about/_plans.ejs +++ b/views/about/_plans.ejs @@ -56,7 +56,7 @@
    -
    +

    Want Something Custom?

  • We offer customized white-label options for business and educational uses.
  • Contact us for more information. -- cgit v1.2.3-70-g09d2 From ef52758ef0c27760a93ca861f1d17259dbc40fc4 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 31 Jan 2015 19:10:24 -0500 Subject: adding radio buttons etc --- .../javascripts/ui/site/EditSubscriptionModal.js | 31 +++++++++++++++++-- public/assets/stylesheets/app.css | 11 +++++-- server/index.js | 2 +- server/lib/api/subscription.js | 2 +- views/partials/edit-subscription.ejs | 35 +++++++++++++++++----- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 0f72995..619bff8 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -35,6 +35,11 @@ var EditSubscriptionModal = ModalView.extend({ this.$planCost = this.$("[data-role=planCost]") this.$planTotal = this.$("[data-role=planTotal]") + this.$basicPlanName = this.$("[data-role=basicPlanName]") + this.$proPlanName = this.$("[data-role=proPlanName]") + this.$basicPlanCost = this.$("[data-role=basicPlanCost]") + this.$proPlanCost = this.$("[data-role=proPlanCost]") + this.$basicLayoutCost = this.$("[data-role=basicLayoutCost]") this.$basicLayoutQuantity = this.$("[data-role=basicLayoutQuantity]") this.$basicLayoutTotal = this.$("[data-role=basicLayoutTotal]") @@ -43,8 +48,24 @@ var EditSubscriptionModal = ModalView.extend({ this.$proLayoutQuantity = this.$("[data-role=proLayoutQuantity]") this.$proLayoutTotal = this.$("[data-role=proLayoutTotal]") + this.$showLayoutsMenu = this.$("[data-role=showLayoutsMenu]") + this.$showPlanMenu = this.$("[data-role=showPlanMenu]") + + this.$layoutsMenu = this.$("[data-role=layoutsMenu]") + this.$planMenu = this.$("[data-role=planMenu]") + this.$closeMenu = this.$("[data-role=closeMenu]") + + this.$buyLayouts = this.$("[data-role=buyLayouts]") + + this.$changePlan = this.$("[data-role=changePlan]") + + this.$basicLayoutInput = this.$("[data-role=basicLayoutInput]") + this.$proLayoutInput = this.$("[data-role=proLayoutInput]") + this.$planRadio = this.$("[name=planRadio]") + this.$upgradeSubscription = this.$("[data-role=upgradeSubscription]") this.$cancelSubscription = this.$("[data-role=cancelSubscription]") + this.$gear = this.$(".gear") }, @@ -100,7 +121,7 @@ var EditSubscriptionModal = ModalView.extend({ var t = {} t.is_pro = plan.name == "pro" t.is_monthly = subscriber.plan_period == "monthly" - t.plan_price = t.is_monthly ? plan.monthly_price : plan.yearly_price + t.plan_price = t.is_monthly ? plan.basic_layout_monthly_price : plan.yearly_price t.basic_layout_price = t.is_monthly ? plan.basic_layout_monthly_price : plan.basic_layout_yearly_price t.basic_layout_total = subscriber.basic_layouts * t.basic_layout_price t.pro_layout_price = t.is_monthly ? plan.pro_layout_monthly_price : plan.pro_layout_yearly_price @@ -113,12 +134,18 @@ var EditSubscriptionModal = ModalView.extend({ var subscriber = this.subscriber var plan = this.plans[ this.plan_levels[ subscriber.plan_type ] ] var totals = this.calculateTotals(subscriber, plan) + + this.$basicPlanName.html ( this.plans[1].name ) + this.$proPlanName.html ( this.plans[2].name ) + this.$basicPlanCost.toDollars ( totals.is_monthly ? this.plans[1].monthly_price : this.plans[2].yearly_price) + this.$proPlanCost.toDollars ( totals.is_monthly ? this.plans[2].monthly_price : this.plans[2].yearly_price) this.$planName.html ( plan.name ) this.$planCost.toDollars ( totals.plan_price ) this.$billingInterval.html ( totals.is_monthly ? "mo." : "yr." ) - this.$proLayoutRow.toggle ( totals.is_pro ) + this.$basicLayoutRow.toggle ( subscriber.basic_layouts > 0 ) + this.$proLayoutRow.toggle ( totals.is_pro && subscriber.pro_layouts > 0) this.$basicLayoutCost.toDollars ( totals.basic_layout_price ) this.$basicLayoutQuantity.html ( subscriber.basic_layouts ) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 082a2d4..4144b8b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -987,6 +987,8 @@ iframe.embed { font-size: 1.9vw; padding: 0; } + +/* debug sync button */ .editSubscription .gear { position: absolute; top: 10px; @@ -1053,8 +1055,13 @@ iframe.embed { background: red; border-color: red; } - - +/* purchase mode */ +.paidPlan input[type=number] { display: none } +.paidPlan.editing input[type=number] { display: inline-block } +.paidPlan.editing input[type=number]+span { display: none } +form .paidPlan div { float: none; } +form .paidPlan label { float: none; font-size: 2vw; margin: 0 10px; } +.paidPlan .upgradeMenu div { padding: 5px 10px; } /* LAYOUTS MODAL */ diff --git a/server/index.js b/server/index.js index 3572675..8c8212f 100644 --- a/server/index.js +++ b/server/index.js @@ -72,7 +72,7 @@ site.setup = function(){ server = http.createServer(app) server.listen(app.get('port'), function () { - console.log('Vvalls server listening on port ' + app.get('port')); + console.log('VValls server listening on port ' + app.get('port')); }); // var io = websocket.listen(server) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 3a8403f..6f08e66 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -28,7 +28,7 @@ var subscription = module.exports = { }) }, ensurePlans: function(req, res, next){ - Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { + Plan.find({}).sort({ 'level': 1 }).exec(function (err, plans) { res.locals.plans = (plans || []) next() }) diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 69ec88d..fcb4b94 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -8,13 +8,13 @@

    Edit Subscription

  • - You are currently using the free version of Vvalls. For access to all of Vvalls features, + You are currently using the free version of VValls. For access to all of VValls features, consider upgrading to a paid plan.




  • -
  • +
  • Your current plan level is @@ -25,13 +25,13 @@ - + - + @@ -42,9 +42,30 @@
    Additional Basic layouts each $/ $/
    Additional Pro layouts @ $ ... $/
    $/
    - - - +
    + + + +
    +
    + + +
    +
    +

    Select desired plan:

    +
    + + + $/ +
    +
    + + + $/ +
    + + +
  • -- cgit v1.2.3-70-g09d2 From a7be7295ae568bee76f18e3cf1228168b265db76 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 14:32:25 -0500 Subject: setting up events --- .../javascripts/ui/site/EditSubscriptionModal.js | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 619bff8..af3b99e 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -15,14 +15,30 @@ var EditSubscriptionModal = ModalView.extend({ "click [data-role='cancelSubscription']": 'destroy', "click .gear": 'sync', "click .planList button": 'followLink', + + "click [data-role=showLayoutsMenu]": "layoutsMode", + "click [data-role=showPlanMenu]": "planMode", + + "click [data-role=closeMenu]": "reset", + + "input [data-role=basicLayoutInput]": "updateQuantity", + "input [data-role=proLayoutInput]": "updateQuantity", + "click [data-role=buyLayouts]": "saveLayouts", + + "input [name=planRadio]": "updatePlan", + "click [data-role=changePlan]": "savePlan", }, initialize: function(){ // this.parent = opt.parent this.__super__.initialize.call(this) + // two sections this.$freePlan = this.$(".freePlan") this.$paidPlan = this.$(".paidPlan") + + // subscription table + this.$planInfo = this.$(".planInfo") this.$planRow = this.$(".planRow") this.$basicLayoutRow = this.$(".basicLayoutRow") this.$proLayoutRow = this.$(".proLayoutRow") @@ -31,15 +47,18 @@ var EditSubscriptionModal = ModalView.extend({ this.$billingInterval = this.$("[data-role=billingInterval]") + // plan stuff this.$planName = this.$("[data-role=planName]") this.$planCost = this.$("[data-role=planCost]") this.$planTotal = this.$("[data-role=planTotal]") this.$basicPlanName = this.$("[data-role=basicPlanName]") - this.$proPlanName = this.$("[data-role=proPlanName]") this.$basicPlanCost = this.$("[data-role=basicPlanCost]") + + this.$proPlanName = this.$("[data-role=proPlanName]") this.$proPlanCost = this.$("[data-role=proPlanCost]") + // basic + pro layout stuff this.$basicLayoutCost = this.$("[data-role=basicLayoutCost]") this.$basicLayoutQuantity = this.$("[data-role=basicLayoutQuantity]") this.$basicLayoutTotal = this.$("[data-role=basicLayoutTotal]") @@ -48,24 +67,24 @@ var EditSubscriptionModal = ModalView.extend({ this.$proLayoutQuantity = this.$("[data-role=proLayoutQuantity]") this.$proLayoutTotal = this.$("[data-role=proLayoutTotal]") + // menus.. main menu this.$showLayoutsMenu = this.$("[data-role=showLayoutsMenu]") this.$showPlanMenu = this.$("[data-role=showPlanMenu]") + this.$cancelSubscription = this.$("[data-role=cancelSubscription]") + // three submenus this.$layoutsMenu = this.$("[data-role=layoutsMenu]") this.$planMenu = this.$("[data-role=planMenu]") - this.$closeMenu = this.$("[data-role=closeMenu]") this.$buyLayouts = this.$("[data-role=buyLayouts]") - + this.$closeMenu = this.$("[data-role=closeMenu]") this.$changePlan = this.$("[data-role=changePlan]") + // input fields this.$basicLayoutInput = this.$("[data-role=basicLayoutInput]") this.$proLayoutInput = this.$("[data-role=proLayoutInput]") this.$planRadio = this.$("[name=planRadio]") - this.$upgradeSubscription = this.$("[data-role=upgradeSubscription]") - this.$cancelSubscription = this.$("[data-role=cancelSubscription]") - this.$gear = this.$(".gear") }, @@ -112,11 +131,15 @@ var EditSubscriptionModal = ModalView.extend({ this.$freePlan.hide() this.$paidPlan.show() - this.updateTotals() + this.reset() this.__super__.show.call(this) }, - + reset: function(){ + var subscriber = this.subscriber + var plan = this.plans[ this.plan_levels[ subscriber.plan_type ] ] + this.displayTotals(subscriber) + }, calculateTotals: function(subscriber, plan){ var t = {} t.is_pro = plan.name == "pro" @@ -129,10 +152,7 @@ var EditSubscriptionModal = ModalView.extend({ t.plan_total = t.plan_price + t.basic_layout_total + t.pro_layout_total return t }, - - updateTotals: function(){ - var subscriber = this.subscriber - var plan = this.plans[ this.plan_levels[ subscriber.plan_type ] ] + displayTotals: function(subscriber, plan){ var totals = this.calculateTotals(subscriber, plan) this.$basicPlanName.html ( this.plans[1].name ) -- cgit v1.2.3-70-g09d2 From 97e7312439b24bfdd255f6868e8b42c469b0b38e Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 14:49:10 -0500 Subject: basic ui --- .../javascripts/ui/site/EditSubscriptionModal.js | 60 ++++++++++++++++++++-- public/assets/stylesheets/app.css | 10 +++- views/partials/edit-subscription.ejs | 4 +- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index af3b99e..539a8ae 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -8,6 +8,7 @@ var EditSubscriptionModal = ModalView.extend({ fixedClose: true, subscriber: null, + tempSubscriber: null, events: { "click [data-role='addLayouts']": 'addLayouts', @@ -19,16 +20,62 @@ var EditSubscriptionModal = ModalView.extend({ "click [data-role=showLayoutsMenu]": "layoutsMode", "click [data-role=showPlanMenu]": "planMode", - "click [data-role=closeMenu]": "reset", + "click [data-role=closeMenu]": "resetMode", "input [data-role=basicLayoutInput]": "updateQuantity", "input [data-role=proLayoutInput]": "updateQuantity", - "click [data-role=buyLayouts]": "saveLayouts", + "click [data-role=saveQuantity]": "saveQuantity", "input [name=planRadio]": "updatePlan", "click [data-role=changePlan]": "savePlan", }, - + + resetMode: function(e){ + e.preventDefault() + this.$paidPlan.removeClass("editLayouts editPlan") + this.reset() + }, + + layoutsMode: function(e){ + e.preventDefault() + this.$paidPlan.addClass("editLayouts") + this.tempSubscriber = defaults({}, this.subscriber) + this.$basicLayoutInput.val( this.subscriber.basic_layouts ) + this.$proLayoutInput.val( this.subscriber.pro_layouts ) + }, + updateQuantity: function(e){ + e.preventDefault() + this.tempSubscriber.basic_layouts = this.$proLayoutInput.int() + this.tempSubscriber.pro_layouts = this.$basicLayoutInput.int() + + var plan = this.getPlan( this.tempSubscriber.plan_type ) + this.displayTotals(this.tempSubscriber, plan) + }, + saveQuantity: function(e){ + e.preventDefault() + // blabla.. save + this.subscriber = this.tempSubscriber + this.resetMode() + }, + + planMode: function(e){ + e.preventDefault() + this.$paidPlan.addClass("editPlan") + this.$planRadio.val( this.subscriber.plan_type ) + this.tempSubscriber = defaults({}, this.subscriber) + }, + updatePlan: function(e){ + e.preventDefault() + var plan = this.getPlan( this.$("[name=planRadio]").val() ) + this.displayTotals(this.tempSubscriber, plan) + }, + savePlan: function(e){ + e.preventDefault() + this.subscriber.plan_type = this.$("[name=planRadio]").val() + this.subscriber = this.tempSubscriber + this.resetMode() + }, + initialize: function(){ // this.parent = opt.parent this.__super__.initialize.call(this) @@ -137,8 +184,11 @@ var EditSubscriptionModal = ModalView.extend({ }, reset: function(){ var subscriber = this.subscriber - var plan = this.plans[ this.plan_levels[ subscriber.plan_type ] ] - this.displayTotals(subscriber) + var plan = this.getPlan(subscriber.plan_type) + this.displayTotals(subscriber, plan) + }, + getPlan: function(plan_type){ + return this.plans[ this.plan_levels[ plan_type ] ] }, calculateTotals: function(subscriber, plan){ var t = {} diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 4144b8b..b3d380c 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1057,11 +1057,17 @@ iframe.embed { } /* purchase mode */ .paidPlan input[type=number] { display: none } -.paidPlan.editing input[type=number] { display: inline-block } -.paidPlan.editing input[type=number]+span { display: none } form .paidPlan div { float: none; } form .paidPlan label { float: none; font-size: 2vw; margin: 0 10px; } .paidPlan .upgradeMenu div { padding: 5px 10px; } +.paidPlan .layoutsMenu { display: none } +.paidPlan .planMenu { display: none } +.paidPlan.editLayouts .layoutsMenu { display: block } +.paidPlan.editLayouts .billingMenu { display: none } +.paidPlan.editLayouts input[type=number] { display: inline-block } +.paidPlan.editLayouts input[type=number]+span { display: none } +.paidPlan.editPlan .planMenu { display: block } +.paidPlan.editPlan .billingMenu { display: none } /* LAYOUTS MODAL */ diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index fcb4b94..086f513 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -48,7 +48,7 @@
    - +
    @@ -63,7 +63,7 @@ $/
    - +
    -- cgit v1.2.3-70-g09d2 From bc843c0c65d9ff98dac35a72821f7e312dc7e62b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 15:31:44 -0500 Subject: let confirmModal take two callbacks --- public/assets/javascripts/ui/lib/ConfirmModal.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/public/assets/javascripts/ui/lib/ConfirmModal.js b/public/assets/javascripts/ui/lib/ConfirmModal.js index a72b31e..7d9da67 100644 --- a/public/assets/javascripts/ui/lib/ConfirmModal.js +++ b/public/assets/javascripts/ui/lib/ConfirmModal.js @@ -4,21 +4,31 @@ var ConfirmModal = new( ModalFormView.extend({ el: ".mediaDrawer.confirm", events: { - "click .yes": "advance", - "click .no": "hide", + "click .yes": "agree", + "click .no": "cancel", }, - confirm: function(question, callback){ + confirm: function(question, agreeCallback, cancelCallback){ this.$(".question").empty().append(question) - this.callback = callback + this.agreeCallback = agreeCallback + this.cancelCallback = cancelCallback this.show() }, - advance: function(e){ + agree: function(e){ e && e.preventDefault() this.hide() - this.callback && this.callback() - this.callback = null + this.agreeCallback && this.agreeCallback() + this.agreeCallback = null + this.cancelCallback = null + }, + + cancel: function(e){ + e && e.preventDefault() + this.hide() + this.cancelCallback && this.cancelCallback() + this.agreeCallback = null + this.cancelCallback = null } }) ) \ No newline at end of file -- cgit v1.2.3-70-g09d2 From fbf637f2210d281c8c6f41b72cf50746939a8ece Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 15:32:01 -0500 Subject: edit layout counts --- .../javascripts/ui/site/EditSubscriptionModal.js | 24 +++++++++++++--------- public/assets/stylesheets/app.css | 13 ++++++++++-- views/partials/edit-subscription.ejs | 4 ++-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 539a8ae..fe93499 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -31,46 +31,50 @@ var EditSubscriptionModal = ModalView.extend({ }, resetMode: function(e){ - e.preventDefault() + e && e.preventDefault() this.$paidPlan.removeClass("editLayouts editPlan") this.reset() }, layoutsMode: function(e){ - e.preventDefault() + e && e.preventDefault() this.$paidPlan.addClass("editLayouts") this.tempSubscriber = defaults({}, this.subscriber) this.$basicLayoutInput.val( this.subscriber.basic_layouts ) this.$proLayoutInput.val( this.subscriber.pro_layouts ) + this.$basicLayoutRow.show() + this.$proLayoutRow.toggle(this.subscriber.plan_name == "pro") }, updateQuantity: function(e){ - e.preventDefault() - this.tempSubscriber.basic_layouts = this.$proLayoutInput.int() - this.tempSubscriber.pro_layouts = this.$basicLayoutInput.int() + e && e.preventDefault() + this.tempSubscriber.basic_layouts = this.$basicLayoutInput.int() + this.tempSubscriber.pro_layouts = this.$proLayoutInput.int() var plan = this.getPlan( this.tempSubscriber.plan_type ) this.displayTotals(this.tempSubscriber, plan) + this.$basicLayoutRow.show() + this.$proLayoutRow.toggle(plan.name == "pro") }, saveQuantity: function(e){ - e.preventDefault() + e && e.preventDefault() // blabla.. save this.subscriber = this.tempSubscriber this.resetMode() }, planMode: function(e){ - e.preventDefault() + e && e.preventDefault() this.$paidPlan.addClass("editPlan") this.$planRadio.val( this.subscriber.plan_type ) this.tempSubscriber = defaults({}, this.subscriber) }, updatePlan: function(e){ - e.preventDefault() + e && e.preventDefault() var plan = this.getPlan( this.$("[name=planRadio]").val() ) this.displayTotals(this.tempSubscriber, plan) }, savePlan: function(e){ - e.preventDefault() + e && e.preventDefault() this.subscriber.plan_type = this.$("[name=planRadio]").val() this.subscriber = this.tempSubscriber this.resetMode() @@ -178,7 +182,7 @@ var EditSubscriptionModal = ModalView.extend({ this.$freePlan.hide() this.$paidPlan.show() - this.reset() + this.resetMode() this.__super__.show.call(this) }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index b3d380c..b58bb01 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1027,6 +1027,10 @@ iframe.embed { padding: 10px 3px; margin: 0; } +.planInfo td { + height: 60px; + vertical-align: middle; +} .planInfo td:nth-child(2), .planInfo th:nth-child(2), .planInfo td:nth-child(3), @@ -1034,6 +1038,10 @@ iframe.embed { .planInfo th:nth-child(3) { text-align: right; } +.planInfo td:nth-child(4) { + width: 90px; +} + .planInfo [data-role="billingInterval"] { font-size: 10px; } @@ -1046,7 +1054,8 @@ iframe.embed { margin: 5px 7px; } .paidPlan [data-role="cancelSubscription"] { - color: red; + color: #800; + border-color: black; width: 200px; float: none; } @@ -1056,7 +1065,7 @@ iframe.embed { border-color: red; } /* purchase mode */ -.paidPlan input[type=number] { display: none } +.paidPlan input[type=number] { display: none; float: right; } form .paidPlan div { float: none; } form .paidPlan label { float: none; font-size: 2vw; margin: 0 10px; } .paidPlan .upgradeMenu div { padding: 5px 10px; } diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 086f513..19f6851 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -43,8 +43,8 @@
    - - +
    +
    -- cgit v1.2.3-70-g09d2 From 60aa806d65a90907c6a76cb017c167c8453260b3 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 16:58:58 -0500 Subject: plan val from radio button --- .../javascripts/ui/site/EditSubscriptionModal.js | 110 ++++++++++----------- views/partials/edit-subscription.ejs | 4 +- 2 files changed, 56 insertions(+), 58 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index fe93499..b9abd75 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -26,60 +26,10 @@ var EditSubscriptionModal = ModalView.extend({ "input [data-role=proLayoutInput]": "updateQuantity", "click [data-role=saveQuantity]": "saveQuantity", - "input [name=planRadio]": "updatePlan", + "change [name=planRadio]": "updatePlan", "click [data-role=changePlan]": "savePlan", }, - resetMode: function(e){ - e && e.preventDefault() - this.$paidPlan.removeClass("editLayouts editPlan") - this.reset() - }, - - layoutsMode: function(e){ - e && e.preventDefault() - this.$paidPlan.addClass("editLayouts") - this.tempSubscriber = defaults({}, this.subscriber) - this.$basicLayoutInput.val( this.subscriber.basic_layouts ) - this.$proLayoutInput.val( this.subscriber.pro_layouts ) - this.$basicLayoutRow.show() - this.$proLayoutRow.toggle(this.subscriber.plan_name == "pro") - }, - updateQuantity: function(e){ - e && e.preventDefault() - this.tempSubscriber.basic_layouts = this.$basicLayoutInput.int() - this.tempSubscriber.pro_layouts = this.$proLayoutInput.int() - - var plan = this.getPlan( this.tempSubscriber.plan_type ) - this.displayTotals(this.tempSubscriber, plan) - this.$basicLayoutRow.show() - this.$proLayoutRow.toggle(plan.name == "pro") - }, - saveQuantity: function(e){ - e && e.preventDefault() - // blabla.. save - this.subscriber = this.tempSubscriber - this.resetMode() - }, - - planMode: function(e){ - e && e.preventDefault() - this.$paidPlan.addClass("editPlan") - this.$planRadio.val( this.subscriber.plan_type ) - this.tempSubscriber = defaults({}, this.subscriber) - }, - updatePlan: function(e){ - e && e.preventDefault() - var plan = this.getPlan( this.$("[name=planRadio]").val() ) - this.displayTotals(this.tempSubscriber, plan) - }, - savePlan: function(e){ - e && e.preventDefault() - this.subscriber.plan_type = this.$("[name=planRadio]").val() - this.subscriber = this.tempSubscriber - this.resetMode() - }, - initialize: function(){ // this.parent = opt.parent this.__super__.initialize.call(this) @@ -135,6 +85,8 @@ var EditSubscriptionModal = ModalView.extend({ this.$basicLayoutInput = this.$("[data-role=basicLayoutInput]") this.$proLayoutInput = this.$("[data-role=proLayoutInput]") this.$planRadio = this.$("[name=planRadio]") + this.$basicPlanInput = this.$("[data-role=basicPlanInput]") + this.$proPlanInput = this.$("[data-role=proPlanInput]") this.$gear = this.$(".gear") }, @@ -198,7 +150,7 @@ var EditSubscriptionModal = ModalView.extend({ var t = {} t.is_pro = plan.name == "pro" t.is_monthly = subscriber.plan_period == "monthly" - t.plan_price = t.is_monthly ? plan.basic_layout_monthly_price : plan.yearly_price + t.plan_price = t.is_monthly ? plan.monthly_price : plan.yearly_price t.basic_layout_price = t.is_monthly ? plan.basic_layout_monthly_price : plan.basic_layout_yearly_price t.basic_layout_total = subscriber.basic_layouts * t.basic_layout_price t.pro_layout_price = t.is_monthly ? plan.pro_layout_monthly_price : plan.pro_layout_yearly_price @@ -232,13 +184,59 @@ var EditSubscriptionModal = ModalView.extend({ this.$planTotal.toDollars ( totals.plan_total ) }, - addLayouts: function(e){ - e.preventDefault() + resetMode: function(e){ + e && e.preventDefault() + this.$paidPlan.removeClass("editLayouts editPlan") + this.reset() }, - changePlan: function(e){ - e.preventDefault() + + layoutsMode: function(e){ + e && e.preventDefault() + this.$paidPlan.addClass("editLayouts") + this.tempSubscriber = defaults({}, this.subscriber) + this.$basicLayoutInput.val( this.subscriber.basic_layouts ) + this.$proLayoutInput.val( this.subscriber.pro_layouts ) + this.$basicLayoutRow.show() + this.$proLayoutRow.toggle(this.subscriber.plan_name == "pro") + }, + updateQuantity: function(e){ + e && e.preventDefault() + var plan = this.getPlan( this.tempSubscriber.plan_type ) + this.tempSubscriber.basic_layouts = this.$basicLayoutInput.int() + this.tempSubscriber.pro_layouts = this.$proLayoutInput.int() + this.displayTotals(this.tempSubscriber, plan) + this.$basicLayoutRow.show() + this.$proLayoutRow.toggle(plan.name == "pro") + }, + saveQuantity: function(e){ + e && e.preventDefault() + this.subscriber = this.tempSubscriber + this.resetMode() + // blabla.. save }, + planMode: function(e){ + e && e.preventDefault() + this.$paidPlan.addClass("editPlan") + switch (this.subscriber.plan_type) { + case 'basic': this.$basicPlanInput.prop('checked', true); break; + case 'pro': this.$proPlanInput.prop('checked', true); break; + } + this.tempSubscriber = defaults({}, this.subscriber) + }, + updatePlan: function(e){ + e && e.preventDefault() + var plan_type = this.$("[name=planRadio]:checked").val() + var plan = this.getPlan( plan_type ) + this.displayTotals(this.tempSubscriber, plan) + }, + savePlan: function(e){ + e && e.preventDefault() + this.subscriber.plan_type = this.$("[name=planRadio]:checked").val() + this.subscriber = this.tempSubscriber + this.resetMode() + // blabla.. save + }, sync: function(){ this.$gear.addClass("turning") $.ajax({ diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 19f6851..e651187 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -54,12 +54,12 @@

    Select desired plan:

    - + $/
    - + $/
    -- cgit v1.2.3-70-g09d2 From 003f59d687d8d3d5e4e9c4a2eeb1bb167753d0c9 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 18:22:28 -0500 Subject: check form input --- .../javascripts/ui/site/EditSubscriptionModal.js | 18 +++++++++++------- views/partials/edit-subscription.ejs | 6 +++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index b9abd75..384460d 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -27,7 +27,9 @@ var EditSubscriptionModal = ModalView.extend({ "click [data-role=saveQuantity]": "saveQuantity", "change [name=planRadio]": "updatePlan", - "click [data-role=changePlan]": "savePlan", + "click [data-role=savePlan]": "savePlan", + + "submit form": "preventDefault", }, initialize: function(){ @@ -148,7 +150,7 @@ var EditSubscriptionModal = ModalView.extend({ }, calculateTotals: function(subscriber, plan){ var t = {} - t.is_pro = plan.name == "pro" + t.is_pro = subscriber.plan_type == "pro" t.is_monthly = subscriber.plan_period == "monthly" t.plan_price = t.is_monthly ? plan.monthly_price : plan.yearly_price t.basic_layout_price = t.is_monthly ? plan.basic_layout_monthly_price : plan.basic_layout_yearly_price @@ -197,16 +199,19 @@ var EditSubscriptionModal = ModalView.extend({ this.$basicLayoutInput.val( this.subscriber.basic_layouts ) this.$proLayoutInput.val( this.subscriber.pro_layouts ) this.$basicLayoutRow.show() - this.$proLayoutRow.toggle(this.subscriber.plan_name == "pro") + this.$proLayoutRow.toggle(this.subscriber.plan_type == "pro") }, updateQuantity: function(e){ e && e.preventDefault() var plan = this.getPlan( this.tempSubscriber.plan_type ) - this.tempSubscriber.basic_layouts = this.$basicLayoutInput.int() - this.tempSubscriber.pro_layouts = this.$proLayoutInput.int() + this.tempSubscriber.basic_layouts = clamp( this.$basicLayoutInput.int() || 0, 0, 100) + this.tempSubscriber.pro_layouts = clamp( this.$proLayoutInput.int() || 0, 0, 100) + + this.$basicLayoutInput.val(this.tempSubscriber.basic_layouts) + this.$proLayoutInput.val(this.tempSubscriber.pro_layouts) this.displayTotals(this.tempSubscriber, plan) this.$basicLayoutRow.show() - this.$proLayoutRow.toggle(plan.name == "pro") + this.$proLayoutRow.toggle(this.tempSubscriber.plan_type == "pro") }, saveQuantity: function(e){ e && e.preventDefault() @@ -233,7 +238,6 @@ var EditSubscriptionModal = ModalView.extend({ savePlan: function(e){ e && e.preventDefault() this.subscriber.plan_type = this.$("[name=planRadio]:checked").val() - this.subscriber = this.tempSubscriber this.resetMode() // blabla.. save }, diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index e651187..1b0fc41 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -32,7 +32,7 @@ Additional Pro layouts - @ $ ... + each $/ $/ @@ -43,12 +43,12 @@
    -
    +

    - +
    -- cgit v1.2.3-70-g09d2 From 3f0ef2173b6d00ae8130b3125b63f3d9ad9e98de Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 18:48:08 -0500 Subject: make it 1 action --- .../javascripts/ui/site/EditSubscriptionModal.js | 57 ++++++++++------------ public/assets/stylesheets/app.css | 14 +++--- views/partials/edit-subscription.ejs | 43 ++++++++-------- 3 files changed, 56 insertions(+), 58 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 384460d..6e5dc9e 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -7,6 +7,7 @@ var EditSubscriptionModal = ModalView.extend({ destroyAction: "/api/subscription/destroy", fixedClose: true, + editing: false, subscriber: null, tempSubscriber: null, @@ -17,14 +18,13 @@ var EditSubscriptionModal = ModalView.extend({ "click .gear": 'sync', "click .planList button": 'followLink', - "click [data-role=showLayoutsMenu]": "layoutsMode", - "click [data-role=showPlanMenu]": "planMode", + "click [data-role=showEditMenu]": "editMode", "click [data-role=closeMenu]": "resetMode", "input [data-role=basicLayoutInput]": "updateQuantity", "input [data-role=proLayoutInput]": "updateQuantity", - "click [data-role=saveQuantity]": "saveQuantity", + "click [data-role=saveChanges]": "saveChanges", "change [name=planRadio]": "updatePlan", "click [data-role=savePlan]": "savePlan", @@ -186,21 +186,28 @@ var EditSubscriptionModal = ModalView.extend({ this.$planTotal.toDollars ( totals.plan_total ) }, - resetMode: function(e){ - e && e.preventDefault() - this.$paidPlan.removeClass("editLayouts editPlan") - this.reset() - }, - - layoutsMode: function(e){ + editMode: function(e){ e && e.preventDefault() - this.$paidPlan.addClass("editLayouts") + + this.editing = true + this.$el.addClass("editing") this.tempSubscriber = defaults({}, this.subscriber) this.$basicLayoutInput.val( this.subscriber.basic_layouts ) this.$proLayoutInput.val( this.subscriber.pro_layouts ) this.$basicLayoutRow.show() this.$proLayoutRow.toggle(this.subscriber.plan_type == "pro") + switch (this.subscriber.plan_type) { + case 'basic': this.$basicPlanInput.prop('checked', true); break; + case 'pro': this.$proPlanInput.prop('checked', true); break; + } }, + resetMode: function(e){ + e && e.preventDefault() + this.editing = false + this.$el.removeClass("editing") + this.reset() + }, + updateQuantity: function(e){ e && e.preventDefault() var plan = this.getPlan( this.tempSubscriber.plan_type ) @@ -213,34 +220,24 @@ var EditSubscriptionModal = ModalView.extend({ this.$basicLayoutRow.show() this.$proLayoutRow.toggle(this.tempSubscriber.plan_type == "pro") }, - saveQuantity: function(e){ + saveChanges: function(e){ e && e.preventDefault() + if (this.tempSubscriber.plan_type != this.subscriber.plan_type + || this.tempSubscriber.basic_layouts != this.subscriber.basic_layouts + || this.tempSubscriber.pro_layouts != this.subscriber.pro_layouts) { + // update plan_type + } this.subscriber = this.tempSubscriber this.resetMode() // blabla.. save }, - planMode: function(e){ - e && e.preventDefault() - this.$paidPlan.addClass("editPlan") - switch (this.subscriber.plan_type) { - case 'basic': this.$basicPlanInput.prop('checked', true); break; - case 'pro': this.$proPlanInput.prop('checked', true); break; - } - this.tempSubscriber = defaults({}, this.subscriber) - }, updatePlan: function(e){ e && e.preventDefault() - var plan_type = this.$("[name=planRadio]:checked").val() - var plan = this.getPlan( plan_type ) - this.displayTotals(this.tempSubscriber, plan) - }, - savePlan: function(e){ - e && e.preventDefault() - this.subscriber.plan_type = this.$("[name=planRadio]:checked").val() - this.resetMode() - // blabla.. save + this.tempSubscriber.plan_type = this.$("[name=planRadio]:checked").val() + this.updateQuantity() }, + sync: function(){ this.$gear.addClass("turning") $.ajax({ diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index b58bb01..ffb133d 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1071,12 +1071,14 @@ form .paidPlan label { float: none; font-size: 2vw; margin: 0 10px; } .paidPlan .upgradeMenu div { padding: 5px 10px; } .paidPlan .layoutsMenu { display: none } .paidPlan .planMenu { display: none } -.paidPlan.editLayouts .layoutsMenu { display: block } -.paidPlan.editLayouts .billingMenu { display: none } -.paidPlan.editLayouts input[type=number] { display: inline-block } -.paidPlan.editLayouts input[type=number]+span { display: none } -.paidPlan.editPlan .planMenu { display: block } -.paidPlan.editPlan .billingMenu { display: none } + +.editing .section_break { display: none } +.editing .paidPlan .currentPlanLevel { display: none } +.editing .paidPlan .billingMenu { display: none } +.editing .paidPlan .layoutsMenu { display: block } +.editing .paidPlan .planMenu { display: block } +.editing .paidPlan input[type=number] { display: inline-block } +.editing .paidPlan input[type=number]+span { display: none } /* LAYOUTS MODAL */ diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 1b0fc41..38c6dfc 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -14,8 +14,23 @@



    -
  • - Your current plan level is +
  • +
    + Your current plan level is +
    +
    +

    Select desired plan:

    +
    + + + $/ +
    +
    + + + $/ +
    +
    @@ -24,13 +39,13 @@ - + - + @@ -43,27 +58,11 @@
    $/
    Additional Basic layoutsBasic layouts each $/ $/
    Additional Pro layoutsPro layouts each $/ $/
    -
    -
    +
    - - -
    -
    -

    Select desired plan:

    -
    - - - $/ -
    -
    - - - $/ -
    - +
  • -- cgit v1.2.3-70-g09d2 From d45c7f3c6e5a05a263f4a58dea83f2d578013f12 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 18:49:29 -0500 Subject: save changes on profile --- views/partials/edit-profile.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/partials/edit-profile.ejs b/views/partials/edit-profile.ejs index 5775ca5..5720bc8 100644 --- a/views/partials/edit-profile.ejs +++ b/views/partials/edit-profile.ejs @@ -83,7 +83,7 @@
  • - +
  • There was a problem with your submission:
    -- cgit v1.2.3-70-g09d2 From 9e40939c50cf098e88f7d66f85bd925fcc9d01e4 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 18:52:32 -0500 Subject: space for blabitybla text --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 8 +++++--- public/assets/stylesheets/app.css | 5 +++-- views/partials/edit-subscription.ejs | 7 ++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 6e5dc9e..cd3d1bb 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -71,12 +71,11 @@ var EditSubscriptionModal = ModalView.extend({ this.$proLayoutTotal = this.$("[data-role=proLayoutTotal]") // menus.. main menu - this.$showLayoutsMenu = this.$("[data-role=showLayoutsMenu]") - this.$showPlanMenu = this.$("[data-role=showPlanMenu]") + this.$showEditMenu = this.$("[data-role=showEditMenu]") this.$cancelSubscription = this.$("[data-role=cancelSubscription]") // three submenus - this.$layoutsMenu = this.$("[data-role=layoutsMenu]") + this.$editMenu = this.$("[data-role=editMenu]") this.$planMenu = this.$("[data-role=planMenu]") this.$buyLayouts = this.$("[data-role=buyLayouts]") @@ -270,6 +269,9 @@ var EditSubscriptionModal = ModalView.extend({ this.didLoad(data) }.bind(this) }) + }.bind(this), + function(){ + this.show() }.bind(this)) }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index ffb133d..7c49ed1 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1069,17 +1069,18 @@ iframe.embed { form .paidPlan div { float: none; } form .paidPlan label { float: none; font-size: 2vw; margin: 0 10px; } .paidPlan .upgradeMenu div { padding: 5px 10px; } -.paidPlan .layoutsMenu { display: none } +.paidPlan .editMenu { display: none } .paidPlan .planMenu { display: none } .editing .section_break { display: none } .editing .paidPlan .currentPlanLevel { display: none } .editing .paidPlan .billingMenu { display: none } -.editing .paidPlan .layoutsMenu { display: block } +.editing .paidPlan .editMenu { display: block } .editing .paidPlan .planMenu { display: block } .editing .paidPlan input[type=number] { display: inline-block } .editing .paidPlan input[type=number]+span { display: none } +.editMenu .fineprint { font-size: 12px; width: auto; text-align: justify; } /* LAYOUTS MODAL */ .templates { diff --git a/views/partials/edit-subscription.ejs b/views/partials/edit-subscription.ejs index 38c6dfc..f3c3589 100644 --- a/views/partials/edit-subscription.ejs +++ b/views/partials/edit-subscription.ejs @@ -61,7 +61,12 @@
    -
    +
    +
    + Your credit card will be charged the difference of XXXX for this month. + Your subscription will renew at XXXX at the start of your next billing cycle. + We thank you for your support! +
    -- cgit v1.2.3-70-g09d2 From 7a23f57b1ef3e9ceca414d909aa15a7d5ea6d536 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 20:46:42 -0500 Subject: hitting update api --- .../javascripts/ui/site/EditSubscriptionModal.js | 25 ++++++++++++++++------ server/lib/api/subscription.js | 20 ++++++++--------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index cd3d1bb..3bc1a24 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -221,14 +221,21 @@ var EditSubscriptionModal = ModalView.extend({ }, saveChanges: function(e){ e && e.preventDefault() - if (this.tempSubscriber.plan_type != this.subscriber.plan_type - || this.tempSubscriber.basic_layouts != this.subscriber.basic_layouts - || this.tempSubscriber.pro_layouts != this.subscriber.pro_layouts) { - // update plan_type + var is_changed = false + var diff = {} + "plan_type basic_layouts pro_layouts".split(" ").forEach(function(field){ + if (this.tempSubscriber[field] != this.subscriber[field]) { + diff[field] = this.tempSubscriber[field] + is_changed = true + } + }.bind(this)) + + if (is_changed) { + diff.plan_type = this.tempSubscriber.plan_type + this.update(diff) } this.subscriber = this.tempSubscriber this.resetMode() - // blabla.. save }, updatePlan: function(e){ @@ -248,12 +255,16 @@ var EditSubscriptionModal = ModalView.extend({ }, update: function(data){ + data['_csrf'] = $("[name=_csrf]").val() + this.$gear.addClass("turning") $.ajax({ url: this.updateAction, type: "put", - data: { _csrf: $("[name=_csrf]").val() }, + data: data, success: function(data){ - } + console.log("SUCCESS") + this.$gear.removeClass("turning") + }.bind(this) }) }, diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 6f08e66..362d633 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -138,26 +138,26 @@ var subscription = module.exports = { } var subscriber = req.subscription - // change.. - // data.plan_code - // data.subscription_add_ons = [] - // add_on.add_on_code - // add_on.quantity - var basic_layouts = max(0, parseInt(req.body.basic_layouts)) - var pro_layouts = max(0, parseInt(req.body.pro_layouts)) + var plan_type = req.body.plan_type + var basic_layouts = Math.max(0, parseInt(req.body.basic_layouts, 10)) + var pro_layouts = Math.max(0, parseInt(req.body.pro_layouts, 10)) var data = {} - data.plan_code = req.body.plan_type + "_monthly" + data.plan_code = plan_type + "_monthly" data.subscription_add_ons = [] - if (plan_levels[req.body.plan_type]) { + if (plan_levels[plan_type] > 0) { data.subscription_add_ons.push({ add_on_code: "extra-basic-layout", quantity: basic_layouts }) } - if (req.body.plan_type == "pro") { + if (plan_type == "pro") { data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts }) } + // data.plan_code + // data.subscription_add_ons = [] + // add_on.add_on_code + // add_on.quantity recurly.subscriptions.update(subscriber.uuid, data, function(){ return res.json(subscriber) }) -- cgit v1.2.3-70-g09d2 From a5c5fa85c85fc31bebae1917ceeac4f8e1e383d5 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sun, 1 Feb 2015 22:02:52 -0500 Subject: talking to recurly --- package.json | 2 +- .../javascripts/ui/site/EditSubscriptionModal.js | 1 - server/lib/api/subscription.js | 32 ++++++++++++++++++---- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index e89fcd9..56ffcdf 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "mongoose-unique-validator": "~0.3.0", "monk": "~0.7.1", "multer": "~0.1.0", - "node-recurly": "^2.1.0", + "node-recurly": "julescarbon/node-recurly", "node-restful": "~0.1.14", "passport": "~0.2.0", "passport-facebook": "~1.0.3", diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 3bc1a24..55ff3b5 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -262,7 +262,6 @@ var EditSubscriptionModal = ModalView.extend({ type: "put", data: data, success: function(data){ - console.log("SUCCESS") this.$gear.removeClass("turning") }.bind(this) }) diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 362d633..7e9221a 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -137,13 +137,20 @@ var subscription = module.exports = { return res.json({ error: "bad input" }) } var subscriber = req.subscription + var user = req.user var plan_type = req.body.plan_type - var basic_layouts = Math.max(0, parseInt(req.body.basic_layouts, 10)) - var pro_layouts = Math.max(0, parseInt(req.body.pro_layouts, 10)) + var basic_layouts = Math.max(0, parseInt(req.body.basic_layouts || 0, 10)) + var pro_layouts = Math.max(0, parseInt(req.body.pro_layouts || 0, 10)) + + if (plan_type == subscription.plan_type + && basic_layouts == subscriber.basic_layouts + && pro_layouts == subscriber.pro_layouts) { + return res.json(subscriber) + } var data = {} - data.plan_code = plan_type + "_monthly" + data.plan_code = plan_type + "-monthly" data.subscription_add_ons = [] if (plan_levels[plan_type] > 0) { @@ -158,8 +165,21 @@ var subscription = module.exports = { // data.subscription_add_ons = [] // add_on.add_on_code // add_on.quantity - recurly.subscriptions.update(subscriber.uuid, data, function(){ - return res.json(subscriber) + recurly.subscriptions.update(subscriber.uuid, data, function(err, data){ + if (err) { + console.log("error updating recurly subscription", err) + return res.json({ error: err }) + } + subscriber.plan_type = plan_type + subscriber.basic_layouts = basic_layouts + subscriber.pro_layouts = pro_layouts + subscriber.save(function(){ + user.plan_level = plan_levels[plan_type] + user.plan_type = plan_type + user.save(function(){ + return res.json(subscriber) + }) + }) }) }, @@ -169,7 +189,7 @@ var subscription = module.exports = { } var subscriber = req.subscription - recurly.subscriptions.terminate(subscriber.uuid, "partial", function(){ + recurly.subscriptions.terminate(subscriber.uuid, "partial", function(err, data){ subscriber.remove(function(){ req.user.plan_code = 0 req.user.plan_type = "free" -- cgit v1.2.3-70-g09d2 From e7ecd5b141945a9c9ca7a57df643eaa3f3fdc3d6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 09:43:06 -0500 Subject: double checking all plan changes.. need to pass full plan info to update --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 3 +-- server/lib/api/subscription.js | 10 ++++++---- views/staff/_nav.ejs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 55ff3b5..c276354 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -224,14 +224,13 @@ var EditSubscriptionModal = ModalView.extend({ var is_changed = false var diff = {} "plan_type basic_layouts pro_layouts".split(" ").forEach(function(field){ + diff[field] = this.tempSubscriber[field] if (this.tempSubscriber[field] != this.subscriber[field]) { - diff[field] = this.tempSubscriber[field] is_changed = true } }.bind(this)) if (is_changed) { - diff.plan_type = this.tempSubscriber.plan_type this.update(diff) } this.subscriber = this.tempSubscriber diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 7e9221a..9c2d6ef 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -142,6 +142,7 @@ var subscription = module.exports = { var plan_type = req.body.plan_type var basic_layouts = Math.max(0, parseInt(req.body.basic_layouts || 0, 10)) var pro_layouts = Math.max(0, parseInt(req.body.pro_layouts || 0, 10)) + if (plan_type != "pro") { pro_layouts = 0 } if (plan_type == subscription.plan_type && basic_layouts == subscriber.basic_layouts @@ -149,15 +150,14 @@ var subscription = module.exports = { return res.json(subscriber) } - var data = {} + var data = { subscription_add_ons: [] } data.plan_code = plan_type + "-monthly" - data.subscription_add_ons = [] - if (plan_levels[plan_type] > 0) { + if (plan_levels[plan_type] > 0 && basic_layouts > 0) { data.subscription_add_ons.push({ add_on_code: "extra-basic-layout", quantity: basic_layouts }) } - if (plan_type == "pro") { + if (plan_type == "pro" && pro_layouts > 0) { data.subscription_add_ons.push({ add_on_code: "extra-pro-layout", quantity: pro_layouts }) } @@ -165,7 +165,9 @@ var subscription = module.exports = { // data.subscription_add_ons = [] // add_on.add_on_code // add_on.quantity + console.log(data) recurly.subscriptions.update(subscriber.uuid, data, function(err, data){ + console.log("got response from RECURLY ...") if (err) { console.log("error updating recurly subscription", err) return res.json({ error: err }) diff --git a/views/staff/_nav.ejs b/views/staff/_nav.ejs index e79ff69..a607638 100644 --- a/views/staff/_nav.ejs +++ b/views/staff/_nav.ejs @@ -4,5 +4,5 @@ projects media plans - subscriptions + \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 95b7043c7bf259da3135652461f80162be432691 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 10:43:46 -0500 Subject: spacing --- config.json.example | 12 ++++++------ public/assets/stylesheets/app.css | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/config.json.example b/config.json.example index dc79edd..7072d48 100644 --- a/config.json.example +++ b/config.json.example @@ -1,9 +1,9 @@ { - "host": "lvh.me:3000", - "hostName": "lvh.me", - "port": 3000, - "socketPort": 1337, - "webhookPort": 5000, + "host": "lvh.me:3000", + "hostName": "lvh.me", + "port": 3000, + "socketPort": 1337, + "webhookPort": 5000, "databaseHost": "lvh.me", - "env": { "development": 1 } + "env": { "development": 1 } } diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 7c49ed1..0a7e24a 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1067,7 +1067,7 @@ iframe.embed { /* purchase mode */ .paidPlan input[type=number] { display: none; float: right; } form .paidPlan div { float: none; } -form .paidPlan label { float: none; font-size: 2vw; margin: 0 10px; } +form .paidPlan label { float: none; font-size: 16px; margin: 0 10px; } .paidPlan .upgradeMenu div { padding: 5px 10px; } .paidPlan .editMenu { display: none } .paidPlan .planMenu { display: none } -- cgit v1.2.3-70-g09d2 From 0cb3f8b480e46a3376b5accba18cde0c3cbdd13d Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 10:53:28 -0500 Subject: bower moved lodash --- Gruntfile.js | 2 +- views/partials/scripts.ejs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index ed236c5..f7af106 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -9,7 +9,7 @@ module.exports = function(grunt) { js: { src: [ "public/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js", - "public/assets/javascripts/vendor/bower_components/lodash/dist/lodash.min.js", + "public/assets/javascripts/vendor/bower_components/lodash/lodash.min.js", "public/assets/javascripts/vendor/bower_components/momentjs/min/moment.min.js", "public/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js", "public/assets/javascripts/vendor/bower_components/marked/lib/marked.js", diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 04bd945..a58eca1 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -2,7 +2,7 @@ [[ } else { ]] - + -- cgit v1.2.3-70-g09d2 From b9ad0704417aaa8cf4da7a1ec2109959622bd454 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 11:31:31 -0500 Subject: setting up staging env --- server/lib/views/staff.js | 3 ++- views/staff/plans/_form.ejs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index 67193fe..c3ecc97 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -728,8 +728,9 @@ var staff = module.exports = { data.name = util.sanitize(data.name) data.slug = util.sanitize(data.slug.toLowerCase()) + data.permissions = {} permissions.forEach(function(field){ - data[field] = data["permissions_" + field] + data.permissions[field] = data["permissions_" + field].length == 2 }) new Plan (data).save(function(err, doc){ diff --git a/views/staff/plans/_form.ejs b/views/staff/plans/_form.ejs index 0240e56..61be7e8 100644 --- a/views/staff/plans/_form.ejs +++ b/views/staff/plans/_form.ejs @@ -100,7 +100,7 @@
  • - +
  • -- cgit v1.2.3-70-g09d2 From 03842d65cc018f9a718b2408d19e978f3d08e042 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 13:23:51 -0500 Subject: sanity --- server/lib/views/index.js | 2 +- server/lib/webhook/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 9f244c8..be46cc6 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -107,7 +107,7 @@ var views = module.exports = { partials: { plans: function (req, res){ views_middleware.ensurePlans(req, res, function(){ - res.render('about/_plans') + res.render('about/_plans', { logged_in: res.locals.logged_in || false }) }) }, }, diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js index 11419c2..798e4be 100644 --- a/server/lib/webhook/index.js +++ b/server/lib/webhook/index.js @@ -37,7 +37,7 @@ site.ready = function(){ console.log('Webhook server listening on port ' + app.get('port')); }); - app.get('/', function(req,res){ res.send('HI THERE') }) + app.get('/', function(req,res){ res.send('hello@vvalls.com') }) webhook.route(app) } -- cgit v1.2.3-70-g09d2 From 466e56bbdcf1b713a91e77081237b3adf0b86ba0 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 13:24:03 -0500 Subject: using xml middleware parser for webhook --- package.json | 1 + server/lib/webhook/index.js | 2 +- server/lib/webhook/webhook.js | 191 +++++++++++++++++++++--------------------- 3 files changed, 99 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 56ffcdf..7a504af 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "express": "~3.4.8", "express-subdomain-handler": "~0.1.0", "express-subdomains": "0.0.5", + "express-xml-bodyparser": "0.0.6", "html-entities": "~1.0.10", "intro.js": "^0.9.0", "js2xml": "^1.0.0", diff --git a/server/lib/webhook/index.js b/server/lib/webhook/index.js index 11419c2..eb6a6b3 100644 --- a/server/lib/webhook/index.js +++ b/server/lib/webhook/index.js @@ -27,7 +27,7 @@ site.init = function(){ site.ready = function(){ app.set('port', config.webhookPort); - app.use(bodyParser()); + // app.use(bodyParser()); app.use(express.query()); app.set('env', config.env.production ? "production" : "development") app.get('env') === 'development' && app.use(express.errorHandler()); diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 4f23d0b..21ff23d 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -12,15 +12,17 @@ app.use(express.basicAuth(function(user, pass, callback) { /* jshint node: true */ var User = require('../schemas/User'), - Subscription = require('../schemas/Subscription'), - config = require('../../../config'), - middleware = require('../middleware'), - util = require('../util'), - _ = require('lodash'), - moment = require('moment'), - xml2js = require('xml2js'), - Recurly = require('node-recurly'), - recurly = new Recurly(require('./recurly-config')); + Subscription = require('../schemas/Subscription'), + config = require('../../../config'), + middleware = require('../middleware'), + util = require('../util'), + _ = require('lodash'), + moment = require('moment'), + xml2js = require('xml2js'), + Recurly = require('node-recurly'), + recurly = new Recurly(require('./recurly-config')); + +var xml_bodyparser = require('express-xml-bodyparser'); var parser = new xml2js.Parser(); @@ -30,34 +32,34 @@ var subscribe = module.exports = { basic: 1, pro: 2, }, - + callbacks: { /* - // accounts - new_account_notification: function(data, user){ - // fires on successful signup - }, - canceled_account_notification: function(data, user){ - }, - billing_info_updated_notification: function(data, user){ - }, - reactivated_account_notification: function(data, user){ - }, - - // invoices - new_invoice_notification: function(data, user){ - }, - closed_invoice_notification: function(data, user){ - }, - past_due_invoice_notification: function(data, user){ - }, + // accounts + new_account_notification: function(data, user){ + // fires on successful signup + }, + canceled_account_notification: function(data, user){ + }, + billing_info_updated_notification: function(data, user){ + }, + reactivated_account_notification: function(data, user){ + }, + + // invoices + new_invoice_notification: function(data, user){ + }, + closed_invoice_notification: function(data, user){ + }, + past_due_invoice_notification: function(data, user){ + }, */ - // subscriptions - new_subscription_notification: function(data, user){ - var account = data.account - Subscription.findOne({ "uuid": data.subscription.uuid }, function(err, subscription){ - if (err || subscription) return; + // subscriptions + new_subscription_notification: function(data, user){ + var account = data.account + Subscription.findOne({ "uuid": data.subscription.uuid }, function(err, subscription){ + if (err || subscription) return; var plan = data.subscription.plan.plan_code.split("-") var plan_type = plan[0] @@ -66,75 +68,76 @@ var subscribe = module.exports = { user.plan_type = plan_type user.plan_level = subscribe.plan_level[plan_type] - var subscriber = new Subscription () + var subscriber = new Subscription () subscriber.uuid = data.subscription.uuid - subscriber.user_id = user._id + subscriber.user_id = user._id subscriber.plan_type = plan_type subscriber.plan_period = plan_period subscriber.plan_level = subscribe.plan_level[plan_type] subscriber.add_ons = subscription.add_ons.map(function(add_on){ - return { - name: add_on.plan, - quantity: add_on.quantity, - } + return { + name: add_on.plan, + quantity: add_on.quantity, + } }) subscriber.save(function(err, data){ - if (err) return; - user.save(function(err){ - // saved! - }) + if (err) return; + user.save(function(err){ + // saved! + }) }) - }) - }, + }) + }, /* - updated_subscription_notification: function(data, user){ - }, - canceled_subscription_notification: function(data, user){ - }, - expired_subscription_notification: function(data, user){ - }, - renewed_subscription_notification: function(data, user){ - }, -*/ - // payments - successful_payment_notification: function(data, user){ - var account = data.account - user.last_charged = new Date(data.transaction.date) - user.save(function(){ - }) - }, + updated_subscription_notification: function(data, user){ + }, + canceled_subscription_notification: function(data, user){ + }, + expired_subscription_notification: function(data, user){ + }, + renewed_subscription_notification: function(data, user){ + }, +*/ + // payments + successful_payment_notification: function(data, user){ + var account = data.account + user.last_charged = new Date(data.transaction.date) + user.save(function(){ + }) + }, /* - failed_payment_notification: function(data, user){ - }, - successful_refund_notification: function(data, user){ - }, - void_payment_notification: function(data, user){ - }, + failed_payment_notification: function(data, user){ + }, + successful_refund_notification: function(data, user){ + }, + void_payment_notification: function(data, user){ + }, */ }, - - execute: function(action, data){ - User.findOne({ _id: data.account.account_code }, function(err, user){ - if (err) { return } - subscribe.callbacks[action](data, user) - }) - }, - + + execute: function(action, data){ + User.findOne({ _id: data.account.account_code }, function(err, user){ + if (err) { return } + subscribe.callbacks[action](data, user) + }) + }, + // then calls to get appropriate info from the recurly api - handle: function(req, res){ - res.status(200).end() - parser.parseString(data, function (err, result) { - console.log(inspect(result, { colors: true, depth: Infinity })); - for (var action in result) { - if (subscribe.callbacks[action]) { - subscribe.execute(action, result[action]); - } - } - }); - }, - - list: function(req, res){ + handle: function(req, res){ + console.log(req.body) + // parser.parseString(req.body, function (err, result) { + var result = req.body + console.log(inspect(result, { colors: true, depth: Infinity })); + for (var action in result) { + if (subscribe.callbacks[action]) { + subscribe.execute(action, result[action]); + return res.status(200).end() + } + } + }, + + list: function(req, res){ recurly.subscriptions.listByAccount(req.params.id, function(data){ if (data.data != 404) { res.json(data) @@ -145,10 +148,10 @@ var subscribe = module.exports = { return } }) - }, - - route: function(app){ - app.post('/subscribe/webhook', subscribe.handle); - app.get('/subscribe/list/:id', subscribe.list); - }, + }, + + route: function(app){ + app.post('/subscribe/webhook', xml_bodyparser(), subscribe.handle); + app.get('/subscribe/list/:id', subscribe.list); + }, } -- cgit v1.2.3-70-g09d2 From cd6b76e4665f37566f08075479d501628f30eb0b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 13:25:16 -0500 Subject: fix template --- views/about/_plans.ejs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/views/about/_plans.ejs b/views/about/_plans.ejs index abd6aaa..16fb9c6 100644 --- a/views/about/_plans.ejs +++ b/views/about/_plans.ejs @@ -19,7 +19,7 @@ [[ } else if (! user.plan_level) { ]] - [[ } else if (user.plan_level == plan.level) { ]] + [[ } else if (user.plan_level == plans.basic.level) { ]] Current Level [[ } ]] @@ -40,9 +40,9 @@ [[ } else if (! user.plan_level) { ]] - [[ } else if (user.plan_level == plan.level) { ]] + [[ } else if (user.plan_level == plans.pro.level) { ]] Current Level - [[ } else if (user.plan_level < plan.level) { ]] + [[ } else if (user.plan_level < plans.pro.level) { ]] [[ } ]] -- cgit v1.2.3-70-g09d2 From 19b74bf938aef3b0c3a35c185d9d1563e773a972 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 13:50:09 -0500 Subject: webhook firing --- package.json | 1 + server/lib/webhook/webhook.js | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 7a504af..69766ce 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "express-subdomains": "0.0.5", "express-xml-bodyparser": "0.0.6", "html-entities": "~1.0.10", + "inspect": "0.0.2", "intro.js": "^0.9.0", "js2xml": "^1.0.0", "knox": "~0.8.10", diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 21ff23d..25e3fb8 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -57,11 +57,13 @@ var subscribe = module.exports = { // subscriptions new_subscription_notification: function(data, user){ - var account = data.account - Subscription.findOne({ "uuid": data.subscription.uuid }, function(err, subscription){ + var account = data.account[0].account_code[0] + var subscrip = data.subscription[0] + var uuid = subscrip.uuid[0] + Subscription.findOne({ "uuid": uuid }, function(err, subscription){ if (err || subscription) return; - var plan = data.subscription.plan.plan_code.split("-") + var plan = subscrip.plan[0].plan_code[0].split("-") var plan_type = plan[0] var plan_period = plan[1] @@ -69,17 +71,25 @@ var subscribe = module.exports = { user.plan_level = subscribe.plan_level[plan_type] var subscriber = new Subscription () - subscriber.uuid = data.subscription.uuid + subscriber.uuid = uuid subscriber.user_id = user._id subscriber.plan_type = plan_type subscriber.plan_period = plan_period subscriber.plan_level = subscribe.plan_level[plan_type] - subscriber.add_ons = subscription.add_ons.map(function(add_on){ - return { - name: add_on.plan, - quantity: add_on.quantity, - } - }) + subscriber.add_ons = [] + var add_ons = subscrip.subscription_add_ons[0].subscription_add_on + if (add_ons) { + add_ons.forEach(function(add_on){ + switch (add_on.add_on_code[0]) { + case 'extra-basic-layout': + subscriber.basic_layouts = parseInt(add_on.quantity[0]._, 10) || 0 + break + case 'extra-pro-layout': + subscriber.pro_layouts = parseInt(add_on.quantity[0]._, 10) || 0 + break + } + }) + } subscriber.save(function(err, data){ if (err) return; user.save(function(err){ @@ -117,7 +127,7 @@ var subscribe = module.exports = { }, execute: function(action, data){ - User.findOne({ _id: data.account.account_code }, function(err, user){ + User.findOne({ _id: data.account[0].account_code[0] }, function(err, user){ if (err) { return } subscribe.callbacks[action](data, user) }) @@ -128,13 +138,12 @@ var subscribe = module.exports = { console.log(req.body) // parser.parseString(req.body, function (err, result) { var result = req.body - console.log(inspect(result, { colors: true, depth: Infinity })); for (var action in result) { if (subscribe.callbacks[action]) { subscribe.execute(action, result[action]); - return res.status(200).end() } } + return res.status(200).end() }, list: function(req, res){ -- cgit v1.2.3-70-g09d2 From 4b6ba728390f3c16c48392beef5cb0b58cbf1763 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 13:57:13 -0500 Subject: null sub --- public/assets/javascripts/ui/site/EditSubscriptionModal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index c276354..3a20234 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -275,6 +275,7 @@ var EditSubscriptionModal = ModalView.extend({ type: "delete", data: { _csrf: $("[name=_csrf]").val() }, success: function(data){ + this.subscriber = null this.didLoad(data) }.bind(this) }) -- cgit v1.2.3-70-g09d2 From 07f648798676d565914dd8e7b1cd78ebfc3b7309 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 13:57:49 -0500 Subject: dont make a million subscriber --- server/lib/webhook/webhook.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 25e3fb8..9e3a4d3 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -60,8 +60,8 @@ var subscribe = module.exports = { var account = data.account[0].account_code[0] var subscrip = data.subscription[0] var uuid = subscrip.uuid[0] - Subscription.findOne({ "uuid": uuid }, function(err, subscription){ - if (err || subscription) return; + Subscription.findOne({ "uuid": uuid }, function(err, old_subscriber){ + // if (err) return; var plan = subscrip.plan[0].plan_code[0].split("-") var plan_type = plan[0] @@ -70,7 +70,7 @@ var subscribe = module.exports = { user.plan_type = plan_type user.plan_level = subscribe.plan_level[plan_type] - var subscriber = new Subscription () + var subscriber = old_subscriber || new Subscription () subscriber.uuid = uuid subscriber.user_id = user._id subscriber.plan_type = plan_type -- cgit v1.2.3-70-g09d2 From 6a4e4d30d5428fd0e629081d6a214e9a618ab52f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 14:05:24 -0500 Subject: css a bit --- public/assets/stylesheets/app.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 0a7e24a..b23b50b 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -942,6 +942,9 @@ iframe.embed { list-style-type: none; margin-bottom: 0; font-size: 1.3vw; + padding: 0 1vw; +} +.paidPlan .planbox li { padding: 0 5.6vw; } .about_custom.planbox li { -- cgit v1.2.3-70-g09d2 From 72754ed88f7dfed9b80f5a46cd11550aac11cf1e Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 15:28:48 -0500 Subject: fix successful_payment_notification --- server/lib/webhook/webhook.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 9e3a4d3..58a13ca 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -1,5 +1,4 @@ // // where should this live? -// app.get('/subscribe/webhook', views.subscription.webhook); /* app.use(express.basicAuth(function(user, pass, callback) { @@ -111,8 +110,8 @@ var subscribe = module.exports = { */ // payments successful_payment_notification: function(data, user){ - var account = data.account - user.last_charged = new Date(data.transaction.date) + var account = data.account[0] + user.last_charged = new Date(data.transaction[0].date[0]._) user.save(function(){ }) }, -- cgit v1.2.3-70-g09d2 From ca838d172cbd7fca1f2cba3bb1f095821710920a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 17:53:16 -0500 Subject: userlist sort --- public/assets/stylesheets/staff.css | 14 ++++++++++++++ server/lib/views/staff.js | 4 +++- views/staff/_users.ejs | 13 +++++++++++++ views/staff/users/show.ejs | 31 ++++++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index fffadbf..d93e46e 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -30,6 +30,15 @@ nav { nav a { margin-left: 10px; } +nav.subnav { + background: white; + padding: 10px; + font-weight: 200; + font-size: 12px; +} +.alphabet a { + margin-left: 5px; +} hr { border: 1px solid #bbb; margin: 10px auto 10px; @@ -62,8 +71,13 @@ hr { user-select: none; } .staff { + background: white; font-size: 15px; } +.staff hr { + border: 1px solid black; + border-top: 0; +} .staff .body a { border-bottom: 1px dotted; } diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index c3ecc97..b772859 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -368,8 +368,10 @@ var staff = module.exports = { helpers: { user: function(user){ + var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) user = user.toObject() - user.last_seen = moment( user.last_seen || user.updated_at || user.created_at ).fromNow() + user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() + user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") user.created_ip = util.num2ip( user.created_ip ) user.last_ip = util.num2ip( user.last_ip ) return user diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index 46811b6..1af47aa 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -1,9 +1,22 @@ + + [[ users.forEach(function(user){ ]] + diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index d6a21d5..e441109 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -17,13 +17,38 @@ [[- profile.displayName ]]
    + [[- user.plan_type ]] + [[- user.last_charged ]] + [[- user.username ]]
    + + [[ if (profile.subscription) { ]] +

    Subscription

    + + + + + + + + + +
    + plan + + [[- profile.plan_type ]] +
    + last charged + + [[- profile.last_charged ]] +
    + [[ } ]] +

    Profile

    -- cgit v1.2.3-70-g09d2 From 1169b347c1f339b64f30466004a3f9a06ef7e117 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 2 Feb 2015 18:16:09 -0500 Subject: find users by initial --- public/assets/stylesheets/staff.css | 8 ++++++++ server/lib/views/staff.js | 12 ++++++++++++ views/staff/_users.ejs | 10 ++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/public/assets/stylesheets/staff.css b/public/assets/stylesheets/staff.css index d93e46e..ebc240a 100644 --- a/public/assets/stylesheets/staff.css +++ b/public/assets/stylesheets/staff.css @@ -39,6 +39,14 @@ nav.subnav { .alphabet a { margin-left: 5px; } +.body .error { + color: #f00; + border: 1px solid #f00; + margin: 20px 5px 200px 5px; + padding: 10px; + width: 400px; + display: inline-block; +} hr { border: 1px solid #bbb; margin: 10px auto 10px; diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js index b772859..07050f1 100644 --- a/server/lib/views/staff.js +++ b/server/lib/views/staff.js @@ -38,6 +38,7 @@ var staff = module.exports = { var criteria = req.criteria || {} var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var initial = util.sanitize(req.query.initial) var sort paginationInfo.sort = req.query.sort paginationInfo.sortOptions = ["date", "last_seen", "username"] @@ -54,6 +55,9 @@ var staff = module.exports = { paginationInfo.sort = "username" break } + if (initial) { + criteria.username = new RegExp('^' + initial, "i") + } User.find(criteria) .select(staff.fields.user) .sort(sort) @@ -61,6 +65,14 @@ var staff = module.exports = { .limit(limit) .exec(function (err, users) { res.locals.users = users.map(staff.helpers.user) + if (! res.locals.users.length) { + if (initial) { + res.locals.opt.error = "No users found starting with " + initial.toUpperCase() + "" + } + else { + res.locals.opt.error = "No users found" + } + } next() }) }, diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index 1af47aa..9caf893 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -1,12 +1,18 @@ +[[ if (! users.length || opt.error) { ]] +
    + [[- opt.error ]] +
    +[[ } ]] +
    [[ users.forEach(function(user){ ]] -- cgit v1.2.3-70-g09d2 From 78620c1451f78bdb470ed89c8a1e5c7a6bb10990 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 3 Feb 2015 13:07:42 -0500 Subject: support basicAuth --- config.json.example | 3 ++- server/index.js | 1 + server/lib/auth/index.js | 9 ++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/config.json.example b/config.json.example index 7072d48..7221aa0 100644 --- a/config.json.example +++ b/config.json.example @@ -5,5 +5,6 @@ "socketPort": 1337, "webhookPort": 5000, "databaseHost": "lvh.me", - "env": { "development": 1 } + "env": { "development": 1 }, + "basicAuth": { "user": "foo", "pass": "bar" } } diff --git a/server/index.js b/server/index.js index 8c8212f..7bc3f7f 100644 --- a/server/index.js +++ b/server/index.js @@ -39,6 +39,7 @@ site.ready = function(){ site.setup = function(){ var SessionStore = new MongoStore({ mongoose_connection: mongoose.connection }) + auth.initBasicAuth(app) app.set('port', config.port); app.set('views', path.join(__dirname, '../views')); app.set('view engine', 'ejs'); diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js index 199377d..8e20bcc 100644 --- a/server/lib/auth/index.js +++ b/server/lib/auth/index.js @@ -39,7 +39,14 @@ var auth = { auth.mail.init() }, - + initBasicAuth: function(app){ + if (config.basicAuth) { + app.use(express.basicAuth(function(user, pass) { + return user === config.basicAuth.user && + pass === config.basicAuth.pass + })) + } + }, initSockets: function (io, SessionStore) { io.set('authorization', passportSocketIo.authorize({ cookieParser: express.cookieParser, -- cgit v1.2.3-70-g09d2 From f51b018fd760d8550a06cb900a1311164ea881ad Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 3 Feb 2015 13:15:58 -0500 Subject: emails --- server/lib/auth/mail.js | 2 +- views/home.ejs | 2 +- views/staff/_users.ejs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/lib/auth/mail.js b/server/lib/auth/mail.js index eac4007..990b53f 100644 --- a/server/lib/auth/mail.js +++ b/server/lib/auth/mail.js @@ -6,7 +6,7 @@ var email = require("emailjs"), var mail = { - from: 'VValls ', + from: 'VValls ', templates: {}, init: function(){ diff --git a/views/home.ejs b/views/home.ejs index ffb0976..20723a5 100755 --- a/views/home.ejs +++ b/views/home.ejs @@ -68,7 +68,7 @@

    Ready To Go Pro?

    Use VValls as part of your product, service, or marketing campaign. We offer many types of customizations, including automation of layouts, more elaborate floor plans, enhanced video, interactivity, and other features. - Contact + Contact [[ include partials/confirm-modal ]] diff --git a/views/staff/_users.ejs b/views/staff/_users.ejs index 9caf893..ee988ab 100644 --- a/views/staff/_users.ejs +++ b/views/staff/_users.ejs @@ -1,5 +1,5 @@
    -[[ layouts.forEach(function(project){ ]] +[[ layouts.forEach(function(layout){ ]]
    [[- layout.name ]] diff --git a/views/staff/layouts/show.ejs b/views/staff/layouts/show.ejs index 0a2014b..b66449f 100644 --- a/views/staff/layouts/show.ejs +++ b/views/staff/layouts/show.ejs @@ -45,14 +45,14 @@ featured? - [[- layout.plan_type == 0 ? "yes" : "no" ]] + [[- layout.is_stock ? "yes" : "no" ]]


    - +

    -- cgit v1.2.3-70-g09d2 From e61e94f5d2f570f0cba3a3f7d91a18d8db524d79 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 10 Aug 2015 20:42:19 -0400 Subject: blueprint upload stuff --- .../javascripts/rectangles/engine/map/_map.js | 2 +- .../javascripts/ui/builder/BlueprintUpload.js | 120 +++++++++++++++++++++ public/assets/stylesheets/app.css | 3 +- public/assets/test/ortho4.html | 43 +++++++- 4 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 public/assets/javascripts/ui/builder/BlueprintUpload.js diff --git a/public/assets/javascripts/rectangles/engine/map/_map.js b/public/assets/javascripts/rectangles/engine/map/_map.js index bf646bb..e3d7621 100644 --- a/public/assets/javascripts/rectangles/engine/map/_map.js +++ b/public/assets/javascripts/rectangles/engine/map/_map.js @@ -44,7 +44,7 @@ var Map = function(opt){ var canvas = base.canvas = document.createElement("canvas") canvas.width = base.dimensions.a canvas.height = base.dimensions.b - + base.el.appendChild(canvas) switch (opt.type) { diff --git a/public/assets/javascripts/ui/builder/BlueprintUpload.js b/public/assets/javascripts/ui/builder/BlueprintUpload.js new file mode 100644 index 0000000..dbc6f12 --- /dev/null +++ b/public/assets/javascripts/ui/builder/BlueprintUpload.js @@ -0,0 +1,120 @@ + +var BlueprintUpload = UploadView.extend({ + el: ".blueprintUpload", + + mediaTag: "blueprint", + createAction: "/api/media/new", + uploadAction: "/api/media/upload", + listAction: "/api/media/user", + destroyAction: "/api/media/destroy", + + events: { + "mousedown": 'stopPropagation', + "change .url": "enterUrl", + "keydown .url": "enterSetUrl", + + "click .blueprint": "choose", + "change [name=blueprint-dimensions]": "changeDimensions", + "change [name=blueprint-units]": "changeUnits", + "click #saveBlueprint": "save", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$url = this.$(".url") + + this.$blueprintMap = this.$("#blueprintMap") + this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") + this.$dimensions = this.$("[name=blueprint-dimensions]") + this.$units = this.$("[name=blueprint-units]") + this.$save = this.$("#saveBlueprint") + + this.map = new Map ({ type: ortho }) + + this.load() + }, + + loaded: false, + load: function(){ + $.get(this.listAction, { tag: this.mediaTag }, this.populate.bind(this)) + }, + + populate: function(data){ + this.loaded = true + if (data && data.length) { + data.forEach(this.append.bind(this)) + this.$(".txt").hide() + } + else { + this.$(".txt").show() + } + }, + + append: function(media){ + var $el = $("
    ") + $el.data("id", media._id) + $el.addClass("blueprint") + this.$blueprints.append($el) + }, + + pick: function(e){ + var $el = $(e.currentTarget) + // load map with it + }, + + destroy: function(_id, cb){ + $.ajax({ + type: "delete", + url: this.destroyAction, + data: { _id: _id, _csrf: $("[name=_csrf]").val() } + }).complete(cb || function(){}) + }, + + show: function(){ + this.toggle(true) + }, + hide: function(){ + this.toggle(false) + }, + toggle: function (state) { + this.$el.toggleClass("active", state) + }, + + addUrl: function (url){ + Parser.loadImage(url, function(media){ + if (! media) return + media._csrf = $("[name=_csrf]").val() + media.tag = this.mediaTag + + var request = $.ajax({ + type: "post", + url: this.createAction, + data: media, + }) + request.done(this.add.bind(this)) + + }.bind(this)) + }, + enterUrl: function(){ + var url = this.$url.sanitize() + this.addUrl(url) + this.$url.val("") + }, + enterSetUrl: function (e) { + e.stopPropagation() + if (e.keyCode == 13) { + setTimeout(this.enterUrl.bind(this), 100) + } + }, + + add: function(media){ + this.append(media) + }, + changeDimensions: function(){ + }, + changeUnits: function(){ + }, + +}) diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 56c65fe..bb32500 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1597,7 +1597,8 @@ form .paidPlan label { float: none; font-size: 16px; margin: 0 10px; } .mediaDrawer.signin, .mediaDrawer.signup, .mediaDrawer.alert, .mediaDrawer.confirm, .mediaDrawer.passwordForgot, .mediaDrawer.passwordReset, .mediaDrawer.usernameTaken, -.mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject { +.mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject, +.mediaDrawer.blueprintUpload { display:table; } .confirm button { diff --git a/public/assets/test/ortho4.html b/public/assets/test/ortho4.html index b434efb..12b6ab2 100644 --- a/public/assets/test/ortho4.html +++ b/public/assets/test/ortho4.html @@ -1,15 +1,19 @@ +
    @@ -47,11 +55,38 @@ body {
    -
    +
    X

    Upload A Room Image

    + +
    +
    +
    + + + +
    +
    + +
    + + Please tell us the scale of your map. + Click both corners of a wall, and then enter how long the wall is. + +
    +
    + +
    + + + + +
    -- cgit v1.2.3-70-g09d2 From 8d749201d661f62766b4e3a84735c3307ff7ab5e Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 11 Aug 2015 13:22:02 -0400 Subject: refactor environment loading --- public/assets/javascripts/app.js | 30 +----- public/assets/javascripts/rectangles/_env.js | 34 +++++- public/assets/javascripts/ui/_router.js | 11 ++ .../javascripts/ui/builder/BlueprintUpload.js | 120 --------------------- public/assets/test/ortho4.html | 9 +- views/modal.ejs | 3 +- views/partials/scripts.ejs | 17 ++- 7 files changed, 68 insertions(+), 156 deletions(-) delete mode 100644 public/assets/javascripts/ui/builder/BlueprintUpload.js diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index 6ebcda5..3cafeca 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -21,40 +21,12 @@ app.init = function () { app.launch = function () { if ($.browser.msie || ! has3d()) { return app.fallback() } - scene = new MX.Scene().addTo('#scene') - scene.width = window.innerWidth - scene.height = window.innerHeight - scene.perspective = window.innerHeight - - window.onresize = function () { - scene.width = window.innerWidth - scene.height = window.innerHeight - scene.perspective = window.innerHeight - scene.update() - } - - cam = scene.camera - cam.y = viewHeight - - if (MX.Map) map = app.map = new MX.Map() - - if (is_mobile) { - app.movements = new MX.MobileMovements(cam, viewHeight) - } - else { - app.movements = new MX.Movements(cam, viewHeight) - } - app.movements.init() - var last_t = 0 function animate (t) { var dt = t - last_t last_t = t requestAnimationFrame(animate) - environment.update(t) - window.path && path.update(t) - app.movements.update(dt || 0) - scene.update() + environment.update(t, dt) } var loader = new Loader(function(){ diff --git a/public/assets/javascripts/rectangles/_env.js b/public/assets/javascripts/rectangles/_env.js index 14f73e3..b3c7d66 100644 --- a/public/assets/javascripts/rectangles/_env.js +++ b/public/assets/javascripts/rectangles/_env.js @@ -1,6 +1,22 @@ var environment = new function(){} environment.init = function(){ + scene = new MX.Scene().addTo('#scene') + scene.width = window.innerWidth + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + cam = scene.camera + cam.y = viewHeight + + if (is_mobile) { + app.movements = new MX.MobileMovements(cam, viewHeight) + } + else { + app.movements = new MX.Movements(cam, viewHeight) + } + app.movements.init() + map = new Map () if (window.scene) { @@ -16,7 +32,14 @@ environment.init = function(){ scene.camera.radius = 20 } - + + window.onresize = function () { + scene.width = window.innerWidth + scene.height = window.innerHeight + scene.perspective = window.innerHeight + scene.update() + } + Rooms.init() Walls.init() Scenery.init() @@ -52,8 +75,13 @@ environment.init = function(){ } }) } -environment.update = function(t){ +environment.minimal = function(){ + environment.update = function(t){} +} +environment.update = function(t, dt){ + app.movements.update(dt || 0) + scene.update() map.update() - window.minimap && window.minimap.update && minimap.update() + window.minimap && minimap.update && minimap.update() z = false } diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 1bdce19..857377c 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -44,6 +44,8 @@ var SiteRouter = Router.extend({ "/project/:name": 'projectViewer', "/project/:name/edit": 'projectEditor', "/project/:name/view": 'projectViewer', + + "/test/blueprint": 'blueprintEditor', }, mobileRoutes: { @@ -157,6 +159,15 @@ var SiteRouter = Router.extend({ this.readerView = app.controller = new ReaderView() this.readerView.load(name) }, + + blueprintEditor: function(e){ + environment.init = environment.minimal + app.launch() + if (app.unsupported) return + + this.blueprintView = app.controller = new BlueprintView () + this.blueprintView.load() + }, signup: function(e){ e && e.preventDefault() diff --git a/public/assets/javascripts/ui/builder/BlueprintUpload.js b/public/assets/javascripts/ui/builder/BlueprintUpload.js deleted file mode 100644 index dbc6f12..0000000 --- a/public/assets/javascripts/ui/builder/BlueprintUpload.js +++ /dev/null @@ -1,120 +0,0 @@ - -var BlueprintUpload = UploadView.extend({ - el: ".blueprintUpload", - - mediaTag: "blueprint", - createAction: "/api/media/new", - uploadAction: "/api/media/upload", - listAction: "/api/media/user", - destroyAction: "/api/media/destroy", - - events: { - "mousedown": 'stopPropagation', - "change .url": "enterUrl", - "keydown .url": "enterSetUrl", - - "click .blueprint": "choose", - "change [name=blueprint-dimensions]": "changeDimensions", - "change [name=blueprint-units]": "changeUnits", - "click #saveBlueprint": "save", - }, - - initialize: function(opt){ - this.parent = opt.parent - this.__super__.initialize.call(this) - - this.$url = this.$(".url") - - this.$blueprintMap = this.$("#blueprintMap") - this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") - this.$dimensions = this.$("[name=blueprint-dimensions]") - this.$units = this.$("[name=blueprint-units]") - this.$save = this.$("#saveBlueprint") - - this.map = new Map ({ type: ortho }) - - this.load() - }, - - loaded: false, - load: function(){ - $.get(this.listAction, { tag: this.mediaTag }, this.populate.bind(this)) - }, - - populate: function(data){ - this.loaded = true - if (data && data.length) { - data.forEach(this.append.bind(this)) - this.$(".txt").hide() - } - else { - this.$(".txt").show() - } - }, - - append: function(media){ - var $el = $("
    ") - $el.data("id", media._id) - $el.addClass("blueprint") - this.$blueprints.append($el) - }, - - pick: function(e){ - var $el = $(e.currentTarget) - // load map with it - }, - - destroy: function(_id, cb){ - $.ajax({ - type: "delete", - url: this.destroyAction, - data: { _id: _id, _csrf: $("[name=_csrf]").val() } - }).complete(cb || function(){}) - }, - - show: function(){ - this.toggle(true) - }, - hide: function(){ - this.toggle(false) - }, - toggle: function (state) { - this.$el.toggleClass("active", state) - }, - - addUrl: function (url){ - Parser.loadImage(url, function(media){ - if (! media) return - media._csrf = $("[name=_csrf]").val() - media.tag = this.mediaTag - - var request = $.ajax({ - type: "post", - url: this.createAction, - data: media, - }) - request.done(this.add.bind(this)) - - }.bind(this)) - }, - enterUrl: function(){ - var url = this.$url.sanitize() - this.addUrl(url) - this.$url.val("") - }, - enterSetUrl: function (e) { - e.stopPropagation() - if (e.keyCode == 13) { - setTimeout(this.enterUrl.bind(this), 100) - } - }, - - add: function(media){ - this.append(media) - }, - changeDimensions: function(){ - }, - changeUnits: function(){ - }, - -}) diff --git a/public/assets/test/ortho4.html b/public/assets/test/ortho4.html index 12b6ab2..1c1adef 100644 --- a/public/assets/test/ortho4.html +++ b/public/assets/test/ortho4.html @@ -91,14 +91,16 @@ body {
    - - + + + + @@ -126,8 +128,10 @@ body { + + + + @@ -79,10 +81,20 @@ + + + + - + + + + + + + @@ -115,6 +127,9 @@ + + + -- cgit v1.2.3-70-g09d2 From b5d2503ec4e5844ab3793c9e48020bcbaef3112b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 11 Aug 2015 13:22:31 -0400 Subject: blueprint integration into views --- .../javascripts/ui/blueprint/BlueprintScale.js | 0 .../javascripts/ui/blueprint/BlueprintUpload.js | 122 +++++++++++++++++++++ .../javascripts/ui/blueprint/BlueprintView.js | 39 +++++++ views/controls/builder/blueprint.ejs | 92 ++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 public/assets/javascripts/ui/blueprint/BlueprintScale.js create mode 100644 public/assets/javascripts/ui/blueprint/BlueprintUpload.js create mode 100644 public/assets/javascripts/ui/blueprint/BlueprintView.js create mode 100644 views/controls/builder/blueprint.ejs diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScale.js b/public/assets/javascripts/ui/blueprint/BlueprintScale.js new file mode 100644 index 0000000..e69de29 diff --git a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js new file mode 100644 index 0000000..fd3a659 --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js @@ -0,0 +1,122 @@ + +var BlueprintUploadView = UploadView.extend({ + el: ".blueprintUpload", + + mediaTag: "blueprint", + createAction: "/api/media/new", + uploadAction: "/api/media/upload", + listAction: "/api/media/user", + destroyAction: "/api/media/destroy", + + events: { + "mousedown": 'stopPropagation', + "change .url": "enterUrl", + "keydown .url": "enterSetUrl", + + "click .blueprint": "choose", + "change [name=blueprint-dimensions]": "changeDimensions", + "change [name=blueprint-units]": "changeUnits", + "click #saveBlueprint": "save", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$url = this.$(".url") + + this.$blueprintMap = this.$("#blueprintMap") + this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") + this.$dimensions = this.$("[name=blueprint-dimensions]") + this.$units = this.$("[name=blueprint-units]") + this.$save = this.$("#saveBlueprint") + + this.map = new Map ({ type: 'ortho' }) + + this.load() + }, + + loaded: false, + load: function(){ + $.get(this.listAction, { tag: this.mediaTag }, this.populate.bind(this)) + }, + + populate: function(data){ + this.loaded = true + if (data && data.length) { + data.forEach(this.append.bind(this)) + this.$(".txt").hide() + } + else { + this.$(".txt").show() + } + }, + + append: function(media){ + var $el = $("
    ") + $el.data("id", media._id) + $el.addClass("blueprint") + this.$blueprints.append($el) + }, + + pick: function(e){ + var $el = $(e.currentTarget) + // load map with it + }, + + destroy: function(_id, cb){ + $.ajax({ + type: "delete", + url: this.destroyAction, + data: { _id: _id, _csrf: $("[name=_csrf]").val() } + }).complete(cb || function(){}) + }, + + show: function(){ + this.toggle(true) + }, + hide: function(){ + this.toggle(false) + }, + toggle: function (state) { + this.$el.toggleClass("active", state) + }, + + addUrl: function (url){ + Parser.loadImage(url, function(media){ + if (! media) return + media._csrf = $("[name=_csrf]").val() + media.tag = this.mediaTag + + var request = $.ajax({ + type: "post", + url: this.createAction, + data: media, + }) + request.done(this.add.bind(this)) + + }.bind(this)) + }, + enterUrl: function(){ + var url = this.$url.sanitize() + this.addUrl(url) + this.$url.val("") + }, + enterSetUrl: function (e) { + e.stopPropagation() + if (e.keyCode == 13) { + setTimeout(this.enterUrl.bind(this), 100) + } + }, + + add: function(media){ + this.append(media) + }, + changeDimensions: function(){ + }, + changeUnits: function(){ + }, + save: function(){ + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintView.js b/public/assets/javascripts/ui/blueprint/BlueprintView.js new file mode 100644 index 0000000..f7ee13e --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintView.js @@ -0,0 +1,39 @@ + +var BlueprintView = View.extend({ + el: "#blueprintView", + + events: { + }, + + initialize: function(){ +// this.info = new BuilderInfo ({ parent: this }) +// this.toolbar = new BuilderToolbar ({ parent: this }) +// this.settings = new BuilderSettings ({ parent: this }) +// this.colorControl = new ColorControl ({ parent: this }) +// this.cursor = new HelpCursor({ parent: this }) + this.blueprintUpload = new BlueprintUploadView ({ parent: this }) + }, + + load: function(name){ +// if (! name || name == "new") { +// this.ready({ isNew: true, _id: "new", name: "" }) +// return +// } +// +// name = sanitize(name) +// +// $.get(this.action + name, this.ready.bind(this)) + }, + + ready: function(data){ +// this.settings.load(data) +// this.info.load(data) + }, + + hideExtras: function(){ + }, + + pickWall: function(wall, pos){ + }, + +}) diff --git a/views/controls/builder/blueprint.ejs b/views/controls/builder/blueprint.ejs new file mode 100644 index 0000000..e5f3257 --- /dev/null +++ b/views/controls/builder/blueprint.ejs @@ -0,0 +1,92 @@ + + +
    +
    +
    + +
    + + + +
    + +
    + + + + +
    + +
    + X +
    + +

    Upload A Room Image

    + +
    +
    +
    + + + +
    +
    + +
    + + Please tell us the scale of your map. + Click both corners of a wall, and then enter how long the wall is. + +
    +
    + +
    + + + + +
    + +
    +
    +
    \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 4024085b09261c23cd89227e340037e0238072c7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 11 Aug 2015 14:15:31 -0400 Subject: uploader functioning --- .../javascripts/ui/blueprint/BlueprintEditor.js | 30 ++++++ .../javascripts/ui/blueprint/BlueprintScale.js | 0 .../javascripts/ui/blueprint/BlueprintUpload.js | 35 ++----- .../javascripts/ui/blueprint/BlueprintView.js | 3 +- public/assets/stylesheets/app.css | 2 +- views/controls/blueprint/editor.ejs | 104 +++++++++++++++++++++ views/controls/builder/blueprint.ejs | 92 ------------------ views/modal.ejs | 2 +- views/partials/scripts.ejs | 1 + 9 files changed, 149 insertions(+), 120 deletions(-) create mode 100644 public/assets/javascripts/ui/blueprint/BlueprintEditor.js delete mode 100644 public/assets/javascripts/ui/blueprint/BlueprintScale.js create mode 100644 views/controls/blueprint/editor.ejs delete mode 100644 views/controls/builder/blueprint.ejs diff --git a/public/assets/javascripts/ui/blueprint/BlueprintEditor.js b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js new file mode 100644 index 0000000..227c1c8 --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js @@ -0,0 +1,30 @@ + +var BlueprintEditor = ModalView.extend({ + el: ".blueprintEditor", + + events: { + "change [name=blueprint-dimensions]": "changeDimensions", + "change [name=blueprint-units]": "changeUnits", + "click #saveBlueprint": "save", + }, + + initialize: function(){ + this.$blueprintMap = this.$("#blueprintMap") + this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") + this.$dimensions = this.$("[name=blueprint-dimensions]") + this.$units = this.$("[name=blueprint-units]") + this.$save = this.$("#saveBlueprint") + + this.map = new Map ({ type: 'ortho' }) + + this.$blueprintMap.append(this.map.el) + }, + + changeDimensions: function(){ + }, + changeUnits: function(){ + }, + save: function(){ + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScale.js b/public/assets/javascripts/ui/blueprint/BlueprintScale.js deleted file mode 100644 index e69de29..0000000 diff --git a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js index fd3a659..9467715 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js @@ -1,5 +1,5 @@ -var BlueprintUploadView = UploadView.extend({ +var BlueprintUpload = UploadView.extend({ el: ".blueprintUpload", mediaTag: "blueprint", @@ -14,9 +14,6 @@ var BlueprintUploadView = UploadView.extend({ "keydown .url": "enterSetUrl", "click .blueprint": "choose", - "change [name=blueprint-dimensions]": "changeDimensions", - "change [name=blueprint-units]": "changeUnits", - "click #saveBlueprint": "save", }, initialize: function(opt){ @@ -24,15 +21,8 @@ var BlueprintUploadView = UploadView.extend({ this.__super__.initialize.call(this) this.$url = this.$(".url") + this.$blueprints = this.$(".blueprints") - this.$blueprintMap = this.$("#blueprintMap") - this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") - this.$dimensions = this.$("[name=blueprint-dimensions]") - this.$units = this.$("[name=blueprint-units]") - this.$save = this.$("#saveBlueprint") - - this.map = new Map ({ type: 'ortho' }) - this.load() }, @@ -52,13 +42,6 @@ var BlueprintUploadView = UploadView.extend({ } }, - append: function(media){ - var $el = $("
    ") - $el.data("id", media._id) - $el.addClass("blueprint") - this.$blueprints.append($el) - }, - pick: function(e){ var $el = $(e.currentTarget) // load map with it @@ -112,11 +95,13 @@ var BlueprintUploadView = UploadView.extend({ add: function(media){ this.append(media) }, - changeDimensions: function(){ - }, - changeUnits: function(){ - }, - save: function(){ - }, + append: function(media){ + var $el = $("") + $el.attr("src", media.url) + $el.data("id", media._id) + $el.addClass("blueprint") + this.$blueprints.append($el) + }, + }) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintView.js b/public/assets/javascripts/ui/blueprint/BlueprintView.js index f7ee13e..40c61d7 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintView.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintView.js @@ -11,7 +11,8 @@ var BlueprintView = View.extend({ // this.settings = new BuilderSettings ({ parent: this }) // this.colorControl = new ColorControl ({ parent: this }) // this.cursor = new HelpCursor({ parent: this }) - this.blueprintUpload = new BlueprintUploadView ({ parent: this }) + this.blueprintUpload = new BlueprintUpload ({ parent: this }) + this.blueprintEditor = new BlueprintEditor ({ parent: this }) }, load: function(name){ diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index bb32500..0f89242 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -1598,7 +1598,7 @@ form .paidPlan label { float: none; font-size: 16px; margin: 0 10px; } .mediaDrawer.alert, .mediaDrawer.confirm, .mediaDrawer.passwordForgot, .mediaDrawer.passwordReset, .mediaDrawer.usernameTaken, .mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject, -.mediaDrawer.blueprintUpload { +.mediaDrawer.blueprintEditor { display:table; } .confirm button { diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs new file mode 100644 index 0000000..6b80287 --- /dev/null +++ b/views/controls/blueprint/editor.ejs @@ -0,0 +1,104 @@ + + +
    +
    +
    + +
    + + + +
    + +
    + + + + +
    +
    + +
    + X +
    + +

    Upload your Blueprint

    + +
    + +
    +
    + + + +
    +
    + +
    +
    Your uploaded blueprints
    +
    +
    + + Please tell us the scale of your blueprint. + Click both corners of a wall, and then enter how long the wall is. + https://s3.amazonaws.com/luckyplop/fbf4295da80f1f66c5e4a248f2ea3e1ce7a22c3d.jpg + +
    +
    + +
    + + + + +
    + +
    +
    diff --git a/views/controls/builder/blueprint.ejs b/views/controls/builder/blueprint.ejs deleted file mode 100644 index e5f3257..0000000 --- a/views/controls/builder/blueprint.ejs +++ /dev/null @@ -1,92 +0,0 @@ - - -
    -
    -
    - -
    - - - -
    - -
    - - - - -
    - -
    - X -
    - -

    Upload A Room Image

    - -
    -
    -
    - - - -
    -
    - -
    - - Please tell us the scale of your map. - Click both corners of a wall, and then enter how long the wall is. - -
    -
    - -
    - - - - -
    - -
    -
    -
    \ No newline at end of file diff --git a/views/modal.ejs b/views/modal.ejs index 433861e..775ba88 100644 --- a/views/modal.ejs +++ b/views/modal.ejs @@ -10,7 +10,7 @@
    - [[ include controls/builder/blueprint ]] + [[ include controls/blueprint/editor ]] [[ include partials/confirm-modal ]] [[ include partials/sign-in ]] [[ include projects/layouts-modal ]] diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 64ac135..2a93e9b 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -128,6 +128,7 @@ + -- cgit v1.2.3-70-g09d2 From d84c89a8dd770ea174a7d2ac90927046a5f4b5f6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 11 Aug 2015 16:50:31 -0400 Subject: blueprint upload styling --- .../javascripts/rectangles/engine/map/ui/ortho.js | 4 +- .../javascripts/ui/blueprint/BlueprintEditor.js | 30 ----- .../javascripts/ui/blueprint/BlueprintScaler.js | 43 ++++++++ .../javascripts/ui/blueprint/BlueprintUpload.js | 36 ++++-- .../javascripts/ui/blueprint/BlueprintView.js | 2 +- views/controls/blueprint/editor.ejs | 122 +++++++++++++++++---- views/partials/scripts.ejs | 2 +- 7 files changed, 178 insertions(+), 61 deletions(-) delete mode 100644 public/assets/javascripts/ui/blueprint/BlueprintEditor.js create mode 100644 public/assets/javascripts/ui/blueprint/BlueprintScaler.js diff --git a/public/assets/javascripts/rectangles/engine/map/ui/ortho.js b/public/assets/javascripts/rectangles/engine/map/ui/ortho.js index 52f7339..5be7446 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui/ortho.js +++ b/public/assets/javascripts/rectangles/engine/map/ui/ortho.js @@ -81,7 +81,9 @@ Map.UI.Ortho = function(map){ } base.set_tool = function(s){ console.log("set tool to", s) - base.tools[currentTool].cancel() + if (base.tools[currentTool]) { + base.tools[currentTool].cancel() + } currentTool = s tool = base.tools[currentTool] } diff --git a/public/assets/javascripts/ui/blueprint/BlueprintEditor.js b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js deleted file mode 100644 index 227c1c8..0000000 --- a/public/assets/javascripts/ui/blueprint/BlueprintEditor.js +++ /dev/null @@ -1,30 +0,0 @@ - -var BlueprintEditor = ModalView.extend({ - el: ".blueprintEditor", - - events: { - "change [name=blueprint-dimensions]": "changeDimensions", - "change [name=blueprint-units]": "changeUnits", - "click #saveBlueprint": "save", - }, - - initialize: function(){ - this.$blueprintMap = this.$("#blueprintMap") - this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") - this.$dimensions = this.$("[name=blueprint-dimensions]") - this.$units = this.$("[name=blueprint-units]") - this.$save = this.$("#saveBlueprint") - - this.map = new Map ({ type: 'ortho' }) - - this.$blueprintMap.append(this.map.el) - }, - - changeDimensions: function(){ - }, - changeUnits: function(){ - }, - save: function(){ - }, - -}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js new file mode 100644 index 0000000..e11b61e --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js @@ -0,0 +1,43 @@ + +var BlueprintScaler = ModalView.extend({ + el: ".blueprintScaler", + + events: { + "change [name=blueprint-dimensions]": "changeDimensions", + "change [name=blueprint-units]": "changeUnits", + "click #saveBlueprint": "save", + }, + + initialize: function(){ + this.$blueprintMap = this.$("#blueprintMap") + this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") + this.$dimensions = this.$("[name=blueprint-dimensions]") + this.$units = this.$("[name=blueprint-units]") + this.$save = this.$("#saveBlueprint") + + this.map = map = new Map ({ + type: "ortho", + el: this.$blueprintMap.get(0), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: -2, + zoom_min: -6.2, + zoom_max: 1, + }) + map.ui.add_tool("arrow", new ArrowTool) + map.ui.add_tool("position", new PositionTool) + map.ui.set_tool("position") + }, + + pick: function(){ + + }, + + changeDimensions: function(){ + }, + changeUnits: function(){ + }, + save: function(){ + }, + +}) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js index 9467715..deb1075 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js @@ -13,7 +13,8 @@ var BlueprintUpload = UploadView.extend({ "change .url": "enterUrl", "keydown .url": "enterSetUrl", - "click .blueprint": "choose", + "click .blueprint": "pick", + "click .remove": "destroy", }, initialize: function(opt){ @@ -34,25 +35,33 @@ var BlueprintUpload = UploadView.extend({ populate: function(data){ this.loaded = true if (data && data.length) { + this.$blueprints.show() data.forEach(this.append.bind(this)) - this.$(".txt").hide() + this.show() } else { - this.$(".txt").show() + this.show() } }, pick: function(e){ var $el = $(e.currentTarget) - // load map with it + var media = $el.data("media") + this.hide() + this.parent.blueprintScaler.pick(media) }, - destroy: function(_id, cb){ + destroy: function(e){ + e.stopPropagation() + var $el = $(e.currentTarget) + var _id = $el.closest(".blueprint").data("id") + $el.remove() $.ajax({ type: "delete", url: this.destroyAction, data: { _id: _id, _csrf: $("[name=_csrf]").val() } - }).complete(cb || function(){}) + }).complete(function(){ + }) }, show: function(){ @@ -93,13 +102,24 @@ var BlueprintUpload = UploadView.extend({ }, add: function(media){ + this.$blueprints.show() this.append(media) + this.hide() + this.parent.blueprintScaler.pick(media) }, append: function(media){ - var $el = $("") - $el.attr("src", media.url) + var $el = $("") + var img = new Image () + img.src = media.url + var remove = document.createElement("span") + remove.className = "remove" + remove.innerHTML = "x" + $el.data("id", media._id) + $el.data("media", media) + $el.append(img) + $el.append(remove) $el.addClass("blueprint") this.$blueprints.append($el) }, diff --git a/public/assets/javascripts/ui/blueprint/BlueprintView.js b/public/assets/javascripts/ui/blueprint/BlueprintView.js index 40c61d7..a803f12 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintView.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintView.js @@ -12,7 +12,7 @@ var BlueprintView = View.extend({ // this.colorControl = new ColorControl ({ parent: this }) // this.cursor = new HelpCursor({ parent: this }) this.blueprintUpload = new BlueprintUpload ({ parent: this }) - this.blueprintEditor = new BlueprintEditor ({ parent: this }) + this.blueprintScaler = new BlueprintScaler ({ parent: this }) }, load: function(name){ diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs index 6b80287..aec5e25 100644 --- a/views/controls/blueprint/editor.ejs +++ b/views/controls/blueprint/editor.ejs @@ -33,13 +33,88 @@ body { .hud span.active { color: #000; } .blueprintUpload { - width: 240px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + width: 340px; + position: absolute; + top: 50%; left: 50%; + background: white; + padding: 10px; + border: 1px solid black; + box-shadow: -3px 3px #000; + -webkit-transform: translate3D(0%,-200%,0); + transform: translate3D(0%,-200%,0); + margin-left: -175px; + margin-top: -200px; + opacity: 0; +} +.blueprintUpload.active { + -webkit-transform: translate3D(0,0,0); + transform: translate3D(0,0,0); + opacity: 1; +} +.blueprintUpload .toolButton { + float: none; + width: 108px; + display: inline-block; +} +.blueprintUpload .url { + font-size: 15px; + border: 1px solid #888; + padding: 2px; + font-weight: 300; + position: relative; + top: 3px; + margin-right: 10px; + width: 190px; +} +.blueprintUpload p { + font-weight: 300; + font-size: 13px; +} +.blueprintUpload .blueprints { + display: none; +} +.blueprintUpload .blueprints h5 { + width: 250px; + margin: 10px auto; + padding-top: 9px; } .blueprints .blueprint { border: 1px solid black; - padding: 5px; + background: white; + padding: 0px; + position: relative; + display: inline-block; +} +.blueprints .blueprint img { height: 100px; max-width: 200px; + display: block; + cursor: pointer; +} +.blueprints .blueprint .remove { + box-shadow: 0 1px 2px #888; + cursor: pointer; + position: absolute; + color: red; + top: 7px; + right: 7px; + width: 20px; height: 20px; + text-align: center; + background: #fff; + border-radius: 50%; +} +.blueprints .blueprint .remove span { + position: relative; + top: -2px; +} +.blueprintUpload .wallpaperUpload .upload-icon { + margin: 0 4px; +} +.uploadNewBlueprint { + color: #333; + border-bottom: 1px solid; cursor: pointer; } @@ -63,42 +138,49 @@ body {
    - X
    -

    Upload your Blueprint

    -
    +

    Upload your Blueprint

    +

    + Upload an image which you will trace to make a floor plan. + Images should be at least 1000x1000. +

    +
    - +
    -
    Your uploaded blueprints
    - Please tell us the scale of your blueprint. - Click both corners of a wall, and then enter how long the wall is. - https://s3.amazonaws.com/luckyplop/fbf4295da80f1f66c5e4a248f2ea3e1ce7a22c3d.jpg +
    +
    + Please tell us the scale of your blueprint. + Click both corners of a wall, and then enter how long the wall is. +

    + Do you want to upload a blueprint? +
    -
    -
    +
    +
    -
    - - +
    + + - + +
    - +
    diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 2a93e9b..136bd4d 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -128,7 +128,7 @@ - + -- cgit v1.2.3-70-g09d2 From 554463ca8e8492bfd5f0f496e3a2291bfb495f80 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 11 Aug 2015 18:49:29 -0400 Subject: blueprint scaler stuff --- .../assets/javascripts/mx/primitives/mx.image.js | 17 ++- .../javascripts/ui/blueprint/BlueprintScaler.js | 34 +++++- .../javascripts/ui/blueprint/BlueprintUpload.js | 5 +- public/assets/stylesheets/app.css | 89 +++++++++++++++ public/assets/test/ortho4.html | 2 + views/controls/blueprint/editor.ejs | 120 +++++---------------- 6 files changed, 163 insertions(+), 104 deletions(-) diff --git a/public/assets/javascripts/mx/primitives/mx.image.js b/public/assets/javascripts/mx/primitives/mx.image.js index f9de141..33b1373 100644 --- a/public/assets/javascripts/mx/primitives/mx.image.js +++ b/public/assets/javascripts/mx/primitives/mx.image.js @@ -1,5 +1,7 @@ MX.Image = MX.Object3D.extend({ init: function (ops) { + ops = ops || {} + this.type = "Image" this.media = ops.media this.width = 0 @@ -41,15 +43,20 @@ MX.Image = MX.Object3D.extend({ layer.dirty = true layer.update() layer.ops.onload + + if (ops.keepImage) { + layer.image = image + } } - image.src = ops.src; - - if (ops.keepImage) { - this.image = image - } + + if (ops.src) image.src = ops.src + else if (ops.media) image.src = ops.media.url + else if (ops.url) image.src = ops.url }, draw: function(ctx, recenter){ + if (! this.image) { return } + if (recenter) { ctx.save() ctx.scale(-1, 1) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js index e11b61e..a81c89b 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js @@ -18,7 +18,7 @@ var BlueprintScaler = ModalView.extend({ this.map = map = new Map ({ type: "ortho", el: this.$blueprintMap.get(0), - width: window.innerWidth/2, + width: window.innerWidth, height: window.innerHeight, zoom: -2, zoom_min: -6.2, @@ -27,10 +27,38 @@ var BlueprintScaler = ModalView.extend({ map.ui.add_tool("arrow", new ArrowTool) map.ui.add_tool("position", new PositionTool) map.ui.set_tool("position") + + scene = scene || { camera: { x: 0, y: 0, z: 0 } } + + this.floorplan = new MX.Image () + + this.animate() }, - pick: function(){ - + pick: function(media){ + this.floorplan.load({ media: media, keepImage: true }) + }, + + animate: function(t){ + requestAnimationFrame(this.animate.bind(this)) + + var dt = t - this.last_t + this.last_t = t + + if (! t) return + + this.map.update(t) + + this.map.draw.ctx.save() + this.map.draw.translate() + + this.floorplan.draw(this.map.draw.ctx, true) + + this.map.draw.coords() + + this.map.draw.mouse(this.map.ui.mouse.cursor) + + this.map.draw.ctx.restore() }, changeDimensions: function(){ diff --git a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js index deb1075..498575a 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintUpload.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintUpload.js @@ -36,8 +36,9 @@ var BlueprintUpload = UploadView.extend({ this.loaded = true if (data && data.length) { this.$blueprints.show() - data.forEach(this.append.bind(this)) - this.show() + data.forEach(this.append.bind(this)) + this.hide() + this.parent.blueprintScaler.pick(data[0]) } else { this.show() diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 0f89242..6507cc1 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -3253,6 +3253,95 @@ a[data-role="forgot-password"] { } +/* blueprint upload box */ + +.blueprintUpload { + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + width: 340px; + position: absolute; + top: 50%; left: 50%; + background: white; + padding: 10px; + border: 1px solid black; + box-shadow: -3px 3px #000; + -webkit-transform: translate3D(0%,-200%,0); + transform: translate3D(0%,-200%,0); + margin-left: -175px; + margin-top: -200px; + opacity: 0; +} +.blueprintUpload.active { + -webkit-transform: translate3D(0,0,0); + transform: translate3D(0,0,0); + opacity: 1; +} +.blueprintUpload .toolButton { + float: none; + width: 108px; + display: inline-block; +} +.blueprintUpload .url { + font-size: 15px; + border: 1px solid #888; + padding: 2px; + font-weight: 300; + position: relative; + top: 3px; + margin-right: 10px; + width: 190px; +} +.blueprintUpload p { + font-weight: 300; + font-size: 13px; +} +.blueprintUpload .blueprints { + display: none; +} +.blueprintUpload .blueprints h5 { + width: 250px; + margin: 10px auto; + padding-top: 9px; +} +.blueprints .blueprint { + border: 2px solid black; + background: white; + padding: 0px; + position: relative; + display: inline-block; +} +.blueprints .blueprint img { + height: 100px; + max-width: 200px; + display: block; + cursor: pointer; +} +.blueprints .blueprint .remove { + box-shadow: -2px 2px #000; + cursor: pointer; + position: absolute; + color: red; + top: 7px; + right: 7px; + width: 20px; height: 20px; + text-align: center; + background: #fff; + border: 1px solid black; +} +.blueprints .blueprint .remove span { + position: relative; + top: -2px; +} +.blueprintUpload .wallpaperUpload .upload-icon { + margin: 0 4px; +} +.uploadNewBlueprint { + color: #333; + border-bottom: 1px solid; + cursor: pointer; +} + + /* KEYBOARD SHORTCUTS */ .keyboard { float: left; width: 50%; margin-top: 50px; } diff --git a/public/assets/test/ortho4.html b/public/assets/test/ortho4.html index 1c1adef..d704e0e 100644 --- a/public/assets/test/ortho4.html +++ b/public/assets/test/ortho4.html @@ -160,7 +160,9 @@ map.ui.placing = false $(window).resize(function(){ scene.width = window.innerWidth/2 + scene.height = window.innerHeight map.canvas.width = map.dimensions.a = window.innerWidth/2 + map.canvas.height = map.dimensions.b = window.innerHeight/2 }) var wall_height = 180 diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs index aec5e25..308b4c8 100644 --- a/views/controls/blueprint/editor.ejs +++ b/views/controls/blueprint/editor.ejs @@ -32,90 +32,20 @@ body { .hud span { color: #888; cursor: pointer; } .hud span.active { color: #000; } -.blueprintUpload { - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - width: 340px; - position: absolute; - top: 50%; left: 50%; - background: white; - padding: 10px; - border: 1px solid black; - box-shadow: -3px 3px #000; - -webkit-transform: translate3D(0%,-200%,0); - transform: translate3D(0%,-200%,0); - margin-left: -175px; - margin-top: -200px; - opacity: 0; -} -.blueprintUpload.active { - -webkit-transform: translate3D(0,0,0); - transform: translate3D(0,0,0); - opacity: 1; -} -.blueprintUpload .toolButton { - float: none; - width: 108px; - display: inline-block; -} -.blueprintUpload .url { - font-size: 15px; - border: 1px solid #888; - padding: 2px; - font-weight: 300; - position: relative; - top: 3px; - margin-right: 10px; - width: 190px; -} -.blueprintUpload p { - font-weight: 300; +.blueprintInfo { + bottom: 14px; + left: 10px; + width: 270px; font-size: 13px; + font-weight: 300; + padding: 10px; } -.blueprintUpload .blueprints { - display: none; -} -.blueprintUpload .blueprints h5 { - width: 250px; - margin: 10px auto; - padding-top: 9px; -} -.blueprints .blueprint { - border: 1px solid black; - background: white; - padding: 0px; - position: relative; - display: inline-block; -} -.blueprints .blueprint img { - height: 100px; - max-width: 200px; - display: block; - cursor: pointer; -} -.blueprints .blueprint .remove { - box-shadow: 0 1px 2px #888; - cursor: pointer; - position: absolute; - color: red; - top: 7px; - right: 7px; - width: 20px; height: 20px; - text-align: center; - background: #fff; - border-radius: 50%; -} -.blueprints .blueprint .remove span { - position: relative; - top: -2px; -} -.blueprintUpload .wallpaperUpload .upload-icon { - margin: 0 4px; +.blueprintInfo .setting { + margin-bottom: 20px; } -.uploadNewBlueprint { - color: #333; - border-bottom: 1px solid; - cursor: pointer; +.blueprintInfo .setting.number input[type=text] { + width: 100px; + font-size: 16px; } @@ -139,7 +69,7 @@ body {
    - +

    Upload your Blueprint

    @@ -161,25 +91,27 @@ body {

    -
    +
    Please tell us the scale of your blueprint. - Click both corners of a wall, and then enter how long the wall is. + Click two corners of a wall, and then enter how long the wall is.

    - Do you want to upload a blueprint? + You can also upload another blueprint. +

    + +
    + + + +
    +
    -
    - - - - -
    -- cgit v1.2.3-70-g09d2 From d9050d0faacb0434a94e4bce2acc8f99e189db4f Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 12 Aug 2015 12:30:44 -0400 Subject: refactor staff area --- server/lib/views/staff.js | 918 ----------------------------------- server/lib/views/staff/defaults.js | 6 + server/lib/views/staff/fields.js | 9 + server/lib/views/staff/helpers.js | 52 ++ server/lib/views/staff/index.js | 452 +++++++++++++++++ server/lib/views/staff/middleware.js | 421 ++++++++++++++++ views/staff/projects/index.ejs | 2 +- 7 files changed, 941 insertions(+), 919 deletions(-) delete mode 100644 server/lib/views/staff.js create mode 100644 server/lib/views/staff/defaults.js create mode 100644 server/lib/views/staff/fields.js create mode 100644 server/lib/views/staff/helpers.js create mode 100644 server/lib/views/staff/index.js create mode 100644 server/lib/views/staff/middleware.js diff --git a/server/lib/views/staff.js b/server/lib/views/staff.js deleted file mode 100644 index 43330e2..0000000 --- a/server/lib/views/staff.js +++ /dev/null @@ -1,918 +0,0 @@ -/* jshint node: true */ - -var User = require('../schemas/User'), - Project = require('../schemas/Project'), - Media = require('../schemas/Media'), - Collaborator = require('../schemas/Collaborator'), - Plan = require('../schemas/Plan'), - Subscription = require('../schemas/Subscription'), - Layout = require('../schemas/Layout'), - config = require('../../../config'), - middleware = require('../middleware'), - util = require('../util'), - _ = require('lodash'), - moment = require('moment'); - - -var staff = module.exports = { - - fields: { - user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", - project: "_id name slug user_id privacy layout_type created_at updated_at", - layout: "_id name slug user_id layout_type created_at updated_at", - plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + - "pro_layout_monthly_price pro_layout_yearly_price " + - "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", - plans_permissions: "basic_editor pro_editor sculpture collaborators no_logo", - }, - - defaults: { - user: { - _id: "", username: "", displayName: "", - created_at: "", updated_at: "", created_ip: "", last_ip: "", - }, - }, - - middleware: { - - ensureUsers: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var initial = util.sanitize(req.query.initial) - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "last_seen", "username"] - switch (req.query.sort) { - case 'date': - sort = {'created_at': -1} - break - case 'last_seen': - sort = {'last_seen': -1} - break - case 'username': - default: - sort = {'username': 1} - paginationInfo.sort = "username" - break - } - if (initial) { - if (initial == "?") { - criteria.username = new RegExp('^[$a-zA-Z]', "i") - } - else { - criteria.username = new RegExp('^' + initial, "i") - } - } - User.find(criteria) - .select(staff.fields.user) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, users) { - res.locals.users = users.map(staff.helpers.user) - if (! res.locals.users.length) { - if (initial) { - res.locals.opt.error = "No users found starting with " + initial.toUpperCase() + "" - } - else { - res.locals.opt.error = "No users found" - } - } - next() - }) - }, - - ensureRecentUsers: function(req, res, next){ - var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } - staff.middleware.ensureUsers(dreq, res, next) - }, - - ensureProjects: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - default: - case 'date': - sort = {'updated_at': -1} - break - case 'name': - paginationInfo.sort = "name" - sort = {'slug': 1} - break - } - Project.find(criteria) - .select(staff.fields.project) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, projects) { - res.locals.projects = projects.map(staff.helpers.project) - next() - }) - }, - - ensureLayouts: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - default: - case 'date': - sort = {'updated_at': -1} - break - case 'name': - paginationInfo.sort = "name" - sort = {'slug': 1} - break - } - Layout.find(criteria) - .select(staff.fields.layout) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, layouts) { - res.locals.layouts = layouts.map(staff.helpers.layout) - next() - }) - }, - - ensureMedia: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date"] - switch (req.query.sort) { - default: - case 'date': - paginationInfo.sort = "date" - sort = {'created_at': -1} - break - } - Media.find(criteria) - // .select(staff.fields.media) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, media) { - res.locals.media = media.map(staff.helpers.media) - next() - }) - }, - - ensureSubscriptions: function(req, res, next){ - var paginationInfo = res.locals.pagination = {} - var criteria = req.criteria || {} - var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) - var offset = paginationInfo.offset = Number(req.query.offset) || 0 - var sort - paginationInfo.sort = req.query.sort - paginationInfo.sortOptions = ["date", "name"] - switch (req.query.sort) { - case 'created': - sort = {'created_at': -1} - break - default: - case 'date': - sort = {'updated_at': -1} - break - } - Subscription.find(criteria) - .select(staff.fields.project) - .sort(sort) - .skip(offset) - .limit(limit) - .exec(function (err, subscriptions) { - res.locals.subscriptions = subscriptions.map(staff.helpers.subscription) - next() - }) - }, - - ensurePlans: function(req, res, next){ - Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { - res.locals.plans = (plans || []).map(staff.helpers.plan) - res.locals.plans.sort(function(a,b){ return a.monthly_price }) - next() - }) - }, - ensurePlan: function (req, res, next) { - if (req.params.slug) { - Plan.findOne({ slug: req.params.slug }, function(err, plan){ - if (err || ! plan) { - console.error(err) - res.redirect("/staff/plans/") - } - else { - req.plan = plan - next() - } - }) - } - else { - res.redirect("/staff/plans/") - } - }, - - ensureSubscription: function (req, res, next) { - if (req.params.id) { - Subscription.findOne({ _id: req.params.id }, function(err, subscription){ - if (err || ! subscription) { - console.error(err) - res.redirect("/staff/subscriptions/") - } - else { - req.subscription = subscription - next() - } - }) - } - else { - res.redirect("/staff/subscriptions/") - } - }, - - ensureRecentProjects: function(req, res, next){ - var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } - staff.middleware.ensureProjects(dreq, res, next) - }, - - ensureProjectsUsers: function(req, res, next){ - if (! res.locals.projects || ! res.locals.projects.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.projects, next) - }, - - ensureLayoutsUsers: function(req, res, next){ - if (! res.locals.layouts || ! res.locals.layouts.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.layouts, next) - }, - - ensureSubscriptionsUsers: function(req, res, next){ - if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.subscriptions, next) - }, - - ensureMediaUsers: function(req, res, next){ - if (! res.locals.media || ! res.locals.media.length) { return next() } - staff.middleware.ensureObjectsUsers(res.locals.media, next) - }, - - ensureSubscriptionUser: function(req, res, next){ - if (! res.locals.subscription) { return next() } - staff.middleware.ensureObjectsUsers([ res.locals.subscription ], function(){ - next() - }) - }, - - ensureMediaUser: function(req, res, next){ - if (! res.locals.media) { return next() } - staff.middleware.ensureObjectsUsers([ res.locals.media ], function(){ - res.locals.mediaUser = res.locals.media.User - next() - }) - }, - - ensureObjectsUsers: function(objects, next){ - if (! objects) { return next () } - var dedupe = {}, user_ids - objects.forEach(function(obj){ - dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] - dedupe[ obj.user_id ].push(obj) - }) - user_ids = _.keys(dedupe) - User.find({ _id: { $in: user_ids } }) - .select(staff.fields.user) - .exec(function (err, users) { - if (! users) { return next () } - users.forEach(function(user){ - dedupe[user._id].forEach(function(obj){ - obj.user = user - }) - }) - next() - }) - }, - - ensureProfile: function(req, res, next){ - var username = req.params.username - if (username) { - User.findOne({ username: username }, function (err, user) { - if (user) { - res.locals.profile = req.method == "GET" ? staff.helpers.user(user) : user - } - else { - res.locals.profile = null - } - next() - }) - } - else { - res.locals.profile = null - next() - } - }, - - ensureSingleMedia: function(req, res, next){ - var id = req.params.id - if (id) { - Media.findOne({ _id: id }, function (err, media) { - if (media) { - res.locals.media = req.method == "GET" ? staff.helpers.media(media) : media - } - else { - res.locals.media = null - } - next() - }) - } - else { - res.locals.media = null - next() - } - }, - - ensureUsersCount: function(req, res, next){ - User.count({}, function(err, count){ - res.locals.userCount = count || 0 - next() - }) - }, - - ensureProjectsCount: function(req, res, next){ - Project.count({}, function(err, count){ - res.locals.projectCount = count || 0 - next() - }) - }, - - ensureLayoutsCount: function(req, res, next){ - Layout.count({}, function(err, count){ - res.locals.layoutCount = count || 0 - next() - }) - }, - - ensureMediaCount: function(req, res, next){ - Media.count({}, function(err, count){ - res.locals.mediaCount = count || 0 - next() - }) - }, - - ensureProfileProjectCount: function(req, res, next){ - if (! res.locals.profile) { return next() } - Project.count({ user_id: res.locals.profile._id}, function(err, count){ - res.locals.profile.projectCount = count || 0 - next() - }) - }, - - ensureProfileMediaCount: function(req, res, next){ - if (! res.locals.profile) { return next() } - Media.count({ user_id: res.locals.profile._id}, function(err, count){ - res.locals.profile.mediaCount = count || 0 - next() - }) - }, - - ensureProfileProjects: function(req, res, next){ - if (! res.locals.profile) { return next() } - Project.find({ user_id: res.locals.profile._id }, staff.fields.project, function(err, projects){ - res.locals.projects = projects.map(staff.helpers.project) - next() - }) - }, - - ensureProfileMedia: function(req, res, next){ - if (! res.locals.profile) { return next() } - req.criteria = { user_id: res.locals.profile._id } - staff.middleware.ensureMedia(req, res, next) - }, - - ensureProject: function(req, res, next){ - res.locals.project = req.project - next() - }, - - ensureProjectUser: function(req, res, next){ - if (! res.locals.project) { return next() } - User.findOne({ _id: res.locals.project.user_id }, staff.fields.user, function(err, user){ - res.locals.projectUser = staff.helpers.user(user) || staff.defaults.user - next() - }) - }, - - ensureProjectCollaborators: function(req, res, next){ - if (! res.locals.project) { - res.locals.collaborators = [] - return next() - } - Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ - res.locals.collaborators = collaborators || [] - next() - }) - }, - - ensureLayout: function(req, res, next){ - res.locals.layout = req.layout - next() - }, - ensureLayoutUser: function(req, res, next){ - if (! res.locals.layout) { return next() } - User.findOne({ _id: res.locals.layout.user_id }, staff.fields.user, function(err, user){ - res.locals.layoutUser = staff.helpers.user(user) || staff.defaults.user - next() - }) - }, - - }, - - helpers: { - user: function(user){ - var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) - user = user.toObject() - user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() - user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") - user.created_ip = util.num2ip( user.created_ip ) - user.last_ip = util.num2ip( user.last_ip ) - return user - }, - - project: function(project){ - project = project.toObject() - project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") - project.user = {} - return project - }, - - layout: function(layout){ - layout = layout.toObject() - layout.date = moment( layout.updated_at || layout.created_at ).format("M/DD/YYYY hh:mm a") - layout.user = {} - return layout - }, - - media: function(media){ - media = media.toObject() - media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") - media.user = {} - media.shortUrl = media.url.replace(/^http.:\/\//,"") - return media - }, - - plan: function(plan){ - plan = plan.toObject() - plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") - plan.user = {} - return plan - }, - - subscription: function(subscription){ - subscription = subscription.toObject() - subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a") - subscription.user = {} - return subscription - }, - }, - - route: function(app){ - app.get('/staff', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureRecentUsers, - staff.middleware.ensureUsersCount, - staff.middleware.ensureProjectsCount, - staff.middleware.ensureMediaCount, - - staff.index - ); - - // - // users - - app.get('/staff/users', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureUsersCount, - staff.middleware.ensureUsers, - - staff.users.index - ); - app.get('/staff/users/:username', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - staff.middleware.ensureProfileProjectCount, - staff.middleware.ensureProfileMediaCount, - staff.middleware.ensureProfileProjects, - - staff.users.show - ); - app.get('/staff/users/:username/media', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - staff.middleware.ensureProfileMedia, - staff.middleware.ensureProfileMediaCount, - - staff.users.media - ); - app.put('/staff/users/:username/bless', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProfile, - - staff.users.bless - ); - - if (app.get('env') === 'development') { - app.get('/staff/authorize', - middleware.ensureAuthenticated, - staff.users.blessSelf - ); - } - - // - // projects - - app.get('/staff/projects', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureProjectsCount, - - staff.middleware.ensureProjects, - staff.middleware.ensureProjectsUsers, - - staff.projects.index - ); - app.get('/staff/projects/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureProject, - staff.middleware.ensureProject, - staff.middleware.ensureProjectUser, - staff.middleware.ensureProjectCollaborators, - - staff.projects.show - ); - app.put('/staff/projects/:slug/feature', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureProject, - staff.middleware.ensureProject, - - staff.projects.feature - ); - - // - // layouts - - app.get('/staff/layouts', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureLayoutsCount, - - staff.middleware.ensureLayouts, - staff.middleware.ensureLayoutsUsers, - - staff.layouts.index - ); - app.get('/staff/layouts/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureLayout, - staff.middleware.ensureLayout, - staff.middleware.ensureLayoutUser, - - staff.layouts.show - ); - app.put('/staff/layouts/:slug/stock', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - middleware.ensureLayout, - staff.middleware.ensureLayout, - - staff.layouts.make_stock - ); - - // - // media - - app.get('/staff/media', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureMediaCount, - - staff.middleware.ensureMedia, - staff.middleware.ensureMediaUsers, - - staff.media.index - ); - app.get('/staff/media/:id', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSingleMedia, - staff.middleware.ensureMediaUser, - - staff.media.show - ); - - // - // plans - - app.get('/staff/plans', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensurePlans, - - staff.plans.index - ); - app.get('/staff/plans/new', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.plans.new - ); - app.post('/staff/plans/new', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.plans.create - ); - app.get('/staff/plans/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensurePlan, - - staff.plans.edit - ); - app.post('/staff/plans/:slug', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensurePlan, - - staff.plans.update - ); - - // - // subscriptions - app.get('/staff/subscriptions', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSubscriptions, - staff.middleware.ensureSubscriptionsUsers, - - staff.subscriptions.index - ); - app.get('/staff/subscriptions/:id', - middleware.ensureAuthenticated, - middleware.ensureIsStaff, - - staff.middleware.ensureSubscription, - staff.middleware.ensureSubscriptionUser, - - staff.subscriptions.show - ); - }, - - paginate: function(req, res){ - var info = res.locals.pagination - info.query = "sort=" + info.sort + "&limit=" + info.limit - info.first_page = 0 - info.last_page = Math.max(0, info.max - info.limit) - info.sortOptions = info.sortOptions - if (info.offset > 0) { - info.prev_page = Math.max(0, info.offset - info.limit) - } - else { - info.prev_page = -1 - } - if (info.count == info.limit && info.offset + info.limit < info.max) { - info.next_page = info.offset + info.limit - } - else { - info.next_page = -1 - } - }, - - index: function(req, res){ - res.render('staff/index') - }, - - // /staff/users/ - // /staff/users/:username - users: { - index: function(req, res){ - res.locals.pagination.count = res.locals.users.length - res.locals.pagination.max = res.locals.userCount - staff.paginate(req, res) - res.render('staff/users/index') - }, - show: function(req, res){ - if (res.locals.profile) { - res.render('staff/users/show', { - profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) - }) - } - else { - res.render('staff/users/show_404') - } - }, - media: function(req, res){ - if (res.locals.profile) { - res.locals.pagination.count = res.locals.media.length - res.locals.pagination.max = res.locals.profile.mediaCount - staff.paginate(req, res) - res.render('staff/users/media') - } - else { - res.render('staff/users/show_404') - } - }, - blessSelf: function(req, res){ - req.user.isStaff = true - req.user.save(function(err, user){ - res.json({ state: user.isStaff }) - }) - }, - bless: function(req, res){ - res.locals.profile.isStaff = req.body.state == "true" - res.locals.profile.save(function(err, user){ - res.json({ state: user.isStaff }) - }) - }, - }, - - // /staff/projects/ - // /staff/projects/:name - projects: { - index: function(req, res){ - res.locals.pagination.count = res.locals.projects.length - res.locals.pagination.max = res.locals.projectCount - staff.paginate(req, res) - res.render('staff/projects/index') - }, - show: function(req, res){ - if (res.locals.project) { - res.render('staff/projects/show', { - projectJSON: util.escape( JSON.stringify( res.locals.project ) ), - projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), - collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), - }) - } - else { - res.render('staff/projects/show_404') - } - }, - feature: function(req, res){ - res.locals.project.featured = req.body.state == "true" - res.locals.project.save(function(err, project){ - res.json({ state: project.featured }) - }) - }, - }, - - // /staff/layouts/ - // /staff/layouts/:name - layouts: { - index: function(req, res){ - res.locals.pagination.count = res.locals.layouts.length - res.locals.pagination.max = res.locals.layoutCount - staff.paginate(req, res) - res.render('staff/layouts/index') - }, - show: function(req, res){ - if (res.locals.layout) { - res.render('staff/layouts/show', { - }) - } - else { - res.render('staff/layouts/show_404') - } - }, - make_stock: function(req, res){ - res.locals.layout.is_stock = req.body.state == "true" - res.locals.layout.save(function(err, layout){ - res.json({ state: layout.is_stock }) - }) - }, - }, - - - media: { - index: function(req, res){ - res.locals.pagination.count = res.locals.media.length - res.locals.pagination.max = res.locals.mediaCount - staff.paginate(req, res) - res.render('staff/media/index') - }, - show: function(req, res){ - if (res.locals.media) { - res.render('staff/media/show', { - mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), - mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), - }) - } - else { - res.render('staff/media/show_404') - } - }, - }, - - plans: { - index: function(req, res){ - res.locals.fields = staff.fields.plans.split(" ") - res.locals.permissions = staff.fields.plans_permissions.split(" ") - res.render('staff/plans/index') - }, - new: function(req, res){ - res.locals.plan = new Plan () - res.render('staff/plans/new') - }, - edit: function(req, res){ - res.locals.plan = req.plan - res.render('staff/plans/edit') - }, - create: function(req, res){ - var plan = new Plan () - var fields = staff.fields.plans.split(" ") - var permissions = staff.fields.plans_permissions.split(" ") - - var data = util.cleanQuery(req.body) - data.name = util.sanitize(data.name) - data.slug = util.sanitize(data.slug.toLowerCase()) - - data.permissions = {} - permissions.forEach(function(field){ - data.permissions[field] = data["permissions_" + field].length == 2 - }) - - new Plan (data).save(function(err, doc){ - if (err || ! doc) { return res.json({ error: err }) } - middleware.updatePlans() - res.redirect("/staff/plans/") - }) - }, - update: function(req, res){ - var fields = staff.fields.plans.split(" ") - var permissions = staff.fields.plans_permissions.split(" ") - - var data = util.cleanQuery(req.body) - data.name = util.sanitize(data.name) - data.slug = util.sanitize(data.slug.toLowerCase()) - - _.extend(req.plan, data) - permissions.forEach(function(field){ - req.plan.permissions[field] = data["permissions_" + field].length == 2 - }) - - req.plan.save(function(err, doc){ - if (err || ! doc) { return res.json({ error: err }) } - middleware.updatePlans() - res.redirect("/staff/plans/") - }) - }, - }, - - subscriptions: { - index: function(req, res){ - res.locals.pagination.count = res.locals.subscriptions.length - res.locals.pagination.max = res.locals.subscriptionCount - staff.paginate(req, res) - res.render('staff/subscriptions/index') - }, - show: function(req, res){ - res.render('staff/subscriptions/show') - }, - }, - -} diff --git a/server/lib/views/staff/defaults.js b/server/lib/views/staff/defaults.js new file mode 100644 index 0000000..4d86c41 --- /dev/null +++ b/server/lib/views/staff/defaults.js @@ -0,0 +1,6 @@ +module.exports = { + user: { + _id: "", username: "", displayName: "", + created_at: "", updated_at: "", created_ip: "", last_ip: "", + }, +} diff --git a/server/lib/views/staff/fields.js b/server/lib/views/staff/fields.js new file mode 100644 index 0000000..57eea7e --- /dev/null +++ b/server/lib/views/staff/fields.js @@ -0,0 +1,9 @@ +module.exports = { + user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", + project: "_id name slug user_id privacy layout_type created_at updated_at", + layout: "_id name slug user_id layout_type created_at updated_at", + plans: "monthly_price yearly_price basic_layout_monthly_price basic_layout_yearly_price " + + "pro_layout_monthly_price pro_layout_yearly_price " + + "basic_layout_limit pro_layout_limit stock_project_limit basic_project_limit pro_project_limit", + plans_permissions: "basic_editor pro_editor sculpture collaborators no_logo", +} diff --git a/server/lib/views/staff/helpers.js b/server/lib/views/staff/helpers.js new file mode 100644 index 0000000..57383f4 --- /dev/null +++ b/server/lib/views/staff/helpers.js @@ -0,0 +1,52 @@ + +var util = require('../../util'), + _ = require('lodash'), + moment = require('moment'); + +module.exports = { + user: function(user){ + var last_seen = moment( user.last_seen || user.updated_at || user.created_at ) + user = user.toObject() + user.last_seen = last_seen.format("YYYY/MM/DD HH:MM") + " " + last_seen.fromNow() + user.last_charged = user.last_charged && moment( user.last_charged ).format("YYYY/MM/DD HH:MM") + user.created_ip = util.num2ip( user.created_ip ) + user.last_ip = util.num2ip( user.last_ip ) + return user + }, + + project: function(project){ + project = project.toObject() + project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") + project.user = {} + return project + }, + + layout: function(layout){ + layout = layout.toObject() + layout.date = moment( layout.updated_at || layout.created_at ).format("M/DD/YYYY hh:mm a") + layout.user = {} + return layout + }, + + media: function(media){ + media = media.toObject() + media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") + media.user = {} + media.shortUrl = media.url.replace(/^http.?:\/\//,"") + return media + }, + + plan: function(plan){ + plan = plan.toObject() + plan.date = moment( plan.updated_at || plan.created_at ).format("M/DD/YYYY hh:mm a") + plan.user = {} + return plan + }, + + subscription: function(subscription){ + subscription = subscription.toObject() + subscription.date = moment( subscription.updated_at || subscription.created_at ).format("M/DD/YYYY hh:mm a") + subscription.user = {} + return subscription + }, +} diff --git a/server/lib/views/staff/index.js b/server/lib/views/staff/index.js new file mode 100644 index 0000000..6a56238 --- /dev/null +++ b/server/lib/views/staff/index.js @@ -0,0 +1,452 @@ +/* jshint node: true */ + +var User = require('../../schemas/User'), + Project = require('../../schemas/Project'), + Media = require('../../schemas/Media'), + Collaborator = require('../../schemas/Collaborator'), + Plan = require('../../schemas/Plan'), + Subscription = require('../../schemas/Subscription'), + Layout = require('../../schemas/Layout'), + config = require('../../../../config'), + middleware = require('../../middleware'), + util = require('../../util'), + _ = require('lodash'), + moment = require('moment'); + + +var staff = module.exports = { + + fields: require('./fields'), + defaults: require('./defaults'), + middleware: require('./middleware'), + helpers: require('./helpers'), + + route: function(app){ + app.get('/staff', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureRecentUsers, + staff.middleware.ensureUsersCount, + staff.middleware.ensureProjectsCount, + staff.middleware.ensureMediaCount, + + staff.index + ); + + // + // users + + app.get('/staff/users', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureUsersCount, + staff.middleware.ensureUsers, + + staff.users.index + ); + app.get('/staff/users/:username', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + staff.middleware.ensureProfileProjectCount, + staff.middleware.ensureProfileMediaCount, + staff.middleware.ensureProfileProjects, + + staff.users.show + ); + app.get('/staff/users/:username/media', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + staff.middleware.ensureProfileMedia, + staff.middleware.ensureProfileMediaCount, + + staff.users.media + ); + app.put('/staff/users/:username/bless', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + + staff.users.bless + ); + + if (app.get('env') === 'development') { + app.get('/staff/authorize', + middleware.ensureAuthenticated, + staff.users.blessSelf + ); + } + + // + // projects + + app.get('/staff/projects', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProjectsCount, + + staff.middleware.ensureProjects, + staff.middleware.ensureProjectsUsers, + + staff.projects.index + ); + app.get('/staff/projects/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureProject, + staff.middleware.ensureProject, + staff.middleware.ensureProjectUser, + staff.middleware.ensureProjectCollaborators, + + staff.projects.show + ); + app.put('/staff/projects/:slug/feature', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureProject, + staff.middleware.ensureProject, + + staff.projects.feature + ); + + // + // layouts + + app.get('/staff/layouts', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureLayoutsCount, + + staff.middleware.ensureLayouts, + staff.middleware.ensureLayoutsUsers, + + staff.layouts.index + ); + app.get('/staff/layouts/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + staff.middleware.ensureLayoutUser, + + staff.layouts.show + ); + app.put('/staff/layouts/:slug/stock', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + middleware.ensureLayout, + staff.middleware.ensureLayout, + + staff.layouts.make_stock + ); + + // + // media + + app.get('/staff/media', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureMediaCount, + + staff.middleware.ensureMedia, + staff.middleware.ensureMediaUsers, + + staff.media.index + ); + app.get('/staff/media/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSingleMedia, + staff.middleware.ensureMediaUser, + + staff.media.show + ); + + // + // plans + + app.get('/staff/plans', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlans, + + staff.plans.index + ); + app.get('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.new + ); + app.post('/staff/plans/new', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.plans.create + ); + app.get('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.edit + ); + app.post('/staff/plans/:slug', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensurePlan, + + staff.plans.update + ); + + // + // subscriptions + app.get('/staff/subscriptions', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscriptions, + staff.middleware.ensureSubscriptionsUsers, + + staff.subscriptions.index + ); + app.get('/staff/subscriptions/:id', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureSubscription, + staff.middleware.ensureSubscriptionUser, + + staff.subscriptions.show + ); + }, + + paginate: function(req, res){ + var info = res.locals.pagination + info.query = "sort=" + info.sort + "&limit=" + info.limit + info.first_page = 0 + info.last_page = Math.max(0, info.max - info.limit) + info.sortOptions = info.sortOptions + if (info.offset > 0) { + info.prev_page = Math.max(0, info.offset - info.limit) + } + else { + info.prev_page = -1 + } + if (info.count == info.limit && info.offset + info.limit < info.max) { + info.next_page = info.offset + info.limit + } + else { + info.next_page = -1 + } + }, + + index: function(req, res){ + res.render('staff/index') + }, + + // /staff/users/ + // /staff/users/:username + users: { + index: function(req, res){ + res.locals.pagination.count = res.locals.users.length + res.locals.pagination.max = res.locals.userCount + staff.paginate(req, res) + res.render('staff/users/index') + }, + show: function(req, res){ + if (res.locals.profile) { + res.render('staff/users/show', { + profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) + }) + } + else { + res.render('staff/users/show_404') + } + }, + media: function(req, res){ + if (res.locals.profile) { + res.locals.pagination.count = res.locals.media.length + res.locals.pagination.max = res.locals.profile.mediaCount + staff.paginate(req, res) + res.render('staff/users/media') + } + else { + res.render('staff/users/show_404') + } + }, + blessSelf: function(req, res){ + req.user.isStaff = true + req.user.save(function(err, user){ + res.json({ state: user.isStaff }) + }) + }, + bless: function(req, res){ + res.locals.profile.isStaff = req.body.state == "true" + res.locals.profile.save(function(err, user){ + res.json({ state: user.isStaff }) + }) + }, + }, + + // /staff/projects/ + // /staff/projects/:name + projects: { + index: function(req, res){ + res.locals.pagination.count = res.locals.projects.length + res.locals.pagination.max = res.locals.projectCount + staff.paginate(req, res) + res.render('staff/projects/index') + }, + show: function(req, res){ + if (res.locals.project) { + res.render('staff/projects/show', { + projectJSON: util.escape( JSON.stringify( res.locals.project ) ), + projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), + collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), + }) + } + else { + res.render('staff/projects/show_404') + } + }, + feature: function(req, res){ + res.locals.project.featured = req.body.state == "true" + res.locals.project.save(function(err, project){ + res.json({ state: project.featured }) + }) + }, + }, + + // /staff/layouts/ + // /staff/layouts/:name + layouts: { + index: function(req, res){ + res.locals.pagination.count = res.locals.layouts.length + res.locals.pagination.max = res.locals.layoutCount + staff.paginate(req, res) + res.render('staff/layouts/index') + }, + show: function(req, res){ + if (res.locals.layout) { + res.render('staff/layouts/show', { + }) + } + else { + res.render('staff/layouts/show_404') + } + }, + make_stock: function(req, res){ + res.locals.layout.is_stock = req.body.state == "true" + res.locals.layout.save(function(err, layout){ + res.json({ state: layout.is_stock }) + }) + }, + }, + + + media: { + index: function(req, res){ + res.locals.pagination.count = res.locals.media.length + res.locals.pagination.max = res.locals.mediaCount + staff.paginate(req, res) + res.render('staff/media/index') + }, + show: function(req, res){ + if (res.locals.media) { + res.render('staff/media/show', { + mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), + mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), + }) + } + else { + res.render('staff/media/show_404') + } + }, + }, + + plans: { + index: function(req, res){ + res.locals.fields = staff.fields.plans.split(" ") + res.locals.permissions = staff.fields.plans_permissions.split(" ") + res.render('staff/plans/index') + }, + new: function(req, res){ + res.locals.plan = new Plan () + res.render('staff/plans/new') + }, + edit: function(req, res){ + res.locals.plan = req.plan + res.render('staff/plans/edit') + }, + create: function(req, res){ + var plan = new Plan () + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + data.permissions = {} + permissions.forEach(function(field){ + data.permissions[field] = data["permissions_" + field].length == 2 + }) + + new Plan (data).save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() + res.redirect("/staff/plans/") + }) + }, + update: function(req, res){ + var fields = staff.fields.plans.split(" ") + var permissions = staff.fields.plans_permissions.split(" ") + + var data = util.cleanQuery(req.body) + data.name = util.sanitize(data.name) + data.slug = util.sanitize(data.slug.toLowerCase()) + + _.extend(req.plan, data) + permissions.forEach(function(field){ + req.plan.permissions[field] = data["permissions_" + field].length == 2 + }) + + req.plan.save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + middleware.updatePlans() + res.redirect("/staff/plans/") + }) + }, + }, + + subscriptions: { + index: function(req, res){ + res.locals.pagination.count = res.locals.subscriptions.length + res.locals.pagination.max = res.locals.subscriptionCount + staff.paginate(req, res) + res.render('staff/subscriptions/index') + }, + show: function(req, res){ + res.render('staff/subscriptions/show') + }, + }, + +} diff --git a/server/lib/views/staff/middleware.js b/server/lib/views/staff/middleware.js new file mode 100644 index 0000000..5c74d0b --- /dev/null +++ b/server/lib/views/staff/middleware.js @@ -0,0 +1,421 @@ + +var User = require('../../schemas/User'), + Project = require('../../schemas/Project'), + Media = require('../../schemas/Media'), + Collaborator = require('../../schemas/Collaborator'), + Plan = require('../../schemas/Plan'), + Subscription = require('../../schemas/Subscription'), + Layout = require('../../schemas/Layout'), + util = require('../../util'), + fields = require('./fields'), + helpers = require('./helpers'), + defaults = require('./defaults'), + _ = require('lodash'), + moment = require('moment'); + + +var middleware = module.exports = { + + ensureUsers: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var initial = util.sanitize(req.query.initial) + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "last_seen", "username"] + switch (req.query.sort) { + case 'date': + sort = {'created_at': -1} + break + case 'last_seen': + sort = {'last_seen': -1} + break + case 'username': + default: + sort = {'username': 1} + paginationInfo.sort = "username" + break + } + if (initial) { + if (initial == "?") { + criteria.username = new RegExp('^[$a-zA-Z]', "i") + } + else { + criteria.username = new RegExp('^' + initial, "i") + } + } + User.find(criteria) + .select(fields.user) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, users) { + res.locals.users = users.map(helpers.user) + if (! res.locals.users.length) { + if (initial) { + res.locals.opt.error = "No users found starting with " + initial.toUpperCase() + "" + } + else { + res.locals.opt.error = "No users found" + } + } + next() + }) + }, + + ensureRecentUsers: function(req, res, next){ + var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } + middleware.ensureUsers(dreq, res, next) + }, + + ensureProjects: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Project.find(criteria) + .select(fields.project) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, projects) { + res.locals.projects = projects.map(helpers.project) + next() + }) + }, + + ensureLayouts: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + default: + case 'date': + sort = {'updated_at': -1} + break + case 'name': + paginationInfo.sort = "name" + sort = {'slug': 1} + break + } + Layout.find(criteria) + .select(fields.layout) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, layouts) { + res.locals.layouts = layouts.map(helpers.layout) + next() + }) + }, + + ensureMedia: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date"] + switch (req.query.sort) { + default: + case 'date': + paginationInfo.sort = "date" + sort = {'created_at': -1} + break + } + Media.find(criteria) + // .select(fields.media) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, media) { + res.locals.media = media.map(helpers.media) + next() + }) + }, + + ensureSubscriptions: function(req, res, next){ + var paginationInfo = res.locals.pagination = {} + var criteria = req.criteria || {} + var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) + var offset = paginationInfo.offset = Number(req.query.offset) || 0 + var sort + paginationInfo.sort = req.query.sort + paginationInfo.sortOptions = ["date", "name"] + switch (req.query.sort) { + case 'created': + sort = {'created_at': -1} + break + default: + case 'date': + sort = {'updated_at': -1} + break + } + Subscription.find(criteria) + .select(fields.project) + .sort(sort) + .skip(offset) + .limit(limit) + .exec(function (err, subscriptions) { + res.locals.subscriptions = subscriptions.map(helpers.subscription) + next() + }) + }, + + ensurePlans: function(req, res, next){ + Plan.find({}).sort({ 'level': -1 }).exec(function (err, plans) { + res.locals.plans = (plans || []).map(helpers.plan) + res.locals.plans.sort(function(a,b){ return a.monthly_price }) + next() + }) + }, + ensurePlan: function (req, res, next) { + if (req.params.slug) { + Plan.findOne({ slug: req.params.slug }, function(err, plan){ + if (err || ! plan) { + console.error(err) + res.redirect("/staff/plans/") + } + else { + req.plan = plan + next() + } + }) + } + else { + res.redirect("/staff/plans/") + } + }, + + ensureSubscription: function (req, res, next) { + if (req.params.id) { + Subscription.findOne({ _id: req.params.id }, function(err, subscription){ + if (err || ! subscription) { + console.error(err) + res.redirect("/staff/subscriptions/") + } + else { + req.subscription = subscription + next() + } + }) + } + else { + res.redirect("/staff/subscriptions/") + } + }, + + ensureRecentProjects: function(req, res, next){ + var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } + middleware.ensureProjects(dreq, res, next) + }, + + ensureProjectsUsers: function(req, res, next){ + if (! res.locals.projects || ! res.locals.projects.length) { return next() } + middleware.ensureObjectsUsers(res.locals.projects, next) + }, + + ensureLayoutsUsers: function(req, res, next){ + if (! res.locals.layouts || ! res.locals.layouts.length) { return next() } + middleware.ensureObjectsUsers(res.locals.layouts, next) + }, + + ensureSubscriptionsUsers: function(req, res, next){ + if (! res.locals.subscriptions || ! res.locals.subscriptions.length) { return next() } + middleware.ensureObjectsUsers(res.locals.subscriptions, next) + }, + + ensureMediaUsers: function(req, res, next){ + if (! res.locals.media || ! res.locals.media.length) { return next() } + middleware.ensureObjectsUsers(res.locals.media, next) + }, + + ensureSubscriptionUser: function(req, res, next){ + if (! res.locals.subscription) { return next() } + middleware.ensureObjectsUsers([ res.locals.subscription ], function(){ + next() + }) + }, + + ensureMediaUser: function(req, res, next){ + if (! res.locals.media) { return next() } + middleware.ensureObjectsUsers([ res.locals.media ], function(){ + res.locals.mediaUser = res.locals.media.User + next() + }) + }, + + ensureObjectsUsers: function(objects, next){ + if (! objects) { return next () } + var dedupe = {}, user_ids + objects.forEach(function(obj){ + dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] + dedupe[ obj.user_id ].push(obj) + }) + user_ids = _.keys(dedupe) + User.find({ _id: { $in: user_ids } }) + .select(fields.user) + .exec(function (err, users) { + if (! users) { return next () } + users.forEach(function(user){ + dedupe[user._id].forEach(function(obj){ + obj.user = user + }) + }) + next() + }) + }, + + ensureProfile: function(req, res, next){ + var username = req.params.username + if (username) { + User.findOne({ username: username }, function (err, user) { + if (user) { + res.locals.profile = req.method == "GET" ? helpers.user(user) : user + } + else { + res.locals.profile = null + } + next() + }) + } + else { + res.locals.profile = null + next() + } + }, + + ensureSingleMedia: function(req, res, next){ + var id = req.params.id + if (id) { + Media.findOne({ _id: id }, function (err, media) { + if (media) { + res.locals.media = req.method == "GET" ? helpers.media(media) : media + } + else { + res.locals.media = null + } + next() + }) + } + else { + res.locals.media = null + next() + } + }, + + ensureUsersCount: function(req, res, next){ + User.count({}, function(err, count){ + res.locals.userCount = count || 0 + next() + }) + }, + + ensureProjectsCount: function(req, res, next){ + Project.count({}, function(err, count){ + res.locals.projectCount = count || 0 + next() + }) + }, + + ensureLayoutsCount: function(req, res, next){ + Layout.count({}, function(err, count){ + res.locals.layoutCount = count || 0 + next() + }) + }, + + ensureMediaCount: function(req, res, next){ + Media.count({}, function(err, count){ + res.locals.mediaCount = count || 0 + next() + }) + }, + + ensureProfileProjectCount: function(req, res, next){ + if (! res.locals.profile) { return next() } + Project.count({ user_id: res.locals.profile._id}, function(err, count){ + res.locals.profile.projectCount = count || 0 + next() + }) + }, + + ensureProfileMediaCount: function(req, res, next){ + if (! res.locals.profile) { return next() } + Media.count({ user_id: res.locals.profile._id}, function(err, count){ + res.locals.profile.mediaCount = count || 0 + next() + }) + }, + + ensureProfileProjects: function(req, res, next){ + if (! res.locals.profile) { return next() } + Project.find({ user_id: res.locals.profile._id }, fields.project, function(err, projects){ + res.locals.projects = projects.map(helpers.project) + next() + }) + }, + + ensureProfileMedia: function(req, res, next){ + if (! res.locals.profile) { return next() } + req.criteria = { user_id: res.locals.profile._id } + middleware.ensureMedia(req, res, next) + }, + + ensureProject: function(req, res, next){ + res.locals.project = req.project + next() + }, + + ensureProjectUser: function(req, res, next){ + if (! res.locals.project) { return next() } + User.findOne({ _id: res.locals.project.user_id }, fields.user, function(err, user){ + res.locals.projectUser = helpers.user(user) || defaults.user + next() + }) + }, + + ensureProjectCollaborators: function(req, res, next){ + if (! res.locals.project) { + res.locals.collaborators = [] + return next() + } + Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ + res.locals.collaborators = collaborators || [] + next() + }) + }, + + ensureLayout: function(req, res, next){ + res.locals.layout = req.layout + next() + }, + ensureLayoutUser: function(req, res, next){ + if (! res.locals.layout) { return next() } + User.findOne({ _id: res.locals.layout.user_id }, fields.user, function(err, user){ + res.locals.layoutUser = helpers.user(user) || defaults.user + next() + }) + }, + +} \ No newline at end of file diff --git a/views/staff/projects/index.ejs b/views/staff/projects/index.ejs index 1d309ce..e4ba469 100644 --- a/views/staff/projects/index.ejs +++ b/views/staff/projects/index.ejs @@ -7,7 +7,7 @@
    [[ include ../_pagination ]] -[[ include ../_layouts ]] +[[ include ../_projects ]] [[ include ../_pagination ]] [[ include ../_footer ]] -- cgit v1.2.3-70-g09d2 From dd4f0178c7bcb5d14e1308e3877c5ab02eddf000 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 12 Aug 2015 12:37:49 -0400 Subject: modify webhook to support custom plans --- .../javascripts/ui/site/EditSubscriptionModal.js | 1 + server/lib/api/subscription.js | 1 + server/lib/schemas/Subscription.js | 1 + server/lib/schemas/User.js | 1 + server/lib/views/staff/middleware.js | 2 +- server/lib/webhook/webhook.js | 24 ++++++++++++++++------ views/staff/subscriptions/index.ejs | 3 +++ 7 files changed, 26 insertions(+), 7 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 3a20234..1033114 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -96,6 +96,7 @@ var EditSubscriptionModal = ModalView.extend({ free: 0, basic: 1, pro: 2, + custom: 3, }, loaded: false, diff --git a/server/lib/api/subscription.js b/server/lib/api/subscription.js index 9c2d6ef..c2fff4c 100644 --- a/server/lib/api/subscription.js +++ b/server/lib/api/subscription.js @@ -16,6 +16,7 @@ var plan_levels = { free: 0, basic: 1, pro: 2, + custom: 3, } var subscription = module.exports = { diff --git a/server/lib/schemas/Subscription.js b/server/lib/schemas/Subscription.js index 355bbe2..bf43e8b 100644 --- a/server/lib/schemas/Subscription.js +++ b/server/lib/schemas/Subscription.js @@ -9,6 +9,7 @@ var mongoose = require('mongoose'), var SubscriptionSchema = new mongoose.Schema({ user_id: { type: mongoose.Schema.ObjectId, index: true }, + plan_code: { type: String, default: "" }, plan_type: { type: String, default: "free" }, plan_period: { type: String, default: "monthly" }, diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 4b6ff39..e6e7f03 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -55,6 +55,7 @@ var UserSchema = new mongoose.Schema({ default: "", }, + plan_code: { type: String, default: "" }, plan_level: { type: Number, default: 0 }, plan_type: { type: String, default: "free" }, last_charged: { type: Date, default: null }, diff --git a/server/lib/views/staff/middleware.js b/server/lib/views/staff/middleware.js index 5c74d0b..1ea98e9 100644 --- a/server/lib/views/staff/middleware.js +++ b/server/lib/views/staff/middleware.js @@ -40,7 +40,7 @@ var middleware = module.exports = { } if (initial) { if (initial == "?") { - criteria.username = new RegExp('^[$a-zA-Z]', "i") + criteria.username = new RegExp('^[^a-zA-Z]', "i") } else { criteria.username = new RegExp('^' + initial, "i") diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index 58a13ca..bd51dac 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -26,10 +26,11 @@ var xml_bodyparser = require('express-xml-bodyparser'); var parser = new xml2js.Parser(); var subscribe = module.exports = { - plan_level: { + plan_levels: { free: 0, basic: 1, pro: 2, + custom: 3, }, callbacks: { @@ -62,19 +63,30 @@ var subscribe = module.exports = { Subscription.findOne({ "uuid": uuid }, function(err, old_subscriber){ // if (err) return; - var plan = subscrip.plan[0].plan_code[0].split("-") - var plan_type = plan[0] - var plan_period = plan[1] + var plan, plan_type, plan_code + var plan_code = subscrip.plan[0].plan_code[0] + if (plan_code.indexOf("-") !== -1) { + plan = plan_code.split("-") + plan_type = plan[0] + plan_period = plan[1] + } + else { + plan_type = "custom" + plan_period = "monthly" + } + + user.plan_code = plan_code user.plan_type = plan_type - user.plan_level = subscribe.plan_level[plan_type] + user.plan_level = subscribe.plan_levels[plan_type] var subscriber = old_subscriber || new Subscription () subscriber.uuid = uuid subscriber.user_id = user._id + subscriber.plan_code = plan_code subscriber.plan_type = plan_type subscriber.plan_period = plan_period - subscriber.plan_level = subscribe.plan_level[plan_type] + subscriber.plan_level = subscribe.plan_levels[plan_type] subscriber.add_ons = [] var add_ons = subscrip.subscription_add_ons[0].subscription_add_on if (add_ons) { diff --git a/views/staff/subscriptions/index.ejs b/views/staff/subscriptions/index.ejs index 3efffb5..adf148c 100644 --- a/views/staff/subscriptions/index.ejs +++ b/views/staff/subscriptions/index.ejs @@ -26,6 +26,9 @@ [[- subscription.user.last_seen ]] + + [[- subscription.plan_code ]] + [[ }) ]] -- cgit v1.2.3-70-g09d2 From cc3d0bf036dc934494bf517ebae88bd8544b9b06 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 12 Aug 2015 13:27:07 -0400 Subject: add artist privilege --- .../javascripts/ui/site/EditSubscriptionModal.js | 1 + public/assets/javascripts/ui/site/StaffView.js | 23 +++++++++++++++++++++- server/lib/schemas/User.js | 1 + server/lib/views/staff/index.js | 16 ++++++++++++++- server/lib/webhook/webhook.js | 1 + views/staff/users/show.ejs | 11 ++++++++++- 6 files changed, 50 insertions(+), 3 deletions(-) diff --git a/public/assets/javascripts/ui/site/EditSubscriptionModal.js b/public/assets/javascripts/ui/site/EditSubscriptionModal.js index 1033114..c1dc9f8 100644 --- a/public/assets/javascripts/ui/site/EditSubscriptionModal.js +++ b/public/assets/javascripts/ui/site/EditSubscriptionModal.js @@ -97,6 +97,7 @@ var EditSubscriptionModal = ModalView.extend({ basic: 1, pro: 2, custom: 3, + artist: 4, }, loaded: false, diff --git a/public/assets/javascripts/ui/site/StaffView.js b/public/assets/javascripts/ui/site/StaffView.js index 59649e3..97f86c2 100644 --- a/public/assets/javascripts/ui/site/StaffView.js +++ b/public/assets/javascripts/ui/site/StaffView.js @@ -5,12 +5,14 @@ var StaffView = View.extend({ "click #toggle-staff": "toggleStaff", "click #toggle-featured": "toggleFeatured", "click #toggle-stock": "toggleStock", + "click #toggle-artist": "toggleArtist", }, initialize: function() { this.$toggleStaff = $("#toggle-staff") this.$toggleFeatured = $("#toggle-featured") this.$toggleStock = $("#toggle-stock") + this.$toggleArtist = $("#toggle-artist") this.$mediaEmbed = $("#media-embed") if (this.$toggleStaff.length && this.$toggleStaff.data().isstaff) { this.$toggleStaff.html("Is Staff") @@ -21,6 +23,9 @@ var StaffView = View.extend({ if (this.$toggleStock.length && this.$toggleStock.data().stock) { this.$toggleStock.html("Layout is Stock") } + if (this.$toggleArtist.length && this.$toggleArtist.data().isartist) { + this.$toggleArtist.html("Is Artist") + } if (this.$mediaEmbed.length) { var media = this.$mediaEmbed.data() this.$mediaEmbed.html( Parser.tag( media ) ) @@ -75,7 +80,6 @@ var StaffView = View.extend({ }, toggleStock: function(){ - console.log("stock") var state = ! this.$toggleStock.data().stock $.ajax({ type: "put", @@ -93,4 +97,21 @@ var StaffView = View.extend({ }) }, + toggleArtist: function(){ + var state = ! this.$toggleArtist.data().isartist + $.ajax({ + type: "put", + dataType: "json", + url: window.location.href + "/artist", + data: { + state: state, + _csrf: $("#_csrf").val(), + }, + success: function(data){ + this.$toggleArtist.data("stock", data.state) + this.$toggleArtist.html(data.state ? "Is Artist" : "Make Artist") + $("#isArtist").html(data.state ? "yes" : "no") + }.bind(this) + }) + }, }) diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index e6e7f03..829b360 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -67,6 +67,7 @@ var UserSchema = new mongoose.Schema({ twitterName: { type: String, default: "" }, facebookUrl: { type: String, default: "" }, isStaff: { type: Boolean, default: false }, + isArtist: { type: Boolean, default: false }, subscription_id: { type: mongoose.Schema.ObjectId }, created_at: { type: Date }, updated_at: { type: Date }, diff --git a/server/lib/views/staff/index.js b/server/lib/views/staff/index.js index 6a56238..033fc88 100644 --- a/server/lib/views/staff/index.js +++ b/server/lib/views/staff/index.js @@ -75,7 +75,15 @@ var staff = module.exports = { staff.users.bless ); - + app.put('/staff/users/:username/artist', + middleware.ensureAuthenticated, + middleware.ensureIsStaff, + + staff.middleware.ensureProfile, + + staff.users.make_artist + ); + if (app.get('env') === 'development') { app.get('/staff/authorize', middleware.ensureAuthenticated, @@ -304,6 +312,12 @@ var staff = module.exports = { res.json({ state: user.isStaff }) }) }, + make_artist: function(req, res){ + res.locals.profile.isArtist = req.body.state == "true" + res.locals.profile.save(function(err, user){ + res.json({ state: user.isArtist }) + }) + }, }, // /staff/projects/ diff --git a/server/lib/webhook/webhook.js b/server/lib/webhook/webhook.js index bd51dac..896d836 100644 --- a/server/lib/webhook/webhook.js +++ b/server/lib/webhook/webhook.js @@ -31,6 +31,7 @@ var subscribe = module.exports = { basic: 1, pro: 2, custom: 3, + artist: 4, }, callbacks: { diff --git a/views/staff/users/show.ejs b/views/staff/users/show.ejs index e441109..a434b57 100644 --- a/views/staff/users/show.ejs +++ b/views/staff/users/show.ejs @@ -35,7 +35,7 @@ plan - [[- profile.plan_type ]] + [[- profile.plan_code ]] @@ -101,12 +101,21 @@ [[- profile.isStaff ? "yes" : "no" ]] + + + is artist? + + + [[- profile.isArtist ? "yes" : "no" ]] + +

    [[ if (String(user._id) != String(profile._id)) { ]] + [[ } ]]
    -- cgit v1.2.3-70-g09d2 From 9ba29a587bf0722db82e5caf1b1cf4e5596003b6 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 12 Aug 2015 18:38:12 -0400 Subject: functioning blueprint scaler --- .../javascripts/rectangles/engine/map/draw.js | 2 +- .../rectangles/engine/map/tools/line.js | 49 ++++++++++++ .../assets/javascripts/rectangles/models/rect.js | 6 ++ .../javascripts/ui/blueprint/BlueprintScaler.js | 91 ++++++++++++++++++++-- .../javascripts/ui/blueprint/BlueprintView.js | 3 + server/lib/schemas/Layout.js | 1 + views/controls/blueprint/editor.ejs | 4 +- views/partials/scripts.ejs | 1 + 8 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 public/assets/javascripts/rectangles/engine/map/tools/line.js diff --git a/public/assets/javascripts/rectangles/engine/map/draw.js b/public/assets/javascripts/rectangles/engine/map/draw.js index 11ba3f8..cc2f4d8 100644 --- a/public/assets/javascripts/rectangles/engine/map/draw.js +++ b/public/assets/javascripts/rectangles/engine/map/draw.js @@ -198,7 +198,7 @@ Map.Draw = function(map, opt){ // - function line (x,y,a,b,translation){ + var line = draw.line = function (x,y,a,b,translation){ if (translation) { x += translation.a a += translation.a diff --git a/public/assets/javascripts/rectangles/engine/map/tools/line.js b/public/assets/javascripts/rectangles/engine/map/tools/line.js new file mode 100644 index 0000000..8f409a8 --- /dev/null +++ b/public/assets/javascripts/rectangles/engine/map/tools/line.js @@ -0,0 +1,49 @@ +var LineTool = MapTool.extend(function(base){ + var exports = {} + + var selected_point = null + + var line = exports.line = [] + + var can_drag, dragging + + exports.down = function(e, cursor){ + this.cursor = cursor + switch (line.length) { + case 0: + line[0] = cursor.x_component() + can_drag = true + break + case 1: + line[1] = cursor.x_component() + can_drag = false + break + case 2: + line[0] = cursor.x_component() + line.pop() + can_drag = true + break + } + } + + exports.move = function(e, cursor){ + this.cursor = cursor + } + + exports.drag = function(e, cursor){ + if (dragging) { + line[1].a = cursor.x.b + line[1].b = cursor.y.b + } + else if (can_drag && cursor.magnitude() > 10/map.zoom) { + line[1] = cursor.y_component() + dragging = true + } + } + + exports.up = function(e, cursor){ + can_drag = dragging = false + } + + return exports +}) \ No newline at end of file diff --git a/public/assets/javascripts/rectangles/models/rect.js b/public/assets/javascripts/rectangles/models/rect.js index c667cf5..92c8c9e 100644 --- a/public/assets/javascripts/rectangles/models/rect.js +++ b/public/assets/javascripts/rectangles/models/rect.js @@ -39,6 +39,12 @@ Rect.prototype.clone = function(){ return new Rect( this.x.clone(), this.y.clone() ) } + Rect.prototype.x_component = function(){ + return new vec2( this.x.a, this.y.a ) + } + Rect.prototype.y_component = function(){ + return new vec2( this.x.b, this.y.b ) + } Rect.prototype.assign = function(r) { this.x.assign(r.x) this.y.assign(r.y) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js index a81c89b..addf9a9 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js @@ -1,10 +1,13 @@ -var BlueprintScaler = ModalView.extend({ +var BlueprintScaler = ModalFormView.extend({ el: ".blueprintScaler", + method: "/api/media/scale", + events: { "change [name=blueprint-dimensions]": "changeDimensions", "change [name=blueprint-units]": "changeUnits", + "click .uploadNewBlueprint": "showBlueprintUpload", "click #saveBlueprint": "save", }, @@ -12,6 +15,7 @@ var BlueprintScaler = ModalView.extend({ this.$blueprintMap = this.$("#blueprintMap") this.$blueprintDimensionsRapper = this.$("#blueprintDimensions") this.$dimensions = this.$("[name=blueprint-dimensions]") + this.$pixels = this.$("[name=blueprint-pixels]") this.$units = this.$("[name=blueprint-units]") this.$save = this.$("#saveBlueprint") @@ -24,23 +28,40 @@ var BlueprintScaler = ModalView.extend({ zoom_min: -6.2, zoom_max: 1, }) - map.ui.add_tool("arrow", new ArrowTool) - map.ui.add_tool("position", new PositionTool) - map.ui.set_tool("position") + this.lineTool = new LineTool + map.ui.add_tool("line", this.lineTool) + map.ui.set_tool("line") scene = scene || { camera: { x: 0, y: 0, z: 0 } } this.floorplan = new MX.Image () - this.animate() + this.animating = false + }, + + showBlueprintUpload: function(){ + this.parent.blueprintUpload.show() }, pick: function(media){ + this.media = media + + if (!! media.scale) { + this.parent.useFloorplan(media) + } + this.floorplan.load({ media: media, keepImage: true }) + + if (! this.animating) { + this.animating = true + this.animate() + } }, animate: function(t){ requestAnimationFrame(this.animate.bind(this)) + + if (! this.animating) return var dt = t - this.last_t this.last_t = t @@ -53,6 +74,27 @@ var BlueprintScaler = ModalView.extend({ this.map.draw.translate() this.floorplan.draw(this.map.draw.ctx, true) + + this.map.draw.ctx.strokeStyle = "#f00" + this.map.draw.ctx.lineWidth = 2/map.zoom + switch (this.lineTool.line.length) { + case 1: + this.map.draw.line( + this.lineTool.line[0].a, + this.lineTool.line[0].b, + this.lineTool.cursor.x.a, + this.lineTool.cursor.y.a + ) + break + case 2: + this.map.draw.line( + this.lineTool.line[0].a, + this.lineTool.line[0].b, + this.lineTool.line[1].a, + this.lineTool.line[1].b + ) + break + } this.map.draw.coords() @@ -62,10 +104,47 @@ var BlueprintScaler = ModalView.extend({ }, changeDimensions: function(){ + app.units = this.$units.val() + this.$dimensions.unitVal() }, changeUnits: function(){ + app.units = this.$units.val() + this.$dimensions.resetUnitVal() + }, + lineLength: function(){ + if (this.lineTool.line.length !== 2) return 0 + var line = this.lineTool.line + return dist( line[0].a, line[0].b, line[1].a, line[1].b ) + } + + validate: function(){ + var val = this.$dimensions.unitVal() + var errors = [] + if (! this.lineLength()) { + errors.push("no line") + alert("Please click two corners of a wall and then specify how long it is in feet or meters.") + } + else if (val == 0) { + errors.push("no measurement") + alert("Please tell us how long the wall is in feet or meters.") + } + return errors }, - save: function(){ + + showErrors: function(){}, + + serialize: function(){ + var fd = new FormData() + fd.append( "_id", this.media._id) + fd.append( "units", this.$units.val() ) + fd.append( "scale", this.$dimensions.unitVal() / this.lineLength() ) + fd.append( "_csrf", $("[name=_csrf]").val()) + return fd + }, + + success: function(){ + this.animating = false + this.parent.useFloorplan(media) }, }) diff --git a/public/assets/javascripts/ui/blueprint/BlueprintView.js b/public/assets/javascripts/ui/blueprint/BlueprintView.js index a803f12..6b204e5 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintView.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintView.js @@ -33,6 +33,9 @@ var BlueprintView = View.extend({ hideExtras: function(){ }, + + useFloorplan: function(media){ + }, pickWall: function(wall, pos){ }, diff --git a/server/lib/schemas/Layout.js b/server/lib/schemas/Layout.js index cff1d78..e15e188 100644 --- a/server/lib/schemas/Layout.js +++ b/server/lib/schemas/Layout.js @@ -23,6 +23,7 @@ var LayoutSchema = new mongoose.Schema({ photo: { type: String, }, + media: mongoose.Schema.Types.Mixed, rooms: [mongoose.Schema.Types.Mixed], startPosition: mongoose.Schema.Types.Mixed, viewHeight: { type: Number }, diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs index 308b4c8..3e0c097 100644 --- a/views/controls/blueprint/editor.ejs +++ b/views/controls/blueprint/editor.ejs @@ -99,8 +99,8 @@ body {

    - - + + - -
    - +
    +
    + + + +
    + +
    -- cgit v1.2.3-70-g09d2 From 6b3d07293bf674703b286cb396049fb8e83b86b7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 14 Aug 2015 16:37:39 -0400 Subject: AnimatedView --- .../javascripts/ui/blueprint/BlueprintScaler.js | 29 ++++----------- public/assets/javascripts/ui/lib/AnimatedView.js | 31 ++++++++++++++++ views/blueprint.ejs | 33 +++++++++++++++++ views/builder.ejs | 16 -------- views/controls/blueprint/editor.ejs | 43 ++++++++++------------ views/modal.ejs | 1 - views/partials/scripts.ejs | 1 + 7 files changed, 93 insertions(+), 61 deletions(-) create mode 100644 public/assets/javascripts/ui/lib/AnimatedView.js create mode 100644 views/blueprint.ejs diff --git a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js index c393cfb..741f4fb 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintScaler.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintScaler.js @@ -1,5 +1,5 @@ -var BlueprintScaler = ModalFormView.extend({ +var BlueprintScaler = ModalFormView.extend(AnimatedView.prototype).extend({ el: ".blueprintScaler", action: "/api/media/scale", @@ -20,7 +20,7 @@ var BlueprintScaler = ModalFormView.extend({ this.$units = this.$("[name=blueprint-units]") this.$save = this.$("#saveBlueprint") - this.map = map = new Map ({ + this.map = new Map ({ type: "ortho", el: this.$blueprintMap.get(0), width: window.innerWidth, @@ -30,14 +30,12 @@ var BlueprintScaler = ModalFormView.extend({ zoom_max: 1, }) this.lineTool = new LineTool - map.ui.add_tool("line", this.lineTool) - map.ui.set_tool("line") + this.map.ui.add_tool("line", this.lineTool) + this.map.ui.set_tool("line") scene = scene || { camera: { x: 0, y: 0, z: 0 } } this.floorplan = new MX.Image () - - this.animating = false }, showBlueprintUpload: function(){ @@ -50,27 +48,16 @@ var BlueprintScaler = ModalFormView.extend({ if (!! media.units) { this.parent.useFloorplan(media) this.hide() + this.stopAnimating() return } this.floorplan.load({ media: media, keepImage: true }) - if (! this.animating) { - this.animating = true - this.animate() - } + this.startAnimating() }, - animate: function(t){ - requestAnimationFrame(this.animate.bind(this)) - - if (! this.animating) return - - var dt = t - this.last_t - this.last_t = t - - if (! t) return - + animate: function(t, dt){ this.map.update(t) this.map.draw.ctx.save() @@ -147,7 +134,7 @@ var BlueprintScaler = ModalFormView.extend({ }, success: function(){ - this.animating = false + this.stopAnimating() this.parent.useFloorplan(this.media) this.hide() }, diff --git a/public/assets/javascripts/ui/lib/AnimatedView.js b/public/assets/javascripts/ui/lib/AnimatedView.js new file mode 100644 index 0000000..3c50b0a --- /dev/null +++ b/public/assets/javascripts/ui/lib/AnimatedView.js @@ -0,0 +1,31 @@ +var AnimatedView = View.extend({ + + _animating: false, + last_t: 0, + + startAnimating: function(){ + if (this._animating) return + this._animating = true + this._animate() + }, + + stopAnimating: function(){ + this._animating = false + }, + + _animate: function(t){ + if (! this._animating) return + + requestAnimationFrame(this._animate.bind(this)) + + var dt = t - this.last_t + this.last_t = t + + if (! t) return + + this.animate(t, dt) + }, + + animate: function(t, dt){}, + +}) \ No newline at end of file diff --git a/views/blueprint.ejs b/views/blueprint.ejs new file mode 100644 index 0000000..371d66f --- /dev/null +++ b/views/blueprint.ejs @@ -0,0 +1,33 @@ + + + + VValls + [[ include partials/meta ]] + + + +
    + +
    + [[ include partials/header ]] + +
    + [[ include controls/builder/info ]] + [[ include controls/builder/toolbar ]] + [[ include controls/builder/settings ]] + [[ include controls/blueprint/editor ]] +
    + +
    +
    +
    +
    +
    + + [[ include partials/confirm-modal ]] + [[ include projects/layouts-modal ]] + [[ include partials/sign-in ]] + + +[[ include partials/scripts ]] + diff --git a/views/builder.ejs b/views/builder.ejs index 0ba4238..6a31e22 100644 --- a/views/builder.ejs +++ b/views/builder.ejs @@ -17,22 +17,6 @@ [[ include controls/builder/settings ]]
    - -
    diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs index 77c958a..e18f501 100644 --- a/views/controls/blueprint/editor.ejs +++ b/views/controls/blueprint/editor.ejs @@ -67,7 +67,7 @@ body {
    -
    +
    @@ -90,30 +90,27 @@ body {
    -
    -
    - Please tell us the scale of your blueprint. - Click two corners of a wall, and then enter how long the wall is. -

    - You can also upload another blueprint. -

    +
    + Please tell us the scale of your blueprint. + Click two corners of a wall, and then enter how long the wall is. +

    + You can also upload another blueprint. +

    -
    -
    - - - -
    - -
    -
    +
    +
    + + + +
    + +
    +
    -
    -
    - +
    diff --git a/views/modal.ejs b/views/modal.ejs index 775ba88..dfc5573 100644 --- a/views/modal.ejs +++ b/views/modal.ejs @@ -10,7 +10,6 @@
    - [[ include controls/blueprint/editor ]] [[ include partials/confirm-modal ]] [[ include partials/sign-in ]] [[ include projects/layouts-modal ]] diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index a0222b5..e0024a4 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -102,6 +102,7 @@ + -- cgit v1.2.3-70-g09d2 From 599b43df07f092b35d25e7adac11db3c3b3d9c76 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Mon, 17 Aug 2015 12:23:39 -0400 Subject: BlueprintEditor --- public/assets/javascripts/ui/_router.js | 7 +- .../javascripts/ui/blueprint/BlueprintEditor.js | 155 +++++++++++++++++++++ .../javascripts/ui/blueprint/BlueprintView.js | 18 +-- server/index.js | 3 + server/lib/views/index.js | 4 + views/blueprint.ejs | 1 + views/controls/blueprint/editor.ejs | 53 ------- views/controls/blueprint/scaler.ejs | 48 +++++++ views/partials/scripts.ejs | 1 + 9 files changed, 227 insertions(+), 63 deletions(-) create mode 100644 public/assets/javascripts/ui/blueprint/BlueprintEditor.js create mode 100644 views/controls/blueprint/scaler.ejs diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 857377c..177e86f 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -38,6 +38,9 @@ var SiteRouter = Router.extend({ "/layout": 'layoutPicker', "/layout/:name": 'layoutEditor', + "/blueprint": 'blueprintEditor', + "/blueprint/:name": 'blueprintEditor', + "/project": 'projectPicker', "/project/new": 'newProject', "/project/new/:layout": 'projectNewWithLayout', @@ -160,13 +163,13 @@ var SiteRouter = Router.extend({ this.readerView.load(name) }, - blueprintEditor: function(e){ + blueprintEditor: function(e, name){ environment.init = environment.minimal app.launch() if (app.unsupported) return this.blueprintView = app.controller = new BlueprintView () - this.blueprintView.load() + this.blueprintView.load(name) }, signup: function(e){ diff --git a/public/assets/javascripts/ui/blueprint/BlueprintEditor.js b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js new file mode 100644 index 0000000..c781495 --- /dev/null +++ b/public/assets/javascripts/ui/blueprint/BlueprintEditor.js @@ -0,0 +1,155 @@ + +var wall_height = 180 +var shapes = new ShapeList +var last_point = new vec2 (0,0) + +var BlueprintEditor = View.extend(AnimatedView.prototype).extend({ + + initialize: function(opt){ + this.parent = opt.parent + + map = new Map ({ + type: "ortho", + el: document.querySelector("#orthographic"), + width: window.innerWidth/2, + height: window.innerHeight, + zoom: -2, + zoom_min: -6.2, + zoom_max: 1, + }) + map.ui.add_tool("arrow", new ArrowTool) + map.ui.add_tool("polyline", new PolylineTool) + map.ui.add_tool("ortho-polyline", new OrthoPolylineTool) + map.ui.add_tool("eraser", new EraserTool) + map.ui.add_tool("position", new PositionTool) + map.ui.placing = false + +/* + $(window).resize(function(){ + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + map.canvas.width = map.dimensions.a = window.innerWidth/2 + map.canvas.height = map.dimensions.b = window.innerHeight/2 + }) +*/ + + var PerspectiveToolbar = new Toolbar (".persp-hud") + PerspectiveToolbar.add("orbit-mode", function(){ + controls.toggle(true) + movements.lock() + }) + PerspectiveToolbar.add("keyboard-mode", function(){ + controls.toggle(false) + movements.unlock() + movements.gravity(true) + cam.rotationX = 0 + cam.rotationY = -cam.rotationY + cam.x = 0 + cam.y = viewHeight + 100 + cam.z = 0 + }) + + var OrthographicToolbar = new Toolbar (".ortho-hud") + OrthographicToolbar.add("arrow-mode", function(){ + map.ui.set_tool("arrow") + }) + OrthographicToolbar.add("polyline-mode", function(){ + map.ui.set_tool("polyline") + }) + OrthographicToolbar.add("ortho-polyline-mode", function(){ + map.ui.set_tool("ortho-polyline") + }) + OrthographicToolbar.add("eraser-mode", function(){ + map.ui.set_tool("eraser") + }) + OrthographicToolbar.pick("ortho-polyline-mode") + }, + + animate: function(t, dt){ + map.update(t) + + movements.update(dt) + controls.update() + scene.update() + + map.draw.ctx.save() + map.draw.translate() + + floorplan.draw(map.draw.ctx, true) + + map.draw.coords() + + if (shapes.workline) { + shapes.workline.draw(map.draw.ctx) + if (map.ui.placing && last_point) { + shapes.workline.draw_line( map.draw.ctx, last_point ) + } + } + + shapes.forEach(function(shape){ + shape.draw(map.draw.ctx) + }) + + map.draw.ctx.strokeStyle = "#f00"; + map.draw.x_at(0,0) + map.draw.mouse(map.ui.mouse.cursor) + map.draw.camera(scene.camera) + + map.draw.ctx.restore() + }, + +}) + +function build () { + scene = new MX.Scene().addTo("#perspective") + scene.camera.radius = 20 + + viewHeight = 100 + + scene.width = window.innerWidth/2 + scene.height = window.innerHeight + scene.perspective = window.innerHeight + + cam = scene.camera + movements = new MX.Movements(cam, viewHeight) + movements.init() + movements.lock() + movements.velocity(8) + app.on("move", function(pos){ + cam.x = pos.x + cam.y = pos.y + cam.z = pos.z + }) + + floorplan = new MX.Image({ + src: "https://s3.amazonaws.com/luckyplop/fbf4295da80f1f66c5e4a248f2ea3e1ce7a22c3d.jpg", + keepImage: true, + rotationX: -PI/2, + rotationY: PI, + }) + scene.add(floorplan) + + // recenter perspective view by rightclicking map + floorplan.el.addEventListener("contextmenu", function(e){ + e.preventDefault() + var offset = offsetFromPoint(e, this) + var x = (offset.left - 0.5) * floorplan.width * floorplan.scale + var z = (offset.top - 0.5) * floorplan.height * floorplan.scale + controls.opt.center.x = -x + controls.opt.center.y = 0 + controls.opt.center.z = -z + }, true) + + scene.update() + + controls = new MX.OrbitCamera({ + el: scene.el, + radius: 3000, + radiusRange: [ 10, 10000 ], + rotationX: PI/4, + rotationY: PI/2, + }) + controls.init() + + animate(0) +} diff --git a/public/assets/javascripts/ui/blueprint/BlueprintView.js b/public/assets/javascripts/ui/blueprint/BlueprintView.js index 6b204e5..0a06fda 100644 --- a/public/assets/javascripts/ui/blueprint/BlueprintView.js +++ b/public/assets/javascripts/ui/blueprint/BlueprintView.js @@ -1,7 +1,9 @@ var BlueprintView = View.extend({ el: "#blueprintView", - + + action: "/api/layout/", + events: { }, @@ -16,14 +18,14 @@ var BlueprintView = View.extend({ }, load: function(name){ -// if (! name || name == "new") { + if (! name || name == "new") { // this.ready({ isNew: true, _id: "new", name: "" }) -// return -// } -// -// name = sanitize(name) -// -// $.get(this.action + name, this.ready.bind(this)) + return + } + + name = sanitize(name) + + $.get(this.action + name, this.ready.bind(this)) }, ready: function(data){ diff --git a/server/index.js b/server/index.js index 0028888..078db8e 100644 --- a/server/index.js +++ b/server/index.js @@ -127,6 +127,9 @@ site.route = function () { app.get('/layout', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.modal) app.get('/layout/:name', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.builder) + app.get('/blueprint', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.blueprint) + app.get('/blueprint/:name', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.blueprint) + app.get('/join/:nonce', middleware.ensureAuthenticated, api.collaborator.join) app.get('/api/collaborator/:slug/index', middleware.ensureAuthenticated, middleware.ensureProject, api.collaborator.index) app.post('/api/collaborator/:slug/create', middleware.ensureAuthenticated, middleware.ensureProject, api.collaborator.create) diff --git a/server/lib/views/index.js b/server/lib/views/index.js index 5241ddb..523f628 100644 --- a/server/lib/views/index.js +++ b/server/lib/views/index.js @@ -84,6 +84,10 @@ var views = module.exports = { res.render('builder') }, + blueprint: function (req, res) { + res.render('blueprint') + }, + modal: function (req, res) { res.render('modal'); }, diff --git a/views/blueprint.ejs b/views/blueprint.ejs index 371d66f..7e13318 100644 --- a/views/blueprint.ejs +++ b/views/blueprint.ejs @@ -16,6 +16,7 @@ [[ include controls/builder/toolbar ]] [[ include controls/builder/settings ]] [[ include controls/blueprint/editor ]] + [[ include controls/blueprint/scaler ]]
    diff --git a/views/controls/blueprint/editor.ejs b/views/controls/blueprint/editor.ejs index e18f501..5334f85 100644 --- a/views/controls/blueprint/editor.ejs +++ b/views/controls/blueprint/editor.ejs @@ -1,8 +1,4 @@