mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-02-17 17:02:18 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
69118206ab
26 changed files with 149 additions and 37 deletions
|
@ -58,7 +58,7 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
|||
console.error 'Unable to save G+ token key', e
|
||||
@accessToken = e
|
||||
@trigger 'logged-in'
|
||||
|
||||
|
||||
loginCodeCombat: ->
|
||||
# email and profile data loaded separately
|
||||
gapi.client.request(path: plusURL, callback: @onPersonEntityReceived)
|
||||
|
@ -71,7 +71,8 @@ module.exports = GPlusHandler = class GPlusHandler extends CocoClass
|
|||
for gpProp, userProp of userPropsToSave
|
||||
keys = gpProp.split('.')
|
||||
value = r
|
||||
value = value[key] for key in keys
|
||||
for key in keys
|
||||
value = value[key]
|
||||
if value and not me.get(userProp)
|
||||
@shouldSave = true
|
||||
me.set(userProp, value)
|
||||
|
|
|
@ -459,6 +459,44 @@ class SlugPropsObject extends TreemaNode.nodeMap.object
|
|||
return res if @workingSchema.properties?[res]?
|
||||
_.string.slugify(res)
|
||||
|
||||
class TaskTreema extends TreemaNode.nodeMap.string
|
||||
buildValueForDisplay: (valEl) ->
|
||||
@taskCheckbox = $('<input type="checkbox">').prop 'checked', @data.complete
|
||||
task = $("<span>#{@data.name}</span>")
|
||||
valEl.append(@taskCheckbox).append(task)
|
||||
@taskCheckbox.on 'change', @onTaskChanged
|
||||
|
||||
buildValueForEditing: (valEl, data) ->
|
||||
@nameInput = @buildValueForEditingSimply(valEl, data.name)
|
||||
@nameInput.parent().prepend(@taskCheckbox)
|
||||
|
||||
onTaskChanged: (e) =>
|
||||
@markAsChanged()
|
||||
@saveChanges()
|
||||
@flushChanges()
|
||||
@broadcastChanges()
|
||||
|
||||
onEditInputBlur: (e) =>
|
||||
@markAsChanged()
|
||||
@saveChanges()
|
||||
if @isValid() then @display() if @isEditing() else @nameInput.focus().select()
|
||||
@flushChanges()
|
||||
@broadcastChanges()
|
||||
|
||||
saveChanges: (oldData) ->
|
||||
@data ?= {}
|
||||
@data.name = @nameInput.val() if @nameInput
|
||||
@data.complete = Boolean(@taskCheckbox.prop 'checked')
|
||||
|
||||
destroy: ->
|
||||
@taskCheckbox.off()
|
||||
super()
|
||||
|
||||
|
||||
#class CheckboxTreema extends TreemaNode.nodeMap.boolean
|
||||
# TODO: try this out
|
||||
|
||||
|
||||
module.exports.setup = ->
|
||||
TreemaNode.setNodeSubclass('date-time', DateTimeTreema)
|
||||
TreemaNode.setNodeSubclass('version', VersionTreema)
|
||||
|
@ -475,3 +513,5 @@ module.exports.setup = ->
|
|||
TreemaNode.setNodeSubclass('i18n', InternationalizationNode)
|
||||
TreemaNode.setNodeSubclass('sound-file', SoundFileTreema)
|
||||
TreemaNode.setNodeSubclass 'slug-props', SlugPropsObject
|
||||
TreemaNode.setNodeSubclass 'task', TaskTreema
|
||||
#TreemaNode.setNodeSubclass 'checkbox', CheckboxTreema
|
||||
|
|
|
@ -62,9 +62,9 @@ module.exports = class SpriteParser
|
|||
break
|
||||
continue unless container.bounds and instructions.length
|
||||
@addContainer {c: instructions, b: container.bounds}, container.name
|
||||
|
||||
|
||||
childrenMovieClips = []
|
||||
|
||||
|
||||
for movieClip, index in movieClips
|
||||
lastBounds = null
|
||||
# fill in bounds which are null...
|
||||
|
@ -73,7 +73,7 @@ module.exports = class SpriteParser
|
|||
movieClip.frameBounds[boundsIndex] = _.clone(lastBounds)
|
||||
else
|
||||
lastBounds = bounds
|
||||
|
||||
|
||||
localGraphics = @getGraphicsFromBlock(movieClip, source)
|
||||
[shapeKeys, localShapes] = @getShapesFromBlock movieClip, source
|
||||
localContainers = @getContainersFromMovieClip movieClip, source, true
|
||||
|
@ -90,7 +90,7 @@ module.exports = class SpriteParser
|
|||
bounds: movieClip.bounds
|
||||
frameBounds: movieClip.frameBounds
|
||||
}, movieClip.name
|
||||
|
||||
|
||||
for movieClip in movieClips
|
||||
if movieClip.name not in childrenMovieClips
|
||||
for bounds in movieClip.frameBounds
|
||||
|
@ -390,7 +390,7 @@ module.exports = class SpriteParser
|
|||
name = node.callee.property?.name
|
||||
return unless name in ['get', 'to', 'wait']
|
||||
return if name is 'get' and callExpressions.length # avoid Ease calls in the tweens
|
||||
flattenedRanges = _.flatten [a.range for a in node.arguments]
|
||||
flattenedRanges = _.flatten [(a.range for a in node.arguments)]
|
||||
range = [_.min(flattenedRanges), _.max(flattenedRanges)]
|
||||
# Replace 'this.<local>' references with just the 'name'
|
||||
argsSource = @subSourceFromRange(range, source)
|
||||
|
|
|
@ -326,7 +326,7 @@ module.exports = Lank = class Lank extends CocoClass
|
|||
|
||||
newScaleFactorX = @thang?.scaleFactorX ? @thang?.scaleFactor ? 1
|
||||
newScaleFactorY = @thang?.scaleFactorY ? @thang?.scaleFactor ? 1
|
||||
if @thang?.spriteName is 'Beam'
|
||||
if @layer?.name is 'Land' or @thang?.spriteName is 'Beam'
|
||||
@scaleFactorX = newScaleFactorX
|
||||
@scaleFactorY = newScaleFactorY
|
||||
else if @thang and (newScaleFactorX isnt @targetScaleFactorX or newScaleFactorY isnt @targetScaleFactorY)
|
||||
|
|
|
@ -65,12 +65,12 @@ module.exports = class SingularSprite extends createjs.Sprite
|
|||
@regY = -reg.y * scale
|
||||
@scaleX = @scaleY = 1 / @resolutionFactor
|
||||
|
||||
if @camera and @thangType.get('name') in floors
|
||||
@baseScaleY *= @camera.y2x
|
||||
@scaleX *= -1 if action.flipX
|
||||
@scaleY *= -1 if action.flipY
|
||||
@baseScaleX = @scaleX
|
||||
@baseScaleY = @scaleY
|
||||
if @camera and @thangType.get('name') in floors
|
||||
@baseScaleY *= @camera.y2x
|
||||
@currentAnimation = actionName
|
||||
return
|
||||
|
||||
|
|
|
@ -46,7 +46,8 @@ module.exports = class System
|
|||
hashString: (s) ->
|
||||
return @hashes[s] if s of @hashes
|
||||
hash = 0
|
||||
hash = hash * 31 + s.charCodeAt(i) for i in [0 ... Math.min(s.length, 100)]
|
||||
for i in [0 ... Math.min(s.length, 100)]
|
||||
hash = hash * 31 + s.charCodeAt(i)
|
||||
hash = @hashes[s] = hash % 3.141592653589793
|
||||
hash
|
||||
|
||||
|
|
|
@ -480,6 +480,8 @@
|
|||
forum_prefix: "For anything public, please try "
|
||||
forum_page: "our forum"
|
||||
forum_suffix: " instead."
|
||||
faq_prefix: "There's also a"
|
||||
faq: "FAQ"
|
||||
subscribe_prefix: "If you need help figuring out a level, please"
|
||||
subscribe: "buy a CodeCombat subscription"
|
||||
subscribe_suffix: "and we'll be happy to help you with your code."
|
||||
|
|
|
@ -1,6 +1,48 @@
|
|||
c = require './../schemas'
|
||||
ThangComponentSchema = require './thang_component'
|
||||
|
||||
defaultTasks = [
|
||||
'Name the level.'
|
||||
'Create a Referee stub, if needed.'
|
||||
'Build the level.'
|
||||
'Set up goals.'
|
||||
'Choose the Existence System lifespan and frame rate.'
|
||||
'Choose the UI System paths and coordinate hover if needed.'
|
||||
'Choose the AI System pathfinding and Vision System line of sight.'
|
||||
'Write the sample code.'
|
||||
|
||||
'Do basic set decoration.'
|
||||
'Adjust script camera bounds.'
|
||||
'Choose music file in Introduction script.'
|
||||
|
||||
'Add to a campaign.'
|
||||
'Publish for playtesting.'
|
||||
'Choose level options like required/restricted gear.'
|
||||
'Create achievements, including unlocking next level.'
|
||||
|
||||
'Playtest with a slow/tough hero.'
|
||||
'Playtest with a fast/weak hero.'
|
||||
'Playtest with a couple random seeds.'
|
||||
'Make sure the level ends promptly on success and failure.'
|
||||
'Remove/simplify unnecessary doodad collision.'
|
||||
'Release to adventurers.'
|
||||
|
||||
'Write the description.'
|
||||
'Translate the sample code comments.'
|
||||
'Add Io/Clojure/Lua/CoffeeScript.'
|
||||
'Write the guide.'
|
||||
'Write a loading tip, if needed.'
|
||||
'Populate i18n.'
|
||||
|
||||
'Mark whether it requires a subscription (after adventurer week).'
|
||||
'Release to everyone.'
|
||||
|
||||
'Check completion/engagement/problem analytics.'
|
||||
'Do any custom scripting, if needed.'
|
||||
'Do thorough set decoration.'
|
||||
'Add a walkthrough video.'
|
||||
]
|
||||
|
||||
SpecificArticleSchema = c.object()
|
||||
c.extendNamedProperties SpecificArticleSchema # name first
|
||||
SpecificArticleSchema.properties.body = {type: 'string', title: 'Content', description: 'The body content of the article, in Markdown.', format: 'markdown'}
|
||||
|
@ -252,6 +294,7 @@ _.extend LevelSchema.properties,
|
|||
terrain: c.terrainString
|
||||
showsGuide: c.shortString(title: 'Shows Guide', description: 'If the guide is shown at the beginning of the level.', 'enum': ['first-time', 'always'])
|
||||
requiresSubscription: {title: 'Requires Subscription', description: 'Whether this level is available to subscribers only.', type: 'boolean'}
|
||||
tasks: c.array {title: 'Tasks', description: 'Tasks to be completed for this level.', default: (name: t for t in defaultTasks)}, c.task
|
||||
|
||||
c.extendBasicProperties LevelSchema, 'level'
|
||||
c.extendSearchableProperties LevelSchema
|
||||
|
|
|
@ -228,3 +228,7 @@ me.RewardSchema = (descriptionFragment='earned by achievements') ->
|
|||
levels: me.array {uniqueItems: true, description: "Levels #{descriptionFragment}."},
|
||||
me.stringID(links: [{rel: 'db', href: '/db/level/{($)}/version'}], title: 'Level', description: 'A reference to the earned Level.', format: 'latest-version-original-reference')
|
||||
gems: me.int {description: "Gems #{descriptionFragment}."}
|
||||
|
||||
me.task = me.object {title: 'Task', description: 'A task to be completed', format: 'task', default: {name: 'TODO', complete: false}},
|
||||
name: {title: 'Name', description: 'What must be done?', type: 'string'}
|
||||
complete: {title: 'Complete', description: 'Whether this task is done.', type: 'boolean', format: 'checkbox'}
|
||||
|
|
|
@ -378,3 +378,8 @@ body > iframe[src^="https://apis.google.com"]
|
|||
|
||||
.progress-bar
|
||||
background-color: lightblue
|
||||
|
||||
.treema-node input[type='checkbox']
|
||||
@include scale(1.25)
|
||||
width: auto
|
||||
margin: 8px 15px 8px 15px
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#components-treema
|
||||
z-index: 11
|
||||
|
||||
.not-present
|
||||
opacity: 0.75
|
||||
|
||||
.edit-component-container
|
||||
margin-left: 290px
|
||||
position: absolute
|
||||
|
|
|
@ -9,10 +9,11 @@ block content
|
|||
li.active(data-i18n="#{currentEditor}")
|
||||
| #{currentEditor}
|
||||
|
||||
if me.get('anonymous')
|
||||
a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="core/AuthModal", role="button", data-i18n="#{currentNewSignup}") Log in to Create a New Content
|
||||
else
|
||||
a.btn.btn-primary.open-modal-button#new-model-button(data-i18n="#{currentNew}") Create a New Something
|
||||
if me.isAdmin() || !newModelsAdminOnly
|
||||
if me.get('anonymous')
|
||||
a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="core/AuthModal", role="button", data-i18n="#{currentNewSignup}") Log in to Create a New Something
|
||||
else
|
||||
a.btn.btn-primary.open-modal-button#new-model-button(data-i18n="#{currentNew}") Create a New Something
|
||||
input#search(data-i18n="[placeholder]#{currentSearch}")
|
||||
hr
|
||||
div.results
|
||||
|
|
|
@ -9,6 +9,9 @@ block modal-body-content
|
|||
span.spl(data-i18n="contact.forum_prefix") For anything public, please try
|
||||
a(href="http://discourse.codecombat.com/", data-i18n="contact.forum_page") our forum
|
||||
span(data-i18n="contact.forum_suffix") instead.
|
||||
span.spl.spr(data-i18n="contact.faq_prefix") There's also a
|
||||
a(data-i18n="contact.faq", href="http://discourse.codecombat.com/t/faq-check-before-posting/1027") FAQ
|
||||
| .
|
||||
if me.isPremium()
|
||||
p(data-i18n="contact.subscriber_support") Since you're a CodeCombat subscriber, your email will get our priority support.
|
||||
else
|
||||
|
|
|
@ -92,9 +92,9 @@ block header
|
|||
li(class=anonymous ? "disabled": "")
|
||||
a(data-i18n="common.fork")#fork-start-button Fork
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert")#revert-button Revert
|
||||
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=anonymous)#revert-button Revert
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-toggle="coco-modal", data-target="editor/level/modals/GenerateTerrainModal", data-i18n="editor.generate_terrain").generate-terrain-button Generate Terrain
|
||||
a(data-toggle="coco-modal", data-target="editor/level/modals/GenerateTerrainModal", data-i18n="editor.generate_terrain", disabled=anonymous).generate-terrain-button Generate Terrain
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
|
||||
li.divider
|
||||
|
|
|
@ -52,11 +52,11 @@ block header
|
|||
span.glyphicon-chevron-down.glyphicon
|
||||
ul.dropdown-menu
|
||||
li.dropdown-header(data-i18n="common.actions") Actions
|
||||
li(class=anonymous ? "disabled": "")
|
||||
li(class=!me.isAdmin() ? "disabled": "")
|
||||
a(data-i18n="common.fork")#fork-start-button Fork
|
||||
li(class=anonymous ? "disabled": "")
|
||||
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert")#revert-button Revert
|
||||
li(class=anonymous ? "disabled": "")
|
||||
li(class=!authorized ? "disabled": "")
|
||||
a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=!authorized)#revert-button Revert
|
||||
li(class=!authorized ? "disabled": "")
|
||||
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
|
||||
li.divider
|
||||
li.dropdown-header(data-i18n="common.info") Info
|
||||
|
|
|
@ -199,6 +199,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
# special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value.
|
||||
elem = $(e.target)
|
||||
return unless elem.data('toggle') is 'coco-modal'
|
||||
return if elem.attr('disabled')
|
||||
target = elem.data('target')
|
||||
Modal = require 'views/'+target
|
||||
e.stopPropagation()
|
||||
|
|
|
@ -6,7 +6,6 @@ module.exports = class ForkModal extends ModalView
|
|||
id: 'fork-modal'
|
||||
template: template
|
||||
instant: false
|
||||
modalWidthPercent: 60
|
||||
|
||||
events:
|
||||
'click #fork-model-confirm-button': 'forkModel'
|
||||
|
|
|
@ -14,6 +14,7 @@ module.exports = class AchievementSearchView extends SearchView
|
|||
context.currentNew = 'editor.new_achievement_title'
|
||||
context.currentNewSignup = 'editor.new_achievement_title_login'
|
||||
context.currentSearch = 'editor.achievement_search_title'
|
||||
context.newModelsAdminOnly = true
|
||||
context.unauthorized = true unless me.isAdmin()
|
||||
@$el.i18n()
|
||||
context
|
||||
|
|
|
@ -14,5 +14,6 @@ module.exports = class ArticleSearchView extends SearchView
|
|||
context.currentNew = 'editor.new_article_title'
|
||||
context.currentNewSignup = 'editor.new_article_title_login'
|
||||
context.currentSearch = 'editor.article_search_title'
|
||||
context.newModelsAdminOnly = true
|
||||
@$el.i18n()
|
||||
context
|
||||
|
|
|
@ -40,7 +40,7 @@ module.exports = class LevelEditView extends RootView
|
|||
'click .play-with-team-button': 'onPlayLevel'
|
||||
'click .play-with-team-parent': 'onPlayLevelTeamSelect'
|
||||
'click #commit-level-start-button': 'startCommittingLevel'
|
||||
'click #fork-start-button': 'startForking'
|
||||
'click li:not(.disabled) > #fork-start-button': 'startForking'
|
||||
'click #level-history-button': 'showVersionHistory'
|
||||
'click #undo-button': 'onUndo'
|
||||
'mouseenter #undo-button': 'showUndoDescription'
|
||||
|
@ -50,7 +50,7 @@ module.exports = class LevelEditView extends RootView
|
|||
'click #components-tab': -> @subviews.editor_level_components_tab_view.refreshLevelThangsTreema @level.get('thangs')
|
||||
'click #level-patch-button': 'startPatchingLevel'
|
||||
'click #level-watch-button': 'toggleWatchLevel'
|
||||
'click #pop-level-i18n-button': 'onPopulateI18N'
|
||||
'click li:not(.disabled) > #pop-level-i18n-button': 'onPopulateI18N'
|
||||
'click a[href="#editor-level-documentation"]': 'onClickDocumentationTab'
|
||||
'mouseup .nav-tabs > li a': 'toggleTab'
|
||||
|
||||
|
@ -66,7 +66,7 @@ module.exports = class LevelEditView extends RootView
|
|||
showLoading: ($el) ->
|
||||
$el ?= @$el.find('.outer-content')
|
||||
super($el)
|
||||
|
||||
|
||||
getTitle: -> "LevelEditor - " + (@level.get('name') or '...')
|
||||
|
||||
onLoaded: ->
|
||||
|
@ -170,7 +170,7 @@ module.exports = class LevelEditView extends RootView
|
|||
button = @$el.find('#level-watch-button')
|
||||
@level.watch(button.find('.watch').is(':visible'))
|
||||
button.find('> span').toggleClass('secret')
|
||||
|
||||
|
||||
onPopulateI18N: ->
|
||||
@level.populateI18N()
|
||||
f = -> document.location.reload()
|
||||
|
|
|
@ -31,7 +31,7 @@ module.exports = class ComponentsTabView extends CocoView
|
|||
thangType = @supermodel.getModelByOriginal ThangType, thang.thangType
|
||||
for component in thangType.get('components') ? []
|
||||
componentMap[component.original] = component
|
||||
|
||||
|
||||
for component in thang.components
|
||||
componentMap[component.original] = component
|
||||
|
||||
|
@ -45,9 +45,10 @@ module.exports = class ComponentsTabView extends CocoView
|
|||
componentModelMap = {}
|
||||
componentModelMap[comp.get('original')] = comp for comp in componentModels
|
||||
components = ({original: key.split('.')[0], majorVersion: parseInt(key.split('.')[1], 10), thangs: value, count: value.length} for key, value of @presentComponents)
|
||||
treemaData = _.sortBy components, (comp) ->
|
||||
comp = componentModelMap[comp.original]
|
||||
res = [comp.get('system'), comp.get('name')]
|
||||
components = components.concat ({original: c.get('original'), majorVersion: c.get('version').major, thangs: [], count: 0} for c in componentModels when not @presentComponents[c.get('original') + '.' + c.get('version').major])
|
||||
treemaData = _.sortBy components, (comp) =>
|
||||
component = componentModelMap[comp.original]
|
||||
res = [(if comp.count then 0 else 1), component.get('system'), component.get('name')]
|
||||
return res
|
||||
|
||||
treemaOptions =
|
||||
|
@ -82,7 +83,7 @@ module.exports = class ComponentsTabView extends CocoView
|
|||
onLevelComponentEditingEnded: (e) ->
|
||||
@removeSubView @levelComponentEditView
|
||||
@levelComponentEditView = null
|
||||
|
||||
|
||||
destroy: ->
|
||||
@componentsTreema?.destroy()
|
||||
super()
|
||||
|
@ -98,4 +99,6 @@ class LevelComponentNode extends TreemaObjectNode
|
|||
comp = _.find @settings.supermodel.getModels(LevelComponent), (m) =>
|
||||
m.get('original') is data.original and m.get('version').major is data.majorVersion
|
||||
name = "#{comp.get('system')}.#{comp.get('name')} v#{comp.get('version').major}"
|
||||
@buildValueForDisplaySimply valEl, "#{name} (#{count})"
|
||||
result = @buildValueForDisplaySimply valEl, "#{name} (#{count})"
|
||||
result.addClass 'not-present' unless data.count
|
||||
result
|
||||
|
|
|
@ -14,7 +14,8 @@ module.exports = class SettingsTabView extends CocoView
|
|||
# not thangs or scripts or the backend stuff
|
||||
editableSettings: [
|
||||
'name', 'description', 'documentation', 'nextLevel', 'background', 'victory', 'i18n', 'icon', 'goals',
|
||||
'type', 'terrain', 'showsGuide', 'banner', 'employerDescription', 'loadingTip', 'requiresSubscription'
|
||||
'type', 'terrain', 'showsGuide', 'banner', 'employerDescription', 'loadingTip', 'requiresSubscription',
|
||||
'tasks'
|
||||
]
|
||||
|
||||
subscriptions:
|
||||
|
|
|
@ -45,13 +45,13 @@ module.exports = class ThangTypeEditView extends RootView
|
|||
'click #stop-button': 'stopAnimation'
|
||||
'click #play-button': 'playAnimation'
|
||||
'click #history-button': 'showVersionHistory'
|
||||
'click #fork-start-button': 'startForking'
|
||||
'click li:not(.disabled) > #fork-start-button': 'startForking'
|
||||
'click #save-button': 'openSaveModal'
|
||||
'click #patches-tab': -> @patchesView.load()
|
||||
'click .play-with-level-button': 'onPlayLevel'
|
||||
'click .play-with-level-parent': 'onPlayLevelSelect'
|
||||
'keyup .play-with-level-input': 'onPlayLevelKeyUp'
|
||||
'click #pop-level-i18n-button': 'onPopulateLevelI18N'
|
||||
'click li:not(.disabled) > #pop-level-i18n-button': 'onPopulateLevelI18N'
|
||||
|
||||
|
||||
onClickSetVectorIcon: ->
|
||||
|
|
|
@ -15,6 +15,7 @@ module.exports = class ThangTypeSearchView extends SearchView
|
|||
context.currentNew = 'editor.new_thang_title'
|
||||
context.currentNewSignup = 'editor.new_thang_title_login'
|
||||
context.currentSearch = 'editor.thang_search_title'
|
||||
context.newModelsAdminOnly = true
|
||||
@$el.i18n()
|
||||
context
|
||||
|
||||
|
|
|
@ -312,7 +312,8 @@ module.exports = class SpellView extends CocoView
|
|||
# Lock contiguous section of default code
|
||||
# Only works for languages without closing delimeters on blocks currently
|
||||
lines = @aceDoc.getAllLines()
|
||||
lastRow = row for line, row in lines when not /^\s*$/.test(line)
|
||||
for line, row in lines when not /^\s*$/.test(line)
|
||||
lastRow = row
|
||||
if lastRow?
|
||||
@readOnlyRanges.push new Range 0, 0, lastRow, lines[lastRow].length - 1
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ LevelHandler = class LevelHandler extends Handler
|
|||
'i18nCoverage'
|
||||
'loadingTip'
|
||||
'requiresSubscription'
|
||||
'tasks'
|
||||
]
|
||||
|
||||
postEditableProperties: ['name']
|
||||
|
@ -72,7 +73,7 @@ LevelHandler = class LevelHandler extends Handler
|
|||
Session.findOne(sessionQuery).exec (err, doc) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendSuccess(res, doc) if doc?
|
||||
return @sendPaymentRequiredError(res, err) if (not req.user.isPremium()) and level.get('requiresSubscription')
|
||||
return @sendPaymentRequiredError(res, err) if (not req.user.isPremium()) and level.get('requiresSubscription')
|
||||
@createAndSaveNewSession sessionQuery, req, res
|
||||
|
||||
createAndSaveNewSession: (sessionQuery, req, res) =>
|
||||
|
|
Loading…
Reference in a new issue