diff --git a/src/coffee/controllers/item_page_controller.coffee b/src/coffee/controllers/item_page_controller.coffee index 481c31f92..d896c8594 100644 --- a/src/coffee/controllers/item_page_controller.coffee +++ b/src/coffee/controllers/item_page_controller.coffee @@ -79,10 +79,11 @@ module.exports = class ItemPageController extends PageController @_usedToMakeController = @addChild ItemGroupController, '.view__item_group.usedToMake', options @_descriptionController = @addChild MarkdownSectionController, '.section.description', - editable: true - modPack: @modPack + client: @client + editable: true + modPack: @modPack beginEditing: => @_beginEditingDescription() - endEditing: => @_endEditingDescription() + endEditing: => @_endEditingDescription() @$byline = @$('.byline') @$bylineLink = @$('.byline a') @@ -157,19 +158,22 @@ module.exports = class ItemPageController extends PageController @client.fetchFile path:GitHub.file.itemDescription modSlug:@_itemSlug.mod, itemSlug:@_itemSlug.item .then (response)=> @_editingFile = response.json.data + @_editingFile.content = new Buffer(@_editingFile.content, 'base64').toString('utf8') + if @_editingFile.content.length > 0 @model.item.parse @_editingFile.content else @model.item.description = '' @_descriptionController.model = @model.item.description + @_descriptionController.loadImages() _endEditingDescription: -> oldDescription = @model.item.description @model.item.description = @_descriptionController.model args = - content: @model.item.unparse() + content: new Buffer(@model.item.unparse(), 'utf8').toString('base64') message: "User-submitted text for #{@model.item.name}" path: GitHub.file.itemDescription modSlug:@_itemSlug.mod, itemSlug:@_itemSlug.item sha: @_editingFile.sha diff --git a/src/coffee/controllers/markdown_image_controller.coffee b/src/coffee/controllers/markdown_image_controller.coffee index 4109da59f..942df8c23 100644 --- a/src/coffee/controllers/markdown_image_controller.coffee +++ b/src/coffee/controllers/markdown_image_controller.coffee @@ -5,6 +5,7 @@ Copyright (c) 2015 by Redwood Labs All rights reserved. ### +_ = require 'underscore' BaseController = require './base_controller' ######################################################################################################################## @@ -25,6 +26,8 @@ module.exports = class MarkdownImageController extends BaseController super refresh: -> + logger.debug "refreshing with model: #{@model.mimeType}, #{_.ellipsize(@model.encodedData)}" + if @model.mimeType? and @model.encodedData? @$image.attr 'src', "data:#{@model.mimeType};base64,#{@model.encodedData}" else diff --git a/src/coffee/controllers/markdown_image_list_controller.coffee b/src/coffee/controllers/markdown_image_list_controller.coffee index 41f98ec63..4960cd8ca 100644 --- a/src/coffee/controllers/markdown_image_list_controller.coffee +++ b/src/coffee/controllers/markdown_image_list_controller.coffee @@ -6,6 +6,7 @@ All rights reserved. ### BaseController = require './base_controller' +{Event} = require '../constants' MarkdownImageController = require './markdown_image_controller' MarkdownImageList = require '../models/markdown_image_list' @@ -14,12 +15,30 @@ MarkdownImageList = require '../models/markdown_image_list' module.exports = class MarkdownImageListController extends BaseController constructor: (options={})-> - options.model ?= new MarkdownImageList + options.model ?= new MarkdownImageList {}, {client:options.client} options.templateName = 'markdown_image_list' super options + @imageBase = '' + + # Public Methods ############################################################################### + + loadImages: -> + @model.loadImages() + # Property Methods ############################################################################# + getImageBase: -> + return @_imageBase + + setImageBase: (newImageBase)-> + oldImageBase = @_imageBase + return unless oldImageBase isnt newImageBase + + @_imageBase = newImageBase + @trigger Event.change + ':imageBase', this, oldImageBase, newImageBase + @trigger Event.change, this + getMarkdownText: -> return @model.markdownText @@ -27,6 +46,7 @@ module.exports = class MarkdownImageListController extends BaseController @model.markdownText = markdownText Object.defineProperties @prototype, + imageBase: {get:@prototype.getImageBase, set:@prototype.setImageBase} markdownText: {get:@prototype.getMarkdownText, set:@prototype.setMarkdownText} # BaseController Overrides ##################################################################### diff --git a/src/coffee/controllers/markdown_section_controller.coffee b/src/coffee/controllers/markdown_section_controller.coffee index 56fe9aaab..b670bdae8 100644 --- a/src/coffee/controllers/markdown_section_controller.coffee +++ b/src/coffee/controllers/markdown_section_controller.coffee @@ -36,6 +36,7 @@ module.exports = class MarkdownSectionController extends BaseController @on Event.animate.hide.finish, => @_updateStateVisibility() @on Event.animate.show.finish, => @_updateStateVisibility() + @client = options.client @confirmactionMessage = options.confirmationMessage @confirmDuration = options.confirmationDuration ?= 5000 @imageBase = options.imageBase ?= '' @@ -53,6 +54,9 @@ module.exports = class MarkdownSectionController extends BaseController # Public Methods ############################################################################### + loadImages: -> + @_imageListController.loadImages() + resetToDefaultState: -> if @model? @state = State.viewing @@ -114,6 +118,17 @@ module.exports = class MarkdownSectionController extends BaseController isEditable: -> return _.isFunction(@_beginEditing) and _.isFunction(@_endEditing) + getImageBase: -> + return @_imageBase + + setImageBase: (newImageBase)-> + oldImageBase = @_imageBase + return unless newImageBase isnt oldImageBase + + @_imageBase = newImageBase + @trigger Event.change + ':imageBase', this, oldImageBase, newImageBase + @trigger Event.change, this + getState: -> return @_state @@ -127,13 +142,17 @@ module.exports = class MarkdownSectionController extends BaseController @_updateStateVisibility() Object.defineProperties @prototype, - editable: {get:@prototype.isEditable} - state: {get:@prototype.getState, set:@prototype.setState} + editable: {get:@prototype.isEditable} + imageBase: {get:@prototype.getImageBase, set:@prototype.setImageBase} + state: {get:@prototype.getState, set:@prototype.setState} # BaseController Overrides ##################################################################### onDidRender: -> - @_imageListController = @addChild MarkdownImageListController, '.image_list' + @_imageListController = @addChild MarkdownImageListController, '.image_list', + client: @client + imageBase: @imageBase + @on Event.change + ':imageBase', => @_imageListController.model.imageBase = @imageBase @$errorText = @$('.error p') @$markdownPanel = @$('.markdown') diff --git a/src/coffee/models/markdown_image.coffee b/src/coffee/models/markdown_image.coffee index e84cc3deb..8bb6c93fa 100644 --- a/src/coffee/models/markdown_image.coffee +++ b/src/coffee/models/markdown_image.coffee @@ -6,26 +6,39 @@ All rights reserved. ### BaseModel = require './base_model' +_ = require 'underscore' {Event} = require '../constants' ######################################################################################################################## module.exports = class MarkdownImage extends BaseModel - @MIMETYPES = [ - {patern:/\.png$/i, text:'image/png'} - {patern:/\.gif$/i, text:'image/gif'} - {patern:/\.jpg$/i, text:'image/jpeg'} - {patern:/\.jpeg$/i, text:'image/jpeg'} + @MimeTypes = MimeTypes = [ + {pattern:/\.png$/i, text:'image/png'} + {pattern:/\.gif$/i, text:'image/gif'} + {pattern:/\.jpg$/i, text:'image/jpeg'} + {pattern:/\.jpeg$/i, text:'image/jpeg'} ] + @Status = Status = { + 'unknown': 'unknown' + 'checking': 'checking' + 'empty': 'empty' + 'creatable': 'creatable' + 'unchanged': 'unchanged' + 'updateable': 'updatable' + } + constructor: (attributes={}, options={})-> attributes.encodedData ?= null attributes.fileName ?= '' attributes.path ?= '' attributes.sha ?= null + attributes.status ?= Status.unknown super + @client = options.client + @on Event.change + ':fileName', => @_mimeType = null # Property Methods ############################################################################# @@ -35,7 +48,7 @@ module.exports = class MarkdownImage extends BaseModel getMimeType: -> if not @_mimeType? - for mimeType in MarkdownImage.MIMETYPES + for mimeType in MimeTypes if mimeType.pattern.test @fileName @_mimeType = mimeType.text break @@ -44,3 +57,19 @@ module.exports = class MarkdownImage extends BaseModel Object.defineProperties @prototype, fullPath: {get:@prototype.getFullPath} + mimeType: {get:@prototype.getMimeType} + + # BaseModel Overrides ########################################################################## + + fetch: -> + if not @client? then throw new Error 'MarkdownImage must be given a client to fetch with' + + @status = Status.checking + @client.fetchFile path:@fullPath + .then (response)=> + data = response.json.data + + if data.sha? + @set encodedData:data.content, sha:data.sha, status:Status.unchanged + else + @status = Status.empty diff --git a/src/coffee/models/markdown_image_list.coffee b/src/coffee/models/markdown_image_list.coffee index 21e3cf261..913c842cb 100644 --- a/src/coffee/models/markdown_image_list.coffee +++ b/src/coffee/models/markdown_image_list.coffee @@ -14,14 +14,27 @@ MarkdownImage = require './markdown_image' module.exports = class MarkdownImageList extends BaseModel constructor: (attributes={}, options={})-> + attributes.imageBase ?= '' attributes.markdownText ?= null super attributes, options + @client = options.client @_images = {} + @on Event.change + ':imageBase', => + for fileName, image of @_images + image.path = @imageBase + @on Event.change + ':markdownText', => @_analyzeMarkdownText() @_analyzeMarkdownText() + # Public Methods ############################################################################### + + loadImages: -> + for fileName, image of @_images + if image.status is MarkdownImage.Status.unknown + image.fetch() + # Property Methods ############################################################################# getAll: -> @@ -50,7 +63,7 @@ module.exports = class MarkdownImageList extends BaseModel fileName = match[2] image = @_images[fileName] if not image? - image = new MarkdownImage fileName:fileName + image = new MarkdownImage {fileName:fileName, path:@imageBase}, {client:@client} @trigger Event.add, this, image changed = true diff --git a/src/jade/templates/markdown_image.jade b/src/jade/templates/markdown_image.jade index d8521e040..0d6288ed4 100644 --- a/src/jade/templates/markdown_image.jade +++ b/src/jade/templates/markdown_image.jade @@ -6,6 +6,6 @@ //- .view__markdown_image - img + .thumbnail: img .fileName: p button diff --git a/src/scss/templates/markdown_image.scss b/src/scss/templates/markdown_image.scss index 0081b73cb..7b6c10302 100644 --- a/src/scss/templates/markdown_image.scss +++ b/src/scss/templates/markdown_image.scss @@ -9,11 +9,21 @@ All rights reserved. position: relative; min-width: 33em; display: inline-block; - margin-right: 2em; + margin: 1em 2em 0 0; vertical-align: top; - img { + .thumbnail { position: absolute; height: 10em; width: 10em; + + background: $color-gray-faint; + border: 0.1em solid $color-gray-light; + border-radius: 1em; + + img { + position: absolute; top: 50%; left: 50%; + @include transform(translate(-50%, -50%)); + max-width: 90%; max-height: 90%; + } } .fileName { diff --git a/test/markdown_image_list.test.coffee b/test/markdown_image_list.test.coffee index ce67e3d89..871f98e5c 100644 --- a/test/markdown_image_list.test.coffee +++ b/test/markdown_image_list.test.coffee @@ -16,7 +16,7 @@ list = null describe 'markdown_image_list.coffee', -> beforeEach -> - list = new MarkdownImageList + list = new MarkdownImageList {}, client:{fetchFile:sinon.stub().returns(w.promise(->))} describe '_analyzeMarkdownText', -> diff --git a/test/test_helper.coffee b/test/test_helper.coffee index 34b5d74e9..d4b7bbd07 100644 --- a/test/test_helper.coffee +++ b/test/test_helper.coffee @@ -16,6 +16,7 @@ global.Backbone = require 'backbone' global.assert = chai.assert global.expect = chai.expect global.should = chai.should() +global.sinon = require 'sinon' global.util = require 'util' global.w = require 'when'