diff --git a/design/pages.graffle b/design/pages.graffle index a73a2d942..6516509e2 100644 Binary files a/design/pages.graffle and b/design/pages.graffle differ diff --git a/src/coffee/controllers/base_controller.coffee b/src/coffee/controllers/base_controller.coffee index 7208e93ed..0dbf0198e 100644 --- a/src/coffee/controllers/base_controller.coffee +++ b/src/coffee/controllers/base_controller.coffee @@ -153,9 +153,9 @@ module.exports = class BaseController extends backbone.View @tryRefresh() Object.defineProperties @prototype, - model: {get:@prototype.getModel, set:@prototype.setModel} + model: {get:@prototype.getModel, set:@prototype.setModel} rendered: {get:@prototype.isRendered } - user: {get:@prototype.user, set:@prototype.setUser} + user: {get:@prototype.getUser, set:@prototype.setUser} # Backbone.View Overrides ###################################################################### diff --git a/src/coffee/controllers/item_page_controller.coffee b/src/coffee/controllers/item_page_controller.coffee index 25c1f0f5c..e8cac6e6f 100644 --- a/src/coffee/controllers/item_page_controller.coffee +++ b/src/coffee/controllers/item_page_controller.coffee @@ -58,7 +58,7 @@ module.exports = class ItemPageController extends PageController onDidRender: -> @adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper' - options = imageLoader:@imageLoader, modPack:@modPack, show:false + options = editable:true, imageLoader:@imageLoader, modPack:@modPack, show:false @_descriptionController = @addChild MarkdownSectionController, '.section.description', options @_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options @_usedAsToolToMakeController = @addChild ItemGroupController, '.view__item_group.usedAsToolToMake', options @@ -111,14 +111,18 @@ module.exports = class ItemPageController extends PageController super + setUser: (user)-> + super user + @_descriptionController.user = user if @_descriptionController? + # Backbone.View Overrides ###################################################################### events: -> return _.extend super, - 'click a.craftingPlan': 'routeLinkClick' - 'click .byline a': 'routeLinkClick' - 'click .markdown a': 'routeLinkClick' - 'click button': 'craftingPlanButtonClicked' + 'click a.craftingPlan': 'routeLinkClick' + 'click .byline a': 'routeLinkClick' + 'click .markdown a': 'routeLinkClick' + 'click button.craftingPlan': 'craftingPlanButtonClicked' # Private Methods ############################################################################## diff --git a/src/coffee/controllers/login_page_controller.coffee b/src/coffee/controllers/login_page_controller.coffee index 235d31069..1e3fdb9b6 100644 --- a/src/coffee/controllers/login_page_controller.coffee +++ b/src/coffee/controllers/login_page_controller.coffee @@ -77,7 +77,7 @@ module.exports = class LoginPageController extends PageController attributes = response.json.data.user if attributes? router.user = new User attributes - router.navigate Url.root(), trigger:true + router.resumeAfterLogin() .catch (error)-> logger.error "Failed to get access token: #{error}" @_accessTokenLookupFailed = true @@ -120,9 +120,9 @@ module.exports = class LoginPageController extends PageController @client.completeGitHubLogin code:code .then (response)=> router.user = new User response.json.user - .catch (error)-> + .catch (error)=> @_accessTokenLookupFailed = true - @refresh + @refresh() .done() _redirectToGitHub: -> diff --git a/src/coffee/controllers/markdown_section_controller.coffee b/src/coffee/controllers/markdown_section_controller.coffee index 2226ab5bc..b2bc48aac 100644 --- a/src/coffee/controllers/markdown_section_controller.coffee +++ b/src/coffee/controllers/markdown_section_controller.coffee @@ -8,14 +8,22 @@ All rights reserved. BaseController = require './base_controller' convertMarkdown = require 'marked' _ = require 'underscore' +{Event} = require '../constants' {Url} = require '../constants' ######################################################################################################################## module.exports = class MarkdownSectionController extends BaseController + @State = State = + viewing: 'viewing' + editing: 'editing' + previewing: 'previewing' + error: 'error' + constructor: (options={})-> if not options.modPack? then throw new Error 'options.modPack is required' + options.editable ?= false options.imageBase ?= '' options.model ?= '' options.title ?= 'Description' @@ -26,30 +34,101 @@ module.exports = class MarkdownSectionController extends BaseController @modPack = options.modPack @title = options.title + @_editable = options.editable + @_state = State.viewing + + # Event Methods ################################################################################ + + onCancelClicked: (event)-> + event.preventDefault() + @_state = State.viewing + @_updateStateVisibility() + + onEditClicked: (event)-> + event.preventDefault() + + if global.router.user? + @_state = State.editing + @_updateStateVisibility() + else + global.router.login() + + onPreviewClicked: (event)-> + event.preventDefault() + @_state = State.preview + @_updateStateVisibility() + + onReturnClicked: (event)-> + event.preventDefault() + @_state = State.editing + @_updateStateVisibility() + + onSaveClicked: (event)-> + # TODO: implement logic to actually save changes + @onCancelClicked event + + onTextChanged: (event)-> + event.preventDefault() + @_updatePreview() + @_updateSizer() + + # Property Methods ############################################################################# + + isEditable: -> + return @_editable + + setEditable: (editable)-> + return if @_editable is editable + @_editable = editable + @tryRefresh() + + Object.defineProperties @prototype, + editable: {get:@prototype.isEditable, set:@prototype.setEditable} + # BaseController Overrides ##################################################################### onDidRender: -> - @$title = @$('h2') + @$buttonPanel = @$('.buttons') + @$cancelButton = @$('button.cancel') + @$editButton = @$('button.edit') + @$editorPanel = @$('.editor') + @$errorPanel = @$('.error') + @$errorText = @$('.error p') @$markdownPanel = @$('.markdown') + @$previewButton = @$('button.preview') + @$returnButton = @$('button.return') + @$saveButton = @$('button.save') + @$sizer = @$('.sizer') + @$textarea = @$('textarea') + @$title = @$('h2') super refresh: -> @$title.html @title - text = @model - text = @_convertWikiLinks text - text = @_convertImageLinks text + @$textarea.val @model - @$markdownPanel.html convertMarkdown text + if @editable + @show @$buttonPanel + else + @hide @$buttonPanel + @_updateSizer() + @_updatePreview() super # Backbone.View Overrides ###################################################################### events: -> return _.extend super, - 'click .markdown a': 'routeLinkClick' + 'click .markdown a': 'routeLinkClick' + 'click button.cancel': 'onCancelClicked' + 'click button.edit': 'onEditClicked' + 'click button.preview': 'onPreviewClicked' + 'click button.return': 'onReturnClicked' + 'click button.save': 'onSaveClicked' + 'input textarea': 'onTextChanged' # Private Methods ############################################################################## @@ -66,3 +145,37 @@ module.exports = class MarkdownSectionController extends BaseController result = "[#{name}](#{display.itemUrl})" return result + + _updateSizer: -> + text = @$textarea.val() + text = text.replace /\n/g, '
' + @$sizer.html text + + _updatePreview: -> + text = @$textarea.val() + text = @_convertWikiLinks text + text = @_convertImageLinks text + + @$markdownPanel.html convertMarkdown text + + _updateStateVisibility: -> + toHide = [] + toShow = [] + errorText = '' + + if @_state is State.viewing + toHide = [@$cancelButton, @$editorPanel, @$errorPanel, @$previewButton, @$returnButton, @$saveButton] + toShow = [@$editButton, @$markdownPanel] + else if @_state is State.editing + toHide = [@$editButton, @$errorPanel, @$markdownPanel, @$previewButton, @$returnButton] + toShow = [@$cancelButton, @$editorPanel, @$previewButton, @$saveButton] + else if @_state is State.preview + toHide = [@$cancelButton, @$editButton, @$editorPanel, @$previewButton, @$saveButton] + toShow = [@$errorPanel, @$markdownPanel, @$returnButton] + errorText = "remember: your changes aren't saved yet!" + # else if @_state is State.error + # TODO: Implement change to error state + + @hide $el for $el in toHide + @once Event.animate.hide.finish, => @show $el for $el in toShow + @$errorText.html errorText diff --git a/src/coffee/crafting_guide_router.coffee b/src/coffee/crafting_guide_router.coffee index a05ef9479..64ff616d4 100644 --- a/src/coffee/crafting_guide_router.coffee +++ b/src/coffee/crafting_guide_router.coffee @@ -36,9 +36,10 @@ backbone = require 'backbone' module.exports = class CraftingGuideRouter extends backbone.Router constructor: (options={})-> + @_lastReported = null @_page = null @_pageControllers = {} - @_lastReported = null + @_postLoginUrl = Url.root @_user = null super options @@ -80,6 +81,16 @@ module.exports = class CraftingGuideRouter extends backbone.Router logger.info "User is not logged in" .done() + login: -> + @storage.store 'post-login-url', window.location.pathname + @navigate Url.login(), trigger:true + + resumeAfterLogin: -> + url = @storage.load 'post-login-url' + url ?= Url.root() + @navigate url, trigger:true + @storage.store 'post-login-url', null + # Property Methods ############################################################################# getUser: -> diff --git a/src/jade/templates/markdown_section.jade b/src/jade/templates/markdown_section.jade index 4d2f8f476..82eed7a1d 100644 --- a/src/jade/templates/markdown_section.jade +++ b/src/jade/templates/markdown_section.jade @@ -7,4 +7,16 @@ .view__markdown_section.section h2 - .panel.markdown \ No newline at end of file + .panel + .markdown.hideable + .editor.hideable.hidden + textarea + .sizer + .images.hideable.hidden + .buttons.hideable.hidden + .error.hideable.hidden: p + button.return.hideable.hidden return + button.cancel.hideable.hidden cancel + button.preview.hideable.hidden preview + button.save.hideable.hidden save + button.edit.hideable edit diff --git a/src/scss/classes.scss b/src/scss/classes.scss index 48960bc5b..40b57a9cd 100644 --- a/src/scss/classes.scss +++ b/src/scss/classes.scss @@ -32,9 +32,9 @@ All rights reserved. width: 100%; } -.error { background: $color-error !important; } +.error { background: $color-error; } -.error-new { background: $color-error-new !important; } +.error-new { background: $color-error-new; } .float-right { float: right; diff --git a/src/scss/templates/markdown_section.scss b/src/scss/templates/markdown_section.scss index 9f49252c5..7b3459d23 100644 --- a/src/scss/templates/markdown_section.scss +++ b/src/scss/templates/markdown_section.scss @@ -6,7 +6,62 @@ All rights reserved. */ .view__markdown_section { + .editor { width: 100%; + + position: relative; + min-height: 10em; + + textarea, .sizer { + width: 100%; + border: 1px solid $color-gray-light; + font-family: $font-family-input; + font-size: $font-size-normal; + } + + textarea { + position: absolute; height: 100%; width: 100%; + + background: $color-gray-faint; + resize: none; + z-index: $layer-normal; + + &:focus { + background: $color-background-panel; + border: 1px solid $color-gray-medium; + } + } + + .sizer { + padding-bottom: 1.5em; + visibility: hidden; + z-index: $layer-normal - 1; + } + } + + .buttons { + position: relative; width: 100%; + + text-align: right; + + button { + margin: 0.66em 0 0 0.66em; + min-width: 6.66em; + padding: 0.25em 0.5em; + } + + .error { + + height: 100%; + + background: none; + display: inline-block; + + p { + color: $color-error-new; + font-weight: bold; + } + } } } diff --git a/src/scss/views.scss b/src/scss/views.scss index be9588c28..0ab6b691d 100644 --- a/src/scss/views.scss +++ b/src/scss/views.scss @@ -57,8 +57,6 @@ All rights reserved. position: absolute; bottom: 5em; height: 3.2em; width: 100%; .login { - display: none; // Just until there's a feature which needs it. - position: absolute; top: 50%; right: 2em; @include transform(translateY(-50%));