CocoModel = require 'models/CocoModel' CocoCollection = require 'collections/CocoCollection' {me} = require('lib/auth') locale = require 'locale/locale' class DateTimeTreema extends TreemaNode.nodeMap.string valueClass: 'treema-date-time' buildValueForDisplay: (el) -> el.text(moment(@data).format('llll')) buildValueForEditing: (valEl) -> @buildValueForEditingSimply valEl, null, 'date' class VersionTreema extends TreemaNode valueClass: 'treema-version' buildValueForDisplay: (valEl) -> @buildValueForDisplaySimply(valEl, "#{@data.major}.#{@data.minor}") class LiveEditingMarkup extends TreemaNode.nodeMap.ace valueClass: 'treema-markdown treema-multiline treema-ace' constructor: -> super(arguments...) @schema.aceMode = 'ace/mode/markdown' buildValueForEditing: (valEl) -> super(valEl) @editor.on('change', @onEditorChange) @addImageUpload(valEl) addImageUpload: (valEl) -> return unless me.isAdmin() valEl.append( $('
').append( $('') .addClass('btn btn-sm btn-primary') .click(=> filepicker.pick @onFileChosen) ) ) onFileChosen: (InkBlob) => body = url: InkBlob.url filename: InkBlob.filename mimetype: InkBlob.mimetype path: @settings.filePath force: true @uploadingPath = [@settings.filePath, InkBlob.filename].join('/') $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded }) onFileUploaded: (e) => @editor.insert "![#{e.metadata.name}](/file/#{@uploadingPath})" onEditorChange: => @saveChanges() @flushChanges() @getRoot().broadcastChanges() buildValueForDisplay: (valEl) -> @editor?.destroy() valEl.html(marked(@data)) class SoundFileTreema extends TreemaNode.nodeMap.string valueClass: 'treema-sound-file' editable: false soundCollection: 'files' onClick: (e) -> return if $(e.target).closest('.btn').length super(arguments...) getFiles: -> @settings[@soundCollection]?.models or [] buildValueForDisplay: (valEl) -> mimetype = "audio/#{@keyForParent}" pickButton = $('') .click(=> filepicker.pick {mimetypes:[mimetype]}, @onFileChosen) playButton = $('') .click(@playFile) stopButton = $('') .click(@stopFile) dropdown = $('') dropdownButton = $('') .addClass('btn btn-primary btn-xs dropdown-toggle') .attr('href', '#') .append($('')) .dropdown() dropdown.append dropdownButton menu = $('') files = @getFiles() for file in files continue unless file.get('contentType') is mimetype path = file.get('metadata').path filename = file.get 'filename' fullPath = [path, filename].join('/') li = $('') .data('fullPath', fullPath) .text(filename) menu.append(li) menu.click (e) => @data = $(e.target).data('fullPath') or @data @reset() dropdown.append(menu) valEl.append(pickButton) if @data valEl.append(playButton) valEl.append(stopButton) valEl.append(dropdown) # if files.length and @canEdit() if @data path = @data.split('/') name = path[path.length-1] valEl.append($('').text(name)) reset: -> @instance = null @flushChanges() @refreshDisplay() playFile: => @src = "/file/#{@data}" if @instance @instance.play() else createjs.Sound.alternateExtensions = ['mp3','ogg'] registered = createjs.Sound.registerSound(@src) if registered is true @instance = createjs.Sound.play(@src) else f = (event) => @instance = createjs.Sound.play(event.src) if event.src is @src createjs.Sound.removeEventListener('fileload', f) createjs.Sound.addEventListener('fileload', f) stopFile: => @instance?.stop() onFileChosen: (InkBlob) => if not @settings.filePath console.error('Need to specify a filePath for this treema', @getRoot()) throw Error('cannot upload file') body = url: InkBlob.url filename: InkBlob.filename mimetype: InkBlob.mimetype path: @settings.filePath force: true @uploadingPath = [@settings.filePath, InkBlob.filename].join('/') $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded }) onFileUploaded: (e) => @data = @uploadingPath @reset() class ImageFileTreema extends TreemaNode.nodeMap.string valueClass: 'treema-image-file' editable: false onClick: (e) -> return if $(e.target).closest('.btn').length super(arguments...) buildValueForDisplay: (valEl) -> mimetype = 'image/*' pickButton = $(' Upload Picture') .click(=> filepicker.pick {mimetypes:[mimetype]}, @onFileChosen) valEl.append(pickButton) if @data valEl.append $('').attr('src', "/file/#{@data}") onFileChosen: (InkBlob) => if not @settings.filePath console.error('Need to specify a filePath for this treema', @getRoot()) throw Error('cannot upload file') body = url: InkBlob.url filename: InkBlob.filename mimetype: InkBlob.mimetype path: @settings.filePath force: true @uploadingPath = [@settings.filePath, InkBlob.filename].join('/') $.ajax('/file', { type: 'POST', data: body, success: @onFileUploaded }) onFileUploaded: (e) => @data = @uploadingPath @flushChanges() @refreshDisplay() class CoffeeTreema extends TreemaNode.nodeMap.ace constructor: -> super(arguments...) @schema.aceMode = 'ace/mode/coffee' @schema.aceTabSize = 2 buildValueForEditing: (valEl) -> super(valEl) @editor.on('change', @onEditorChange) valEl onEditorChange: => @saveChanges() @flushChanges() @getRoot().broadcastChanges() class JavaScriptTreema extends CoffeeTreema constructor: -> super(arguments...) @schema.aceMode = 'ace/mode/javascript' @schema.aceTabSize = 4 KB = 1024 MB = 1024*1024 class InternationalizationNode extends TreemaNode.nodeMap.object findLanguageName: (languageCode) -> locale[languageCode]?.nativeDescription or "#{languageCode} Not Found" getChildSchema: (key) -> #construct the child schema here i18nChildSchema = { title: @findLanguageName(key) type: 'object' properties: {} } return i18nChildSchema unless @parent unless @schema.props? console.warn 'i18n props array is empty! Filling with all parent properties by default' @schema.props = (prop for prop,_ of @parent.schema.properties when prop isnt 'i18n') for i18nProperty in @schema.props i18nChildSchema.properties[i18nProperty] = @parent.schema.properties[i18nProperty] return i18nChildSchema #this must be filled out in order for the i18n node to work childPropertiesAvailable: -> return _.keys locale class LatestVersionCollection extends CocoCollection class LatestVersionReferenceNode extends TreemaNode searchValueTemplate: '' valueClass: 'treema-latest-version' url: '/db/article' lastTerm: null constructor: -> super(arguments...) # to dynamically build the search url, inspect the links url that should be included links = @schema.links or [] link = (l for l in links when l.rel is 'db')[0] return unless link parts = (p for p in link.href.split('/') when p.length) @url = "/db/#{parts[1]}" @model = require('models/' + _.string.classify(parts[1])) buildValueForDisplay: (valEl) -> val = if @data then @formatDocument(@data) else 'None' @buildValueForDisplaySimply(valEl, val) buildValueForEditing: (valEl) -> valEl.html(@searchValueTemplate) input = valEl.find('input') input.focus().keyup @search input.attr('placeholder', @formatDocument(@data)) if @data search: => term = @getValEl().find('input').val() return if term is @lastTerm # HACK while search is broken if @collection @lastTerm = term @searchCallback() return @getSearchResultsEl().empty() if @lastTerm and not term return unless term @lastTerm = term @getSearchResultsEl().empty().append('Searching') @collection = new LatestVersionCollection() # HACK while search is broken # @collection.url = "#{@url}?term=#{term}&project=true" @collection.url = "#{@url}?term=#{''}&project=true" @collection.fetch() @collection.once 'sync', @searchCallback, @ searchCallback: -> container = @getSearchResultsEl().detach().empty() first = true for model in @collection.models row = $('').addClass('treema-search-result-row') text = @formatDocument(model) continue unless text? # HACK while search is broken continue unless text.toLowerCase().indexOf(@lastTerm.toLowerCase()) >= 0 row.addClass('treema-search-selected') if first first = false row.text(text) row.data('value', model) container.append(row) if not @collection.models.length container.append($('