diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-08-14 15:24:34 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-08-14 15:24:34 -0400 |
| commit | 31907c69cc192a23bb409adf5c438ed708db0842 (patch) | |
| tree | 516a88386f96606b1890c83e5083fdb943582a68 | |
| parent | c4c45b64c2c0fc109f4c21effe7f73f5c46a1ae9 (diff) | |
| parent | 63da3ba331aa3d9714151ba5f502e6e1851d75bb (diff) | |
merge
| -rw-r--r-- | public/assets/javascripts/rectangles/engine/scenery/move.js | 8 | ||||
| -rw-r--r-- | public/assets/javascripts/rectangles/engine/scenery/resize.js | 3 | ||||
| -rw-r--r-- | public/assets/javascripts/rectangles/engine/scenery/undo.js | 18 | ||||
| -rw-r--r-- | public/assets/javascripts/rectangles/models/wall.js | 3 | ||||
| -rw-r--r-- | public/assets/javascripts/rectangles/util/minotaur.js | 64 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/_router.js | 1 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/builder/BuilderSettings.js | 3 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorSettings.js | 29 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaEditor.js | 1 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/FormView.js | 28 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/View.js | 17 | ||||
| -rwxr-xr-x | public/assets/stylesheets/app.css | 19 | ||||
| -rw-r--r-- | server/lib/api/projects.js | 23 | ||||
| -rw-r--r-- | views/partials/header.ejs | 4 | ||||
| -rw-r--r-- | views/partials/scripts.ejs | 1 |
15 files changed, 193 insertions, 29 deletions
diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index fa247e1..f2d37d8 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -30,6 +30,9 @@ Scenery.move = function(base){ redo: { id: base.id }, }) + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + Scenery.remove(base.id) return } @@ -81,7 +84,10 @@ Scenery.move = function(base){ undo: oldState, redo: base.serialize(), }) - + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + oldState = null } diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index c5c754a..6b2e52c 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -200,6 +200,9 @@ Scenery.resize = new function(){ redo: obj.serialize(), }) + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + document.body.classList.remove("dragging") } diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 7798550..54ab755 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -4,9 +4,15 @@ type: "create-scenery", undo: function(state){ Scenery.remove(state.id) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, redo: function(state){ Scenery.deserialize([ state ]) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, }, { @@ -19,6 +25,9 @@ if (editor.permissions.resize) { Scenery.resize.show(scenery) } + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, redo: function(state){ var scenery = Scenery.find(state.id) @@ -30,15 +39,24 @@ Scenery.resize.rotate_dots() Scenery.resize.move_dots() } + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, }, { type: "destroy-scenery", undo: function(state){ Scenery.deserialize([ state ]) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, redo: function(state){ Scenery.remove(state.id) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, }, diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index f015a44..b66d5f5 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -59,6 +59,9 @@ undo: { id: scenery.id }, redo: scenery.serialize(), }) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) } else if (Scenery.nextWallpaper) { base.wallpaper() diff --git a/public/assets/javascripts/rectangles/util/minotaur.js b/public/assets/javascripts/rectangles/util/minotaur.js new file mode 100644 index 0000000..039a053 --- /dev/null +++ b/public/assets/javascripts/rectangles/util/minotaur.js @@ -0,0 +1,64 @@ +(function(){ + + var Monitor = function () { + var base = this + base.$el = $("#minotaur") + base.timeout = null + base.delay = 500 + base.objects = {} + + base.init = function () { + base.$el.removeClass() + base.$el.click(base.save) + } + + base.watch = function (object) { + base.objects[object.type] = base.objects[object.type] || {} + base.objects[object.type][object._id] = object + base.clear() + base.timeout = setTimeout(base.save, base.delay) + } + + base.unwatch = function (object) { + if (base.objects[object.type] && base.objects[object.type][object._id]) { + delete base.objects[object.type][object._id] + } + } + + base.clear = function () { + if (base.timeout) clearTimeout(base.timeout) + base.timeout = false + } + + base.save = function () { + var saving = false + base.clear() + + for (var type in base.objects) { + for (var id in base.objects[type]) { + var obj = base.objects[type][id] + if (obj) { + obj.save(null, function(){ base.hide() }, function(){}) + } + delete base.objects[type][id] + saving = true + } + } + + saving ? base.show() : base.hide() + } + + base.show = function () { + base.$el.removeClass().addClass('saving') + } + + base.hide = function () { + base.$el.removeClass() + } + + base.init(); + } + + window.Minotaur = new Monitor (); + +})() diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index d07810e..794079e 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -27,6 +27,7 @@ var SiteRouter = Router.extend({ "/profile": 'profile', "/profile/edit": 'editProfile', + "/profile/:name": 'profile', "/about/:name/edit": 'editDocument', "/about/new": 'newDocument', diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index c551f95..0091454 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -122,6 +122,9 @@ var BuilderSettings = FormView.extend({ this.$name.val(data.name) this.action = this.updateAction + Minotaur.unwatch(this) + Minotaur.hide() + window.history.pushState(null, document.title, "/layout/" + data.slug) }, diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index d6a79fb..e9239e4 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -5,7 +5,7 @@ var EditorSettings = FormView.extend({ createAction: "/api/project/new", updateAction: "/api/project/edit", destroyAction: "/api/project/destroy", - + events: { "keydown": 'stopPropagation', "keydown [name=name]": 'enterSubmit', @@ -32,13 +32,17 @@ var EditorSettings = FormView.extend({ data.rooms && Rooms.deserialize(data.rooms) data.startPosition && scene.camera.move(data.startPosition) - if (! data.isNew) { + if (data.isNew) { + this.$name.val( "Room " + moment().format("DD/MM/YYYY ha") ) + } + else { // console.log(data) + this.thumbnailIsStale() this.$id.val( data._id ) this.$name.val( data.name ) this.$description.val( data.description ) - data.privacy && this.$privacy.find("[value=" + data.privacy + "]").prop('checked', "checked") + data.privacy && this.$privacy.find("[value=" + data.privacy + "]").prop("checked", "checked") data.media && Scenery.deserialize(data.media) } @@ -121,15 +125,32 @@ var EditorSettings = FormView.extend({ fd.append( "walls", JSON.stringify( Rooms.serializeWalls() ) ) fd.append( "media", JSON.stringify( Scenery.serialize() ) ) fd.append( "startPosition", JSON.stringify( app.position(scene.camera) ) ) - fd.append( "thumbnail", dataUriToBlob(map.canvas.toDataURL()) ) + + if (this.thumbnailIsStale()) { + fd.append( "thumbnail", dataUriToBlob(map.canvas.toDataURL()) ) + } return fd }, + thumbnailState: null, + thumbnailIsStale: function(){ + var newState = JSON.stringify( Rooms.serialize() ) + + if (newState !== this.thumbnailState) { + this.thumbnailState = newState + return true + } + return false + }, + success: function(data){ this.$id.val(data._id) this.$name.val(data.name) this.action = this.updateAction + Minotaur.unwatch(this) + Minotaur.hide() + window.history.pushState(null, document.title, "/project/" + data.slug + "/edit") }, diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index e3a8f2e..cc924da 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -4,6 +4,7 @@ var MediaEditor = FormView.extend({ events: { "keydown": 'stopPropagation', + "focus [name]": "clearMinotaur", "click [data-role=play-media]": "togglePaused", "mousedown [name=keyframe]": "stopPropagation", "mousedown": "stopPropagation", diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index 219952d..ab33bc0 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -54,15 +54,20 @@ var FormView = View.extend({ return fd }, - save: function(e){ - e.preventDefault() + 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) { - this.showErrors(errors) + if (errorCallback) { + errorCallback(errors) + } + else { + this.showErrors(errors) + } return } } @@ -74,18 +79,29 @@ var FormView = View.extend({ dataType: "json", processData: false, contentType: false, - }); + }) + request.done($.proxy(function (response) { if (response.error) { var errors = [] for (var key in response.error.errors) { errors.push(response.error.errors[key].message); } - this.showErrors(errors) + if (errorCallback) { + errorCallback(errors) + } + else { + this.showErrors(errors) + } return } else { - this.success && this.success(response) + if (successCallback) { + successCallback(response) + } + if (this.success) { + this.success(response) + } } }, this)); } diff --git a/public/assets/javascripts/ui/lib/View.js b/public/assets/javascripts/ui/lib/View.js index 999a0e5..d94e6db 100644 --- a/public/assets/javascripts/ui/lib/View.js +++ b/public/assets/javascripts/ui/lib/View.js @@ -1,13 +1,14 @@ var View = (function($, _){ var View = function(options) { - this.cid = _.uniqueId('view'); + this._id = _.uniqueId('view') + this.type = "view" options || (options = {}); - _.extend(this, _.pick(options, viewOptions)); - this._ensureElement(); - this.initialize.apply(this, arguments); - this.delegateEvents(); - }; + _.extend(this, _.pick(options, viewOptions)) + this._ensureElement() + this.initialize.apply(this, arguments) + this.delegateEvents() + } var delegateEventSplitter = /^(\S+)\s*(.*)$/; @@ -58,7 +59,7 @@ var View = (function($, _){ var match = key.match(delegateEventSplitter); var eventName = match[1], selector = match[2]; method = _.bind(method, this); - eventName += '.delegateEvents' + this.cid; + eventName += '.delegateEvents' + this._id; if (selector === '') { this.$el.on(eventName, method); } else { @@ -70,7 +71,7 @@ var View = (function($, _){ // Clears all callbacks previously bound to the view with `delegateEvents`. undelegateEvents: function() { - this.$el.off('.delegateEvents' + this.cid); + this.$el.off('.delegateEvents' + this._id); return this; }, diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 7cc41f5..1c48eee 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -629,7 +629,24 @@ iframe.embed { background-size: 100% 100%; } - +#minotaur { + position: absolute; + top: 26px; + right: 260px; + opacity: 0; +} +#minotaur .label:after { + padding: 6px; + font-size: 13px; + font-weight: 300; +} +#minotaur.saving { + background: #8fd; + opacity: 1; +} +#minotaur.saving .label:after { + content: 'SAVING'; +} .rapper { position:relative; diff --git a/server/lib/api/projects.js b/server/lib/api/projects.js index fc54a5f..bd3cb81 100644 --- a/server/lib/api/projects.js +++ b/server/lib/api/projects.js @@ -72,15 +72,20 @@ var projects = { data.slug = util.slugify(data.name) data.description = util.sanitize(data.description) - upload.put("projects", req.files.thumbnail, { - unacceptable: function(err){ - res.json({ error: { errors: { thumbnail: { message: "Problem saving thumbnail: " + err } } } }) - }, - success: function(url){ - data.photo = url - done() - } - }) + if (req.files.thumbnail) { + upload.put("projects", req.files.thumbnail, { + unacceptable: function(err){ + res.json({ error: { errors: { thumbnail: { message: "Problem saving thumbnail: " + err } } } }) + }, + success: function(url){ + data.photo = url + done() + } + }) + } + else { + done() + } function done() { Project.findOne({ _id: _id }, function(err, doc){ diff --git a/views/partials/header.ejs b/views/partials/header.ejs index e83f42a..6697aff 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -1,5 +1,9 @@ <a href="/" class="logo"><img src="/assets/img/logo4.svg"></a> +<div id="minotaur"> + <span class="label"></span> +</div> + <span class="topLinks"> [[ if (logged_in) { ]] diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index d0454d6..6d85699 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -30,6 +30,7 @@ <script type="text/javascript" src="/assets/javascripts/rectangles/util/mouse.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/util/keys.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/util/undostack.js"></script> +<script type="text/javascript" src="/assets/javascripts/rectangles/util/minotaur.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/models/vec2.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/models/vec3.js"></script> <script type="text/javascript" src="/assets/javascripts/rectangles/models/mat4.js"></script> |
