mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
More work on the CampaignEditorView. Data gets saved to models now.
This commit is contained in:
parent
1cc6a97e43
commit
b63b4d64da
4 changed files with 204 additions and 41 deletions
|
@ -313,7 +313,7 @@ class InternationalizationNode extends TreemaNode.nodeMap.object
|
||||||
|
|
||||||
class LatestVersionCollection extends CocoCollection
|
class LatestVersionCollection extends CocoCollection
|
||||||
|
|
||||||
class LatestVersionReferenceNode extends TreemaNode
|
module.exports.LatestVersionReferenceNode = class LatestVersionReferenceNode extends TreemaNode
|
||||||
searchValueTemplate: '<input placeholder="Search" /><div class="treema-search-results"></div>'
|
searchValueTemplate: '<input placeholder="Search" /><div class="treema-search-results"></div>'
|
||||||
valueClass: 'treema-latest-version'
|
valueClass: 'treema-latest-version'
|
||||||
url: '/db/article'
|
url: '/db/article'
|
||||||
|
@ -383,7 +383,11 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
m = CocoModel.getReferencedModel(@getData(), @workingSchema)
|
m = CocoModel.getReferencedModel(@getData(), @workingSchema)
|
||||||
data = @getData()
|
data = @getData()
|
||||||
if _.isString data # LatestVersionOriginalReferenceNode just uses original
|
if _.isString data # LatestVersionOriginalReferenceNode just uses original
|
||||||
m = @settings.supermodel.getModelByOriginal(m.constructor, data)
|
if m.schema().properties.version
|
||||||
|
m = @settings.supermodel.getModelByOriginal(m.constructor, data)
|
||||||
|
else
|
||||||
|
# get by id
|
||||||
|
m = @settings.supermodel.getModel(m.constructor, data)
|
||||||
else
|
else
|
||||||
m = @settings.supermodel.getModelByOriginalAndMajorVersion(m.constructor, data.original, data.majorVersion)
|
m = @settings.supermodel.getModelByOriginalAndMajorVersion(m.constructor, data.original, data.majorVersion)
|
||||||
if @instance and not m
|
if @instance and not m
|
||||||
|
@ -434,7 +438,7 @@ class LatestVersionReferenceNode extends TreemaNode
|
||||||
selected = @getSelectedResultEl()
|
selected = @getSelectedResultEl()
|
||||||
return not selected.length
|
return not selected.length
|
||||||
|
|
||||||
class LatestVersionOriginalReferenceNode extends LatestVersionReferenceNode
|
module.exports.LatestVersionOriginalReferenceNode = class LatestVersionOriginalReferenceNode extends LatestVersionReferenceNode
|
||||||
# Just for saving the original, not the major version.
|
# Just for saving the original, not the major version.
|
||||||
saveChanges: ->
|
saveChanges: ->
|
||||||
selected = @getSelectedResultEl()
|
selected = @getSelectedResultEl()
|
||||||
|
@ -443,6 +447,15 @@ class LatestVersionOriginalReferenceNode extends LatestVersionReferenceNode
|
||||||
@data = fullValue.attributes.original
|
@data = fullValue.attributes.original
|
||||||
@instance = fullValue
|
@instance = fullValue
|
||||||
|
|
||||||
|
module.exports.IDReferenceNode = class IDReferenceNode extends LatestVersionReferenceNode
|
||||||
|
# Just for saving the _id
|
||||||
|
saveChanges: ->
|
||||||
|
selected = @getSelectedResultEl()
|
||||||
|
return unless selected.length
|
||||||
|
fullValue = selected.data('value')
|
||||||
|
@data = fullValue.attributes._id
|
||||||
|
@instance = fullValue
|
||||||
|
|
||||||
class LevelComponentReferenceNode extends LatestVersionReferenceNode
|
class LevelComponentReferenceNode extends LatestVersionReferenceNode
|
||||||
# HACK: this list of properties is needed by the thang components edit view and config views.
|
# HACK: this list of properties is needed by the thang components edit view and config views.
|
||||||
# need a better way to specify this, or keep the search models from bleeding into those
|
# need a better way to specify this, or keep the search models from bleeding into those
|
||||||
|
|
|
@ -83,22 +83,27 @@ _.extend CampaignSchema.properties, {
|
||||||
}
|
}
|
||||||
|
|
||||||
requiredGear: { type: 'object', additionalProperties: {
|
requiredGear: { type: 'object', additionalProperties: {
|
||||||
type: 'string' # should be an originalID, denormalized on the editor side
|
type: 'array'
|
||||||
|
items: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
|
||||||
}}
|
}}
|
||||||
restrictedGear: { type: 'object', additionalProperties: {
|
restrictedGear: { type: 'object', additionalProperties: {
|
||||||
type: 'string' # should be an originalID, denormalized on the editor side
|
type: 'array'
|
||||||
|
items: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
|
||||||
}}
|
}}
|
||||||
allowedHeroes: { type: 'array', items: {
|
allowedHeroes: { type: 'array', items: {
|
||||||
type: 'string' # should be an originalID, denormalized on the editor side
|
type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#- denormalized from Achievements
|
#- denormalized from Achievements
|
||||||
unlocks: { type: 'array', items: {
|
rewards: { type: 'array', items: {
|
||||||
type: 'object'
|
type: 'object'
|
||||||
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
original: { type: 'string' }
|
achievement: { type: 'string', links: [{rel: 'db', href: '/db/achievement/{{$}}'}], format: 'achievement' }
|
||||||
type: { enum: ['hero', 'item', 'level'] }
|
item: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
|
||||||
achievement: { type: 'string' }
|
hero: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
|
||||||
|
level: { type: 'string', links: [{rel: 'db', href: '/db/level/{($)}/version'}], format: 'latest-version-original-reference' }
|
||||||
|
type: { enum: ['heroes', 'items', 'levels'] }
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#- normal properties
|
#- normal properties
|
||||||
|
|
|
@ -1,39 +1,157 @@
|
||||||
RootView = require 'views/core/RootView'
|
RootView = require 'views/core/RootView'
|
||||||
Campaign = require 'models/Campaign'
|
Campaign = require 'models/Campaign'
|
||||||
Level = require 'models/Level'
|
Level = require 'models/Level'
|
||||||
|
Achievement = require 'models/Achievement'
|
||||||
|
ThangType = require 'models/ThangType'
|
||||||
WorldMapView = require 'views/play/WorldMapView'
|
WorldMapView = require 'views/play/WorldMapView'
|
||||||
CocoCollection = require 'collections/CocoCollection'
|
CocoCollection = require 'collections/CocoCollection'
|
||||||
|
treemaExt = require 'core/treema-ext'
|
||||||
|
utils = require 'core/utils'
|
||||||
|
|
||||||
|
achievementProject = ['related', 'rewards', 'name', 'slug']
|
||||||
|
thangTypeProject = ['name', 'original', 'slug']
|
||||||
|
|
||||||
module.exports = class CampaignEditorView extends RootView
|
module.exports = class CampaignEditorView extends RootView
|
||||||
id: "campaign-editor-view"
|
id: "campaign-editor-view"
|
||||||
template: require 'templates/editor/campaign/campaign-editor-view'
|
template: require 'templates/editor/campaign/campaign-editor-view'
|
||||||
className: 'editor'
|
className: 'editor'
|
||||||
|
|
||||||
constructor: ->
|
constructor: (options, campaignHandle) ->
|
||||||
super(arguments...)
|
super(options)
|
||||||
|
|
||||||
# TODO: move the outputted data to the db, and load the Campaign objects instead
|
# MIGRATION CODE
|
||||||
for level in levels
|
# for level in levels
|
||||||
_.extend level, options[level.id]
|
# _.extend level, options[level.id]
|
||||||
level.slug = level.id
|
# level.slug = level.id
|
||||||
delete level.id
|
# delete level.id
|
||||||
delete level.nextLevels
|
# delete level.nextLevels
|
||||||
level.position = { x: level.x, y: level.y }
|
# level.position = { x: level.x, y: level.y }
|
||||||
delete level.x
|
# delete level.x
|
||||||
delete level.y
|
# delete level.y
|
||||||
if level.unlocksHero
|
# if level.unlocksHero
|
||||||
level.unlocks = [{
|
# level.unlocks = [{
|
||||||
original: level.unlocksHero.originalID
|
# original: level.unlocksHero.originalID
|
||||||
type: 'hero'
|
# type: 'hero'
|
||||||
}]
|
# }]
|
||||||
delete level.unlocksHero
|
# delete level.unlocksHero
|
||||||
campaign.levels[level.original] = level
|
# campaign.levels[level.original] = level
|
||||||
@campaign = new Campaign(campaign)
|
# @campaign = new Campaign(campaign)
|
||||||
#------------------------------------------------
|
#------------------------------------------------
|
||||||
|
|
||||||
|
@campaign = new Campaign({_id:campaignHandle})
|
||||||
|
|
||||||
collection = new CocoCollection({model: Level, url})
|
#--------------- temporary migration to change thang type slugs to originals
|
||||||
collection.ur
|
#- should keep around though for loading the names of items and heroes that are referenced
|
||||||
|
#- just load names instead of slugs, though
|
||||||
|
@sluggyThangs = new Backbone.Collection()
|
||||||
|
@listenToOnce @campaign, 'sync', ->
|
||||||
|
slugs = []
|
||||||
|
for level in _.values(@campaign.get('levels'))
|
||||||
|
slugs = slugs.concat(_.values(level.requiredGear)) if level.requiredGear
|
||||||
|
slugs = slugs.concat(_.values(level.restrictedGear)) if level.restrictedGear
|
||||||
|
slugs = slugs.concat(level.allowedHeroes) if level.allowedHeroes
|
||||||
|
slugs = _.uniq _.flatten slugs
|
||||||
|
for slug in slugs
|
||||||
|
thangType = new ThangType()
|
||||||
|
thangType.setProjection(thangTypeProject)
|
||||||
|
if utils.isID slug
|
||||||
|
thangType.setURL("/db/thang.type/#{slug}/version")
|
||||||
|
else
|
||||||
|
thangType.setURL("/db/thang.type/#{slug}")
|
||||||
|
@supermodel.loadModel(thangType, 'thang')
|
||||||
|
@sluggyThangs.add(thangType)
|
||||||
|
#---------------
|
||||||
|
@supermodel.loadModel(@campaign, 'campaign')
|
||||||
|
|
||||||
|
@levels = new CocoCollection([], {
|
||||||
|
model: Level
|
||||||
|
url: "/db/campaign/#{campaignHandle}/levels"
|
||||||
|
project: Campaign.denormalizedLevelProperties
|
||||||
|
})
|
||||||
|
@supermodel.loadCollection(@levels, 'levels')
|
||||||
|
|
||||||
|
@achievements = new CocoCollection([], {
|
||||||
|
model: Achievement
|
||||||
|
url: "/db/campaign/#{campaignHandle}/achievements"
|
||||||
|
project: achievementProject
|
||||||
|
})
|
||||||
|
@supermodel.loadCollection(@achievements, 'achievements')
|
||||||
|
|
||||||
|
@toSave = new Backbone.Collection()
|
||||||
|
|
||||||
|
onLoaded: ->
|
||||||
|
campaignLevels = $.extend({}, @campaign.get('levels'))
|
||||||
|
for level in @levels.models
|
||||||
|
levelOriginal = level.get('original')
|
||||||
|
campaignLevel = campaignLevels[levelOriginal] ? {}
|
||||||
|
|
||||||
|
#--------------- temporary migrations
|
||||||
|
if campaignLevel.restrictedGear
|
||||||
|
for slot, value of campaignLevel.restrictedGear
|
||||||
|
if _.isString(value)
|
||||||
|
campaignLevel.restrictedGear[slot] = [value]
|
||||||
|
#
|
||||||
|
if campaignLevel.requiredGear
|
||||||
|
for slot, value of campaignLevel.requiredGear
|
||||||
|
if _.isString(value)
|
||||||
|
campaignLevel.requiredGear[slot] = [value]
|
||||||
|
#
|
||||||
|
if campaignLevel.requiredGear
|
||||||
|
for gear in _.values(campaignLevel.requiredGear)
|
||||||
|
for slug, index in gear
|
||||||
|
thang = @sluggyThangs.findWhere({slug: slug})
|
||||||
|
continue unless thang
|
||||||
|
gear[index] = thang.get('original')
|
||||||
|
#
|
||||||
|
if campaignLevel.restrictedGear
|
||||||
|
for gear in _.values(campaignLevel.restrictedGear)
|
||||||
|
for slug, index in gear
|
||||||
|
thang = @sluggyThangs.findWhere({slug: slug})
|
||||||
|
continue unless thang
|
||||||
|
gear[index] = thang.get('original')
|
||||||
|
#
|
||||||
|
if campaignLevel.allowedHeroes
|
||||||
|
for slug, index in campaignLevel.allowedHeroes
|
||||||
|
thang = @sluggyThangs.findWhere({slug: slug})
|
||||||
|
continue unless thang
|
||||||
|
level.allowedHeroes[index] = thang.get('original')
|
||||||
|
#---------------
|
||||||
|
|
||||||
|
$.extend campaignLevel, _.omit(level.attributes, '_id')
|
||||||
|
achievements = @achievements.where {'related': levelOriginal}
|
||||||
|
rewards = []
|
||||||
|
for achievement in achievements
|
||||||
|
for rewardType, rewardArray of achievement.get('rewards')
|
||||||
|
for reward in rewardArray
|
||||||
|
rewardObject = { achievement: achievement.id }
|
||||||
|
|
||||||
|
if rewardType is 'heroes'
|
||||||
|
rewardObject.hero = reward
|
||||||
|
thangType = new ThangType({}, {project: thangTypeProject})
|
||||||
|
thangType.setURL("/db/thang.type/#{reward}/version")
|
||||||
|
@supermodel.loadModel(thangType, 'thang')
|
||||||
|
|
||||||
|
if rewardType is 'levels'
|
||||||
|
rewardObject.level = reward
|
||||||
|
if not @levels.findWhere({original: reward})
|
||||||
|
level = new Level({}, {project: Campaign.denormalizedLevelProperties})
|
||||||
|
level.setURL("/db/level/#{reward}/version")
|
||||||
|
@supermodel.loadModel(level, 'level')
|
||||||
|
|
||||||
|
if rewardType is 'items'
|
||||||
|
rewardObject.item = reward
|
||||||
|
thangType = new ThangType({}, {project: thangTypeProject})
|
||||||
|
thangType.setURL("/db/thang.type/#{reward}/version")
|
||||||
|
@supermodel.loadModel(thangType, 'thang')
|
||||||
|
|
||||||
|
rewards.push rewardObject
|
||||||
|
campaignLevel.rewards = rewards
|
||||||
|
delete campaignLevel.unlocks
|
||||||
|
campaignLevels[levelOriginal] = campaignLevel
|
||||||
|
|
||||||
|
@campaign.set('levels', campaignLevels)
|
||||||
|
super()
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
c.campaign = @campaign
|
c.campaign = @campaign
|
||||||
|
@ -51,17 +169,47 @@ module.exports = class CampaignEditorView extends RootView
|
||||||
nodeClasses:
|
nodeClasses:
|
||||||
levels: LevelsNode
|
levels: LevelsNode
|
||||||
level: LevelNode
|
level: LevelNode
|
||||||
|
achievement: AchievementNode
|
||||||
|
supermodel: @supermodel
|
||||||
|
|
||||||
@treema = @$el.find('#campaign-treema').treema treemaOptions
|
@treema = @$el.find('#campaign-treema').treema treemaOptions
|
||||||
@treema.build()
|
@treema.build()
|
||||||
@treema.open()
|
@treema.open()
|
||||||
@treema.childrenTreemas.levels.open()
|
@treema.childrenTreemas.levels?.open()
|
||||||
|
|
||||||
worldMapView = new WorldMapView({supermodel: @supermodel, editorMode: true}, 'dungeon')
|
worldMapView = new WorldMapView({supermodel: @supermodel, editorMode: true}, 'dungeon')
|
||||||
worldMapView.highlightElement = _.noop # make it stop
|
worldMapView.highlightElement = _.noop # make it stop
|
||||||
@insertSubView worldMapView
|
@insertSubView worldMapView
|
||||||
|
|
||||||
|
onTreemaChanged: (e, nodes) =>
|
||||||
|
for node in nodes
|
||||||
|
path = node.getPath()
|
||||||
|
if _.string.startsWith path, '/levels/'
|
||||||
|
parts = path.split('/')
|
||||||
|
original = parts[2]
|
||||||
|
level = @supermodel.getModelByOriginal Level, original
|
||||||
|
campaignLevel = @treema.get "/levels/#{original}"
|
||||||
|
|
||||||
|
if 'rewards' in parts
|
||||||
|
rewardsData = @
|
||||||
|
@updateRewardsForLevel level, campaignLevel.rewards
|
||||||
|
|
||||||
|
for key in Campaign.denormalizedLevelProperties
|
||||||
|
level.set key, campaignLevel[key]
|
||||||
|
@toSave.add level
|
||||||
|
|
||||||
|
@toSave.add @campaign
|
||||||
|
|
||||||
|
updateRewardsForLevel: (level, rewards) ->
|
||||||
|
achievements = @supermodel.getModels(Achievement)
|
||||||
|
achievements = (a for a in achievements when a.get('related') is level.get('original'))
|
||||||
|
for achievement in achievements
|
||||||
|
rewardSubset = (r for r in rewards when r.achievement is achievement._id)
|
||||||
|
newRewards = {}
|
||||||
|
newRewards.heroes = _.compact((r.hero for r in rewards))
|
||||||
|
newRewards.items = _.compact((r.item for r in rewards))
|
||||||
|
newRewards.levels = _.compact((r.level for r in rewards))
|
||||||
|
achievement.set 'rewards', newRewards
|
||||||
|
|
||||||
class LevelsNode extends TreemaObjectNode
|
class LevelsNode extends TreemaObjectNode
|
||||||
valueClass: 'treema-levels'
|
valueClass: 'treema-levels'
|
||||||
|
@ -73,15 +221,12 @@ class LevelsNode extends TreemaObjectNode
|
||||||
childPropertiesAvailable: -> @childSource
|
childPropertiesAvailable: -> @childSource
|
||||||
|
|
||||||
childSource: (req, res) =>
|
childSource: (req, res) =>
|
||||||
console.log 'calling child source!', req
|
|
||||||
s = new Backbone.Collection([], {model:Level})
|
s = new Backbone.Collection([], {model:Level})
|
||||||
s.url = '/db/level'
|
s.url = '/db/level'
|
||||||
s.fetch({data: {term:req.term, project: Campaign.denormalizedLevelProperties.join(',')}})
|
s.fetch({data: {term:req.term, project: Campaign.denormalizedLevelProperties.join(',')}})
|
||||||
s.once 'sync', (collection) ->
|
s.once 'sync', (collection) ->
|
||||||
LevelsNode.levels[level.get('original')] = level for level in collection.models
|
LevelsNode.levels[level.get('original')] = level for level in collection.models
|
||||||
console.log 'results!', collection.models
|
|
||||||
mapped = ({label: r.get('name'), value: r.get('original')} for r in collection.models)
|
mapped = ({label: r.get('name'), value: r.get('original')} for r in collection.models)
|
||||||
console.log 'mapped', mapped
|
|
||||||
res(mapped)
|
res(mapped)
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,11 +237,11 @@ class LevelNode extends TreemaObjectNode
|
||||||
|
|
||||||
populateData: ->
|
populateData: ->
|
||||||
return if @data.name?
|
return if @data.name?
|
||||||
console.log 'how do I do this?', @data, @keyForParent, LevelsNode.levels
|
|
||||||
data = _.pick LevelsNode.levels[@keyForParent].attributes, Campaign.denormalizedLevelProperties
|
data = _.pick LevelsNode.levels[@keyForParent].attributes, Campaign.denormalizedLevelProperties
|
||||||
_.extend @data, data
|
_.extend @data, data
|
||||||
console.log 'extended to data', data
|
|
||||||
console.log 'now data is', @data
|
class AchievementNode extends treemaExt.IDReferenceNode
|
||||||
|
buildSearchURL: (term) -> "#{@url}?term=#{term}&project=#{achievementProject.join(',')}"
|
||||||
|
|
||||||
campaign = {
|
campaign = {
|
||||||
name: 'Dungeon'
|
name: 'Dungeon'
|
||||||
|
|
|
@ -36,7 +36,7 @@ CampaignHandler = class CampaignHandler extends Handler
|
||||||
return @getRelatedAchievements(req, res, campaign, projection) if relationship is 'achievements'
|
return @getRelatedAchievements(req, res, campaign, projection) if relationship is 'achievements'
|
||||||
else
|
else
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
|
|
||||||
|
|
||||||
getRelatedLevels: (req, res, campaign, projection) ->
|
getRelatedLevels: (req, res, campaign, projection) ->
|
||||||
levels = campaign.get('levels') or []
|
levels = campaign.get('levels') or []
|
||||||
|
|
Loading…
Reference in a new issue