mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-01 07:54:11 -05:00
Use shareable false/true/'project' for different levels of shareability
This commit is contained in:
parent
6ae89e31f1
commit
b64bcd9f02
13 changed files with 21 additions and 12 deletions
|
@ -87,7 +87,7 @@ module.exports = class Classroom extends CocoModel
|
||||||
if options.withoutLadderLevels
|
if options.withoutLadderLevels
|
||||||
levels.remove(levels.filter((level) -> level.isLadder()))
|
levels.remove(levels.filter((level) -> level.isLadder()))
|
||||||
if options.projectLevels
|
if options.projectLevels
|
||||||
levels.remove(levels.filter((level) -> not level.isType('game-dev', 'web-dev')))
|
levels.remove(levels.filter((level) -> level.get('shareable') isnt 'project'))
|
||||||
return levels
|
return levels
|
||||||
|
|
||||||
getLadderLevel: (courseID) ->
|
getLadderLevel: (courseID) ->
|
||||||
|
|
|
@ -67,6 +67,7 @@ _.extend CampaignSchema.properties, {
|
||||||
adventurer: { type: 'boolean' }
|
adventurer: { type: 'boolean' }
|
||||||
practice: { type: 'boolean' }
|
practice: { type: 'boolean' }
|
||||||
practiceThresholdMinutes: {type: 'number'}
|
practiceThresholdMinutes: {type: 'number'}
|
||||||
|
shareable: { title: 'Shareable', type: ['string', 'boolean'], enum: [false, true, 'project'], description: 'Whether the level is not shareable, shareable, or a sharing-encouraged project level.' }
|
||||||
adminOnly: { type: 'boolean' }
|
adminOnly: { type: 'boolean' }
|
||||||
disableSpaces: { type: ['boolean','number'] }
|
disableSpaces: { type: ['boolean','number'] }
|
||||||
hidesSubmitUntilRun: { type: 'boolean' }
|
hidesSubmitUntilRun: { type: 'boolean' }
|
||||||
|
|
|
@ -25,7 +25,7 @@ _.extend ClassroomSchema.properties,
|
||||||
levels: c.array { title: 'Levels' }, c.object { title: 'Level' }, {
|
levels: c.array { title: 'Levels' }, c.object { title: 'Level' }, {
|
||||||
practice: {type: 'boolean'}
|
practice: {type: 'boolean'}
|
||||||
practiceThresholdMinutes: {type: 'number'}
|
practiceThresholdMinutes: {type: 'number'}
|
||||||
shareable: {type: 'boolean'}
|
shareable: { title: 'Shareable', type: ['string', 'boolean'], enum: [false, true, 'project'], description: 'Whether the level is not shareable, shareable, or a sharing-encouraged project level.' }
|
||||||
type: c.shortString()
|
type: c.shortString()
|
||||||
original: c.objectId()
|
original: c.objectId()
|
||||||
name: {type: 'string'}
|
name: {type: 'string'}
|
||||||
|
|
|
@ -328,8 +328,8 @@ _.extend LevelSchema.properties,
|
||||||
replayable: {type: 'boolean', title: 'Replayable', description: 'Whether this (hero) level infinitely scales up its difficulty and can be beaten over and over for greater rewards.'}
|
replayable: {type: 'boolean', title: 'Replayable', description: 'Whether this (hero) level infinitely scales up its difficulty and can be beaten over and over for greater rewards.'}
|
||||||
buildTime: {type: 'number', description: 'How long it has taken to build this level.'}
|
buildTime: {type: 'number', description: 'How long it has taken to build this level.'}
|
||||||
practice: { type: 'boolean' }
|
practice: { type: 'boolean' }
|
||||||
shareable: { type: 'boolean', title: 'Shareable' }
|
|
||||||
practiceThresholdMinutes: {type: 'number', description: 'Players with larger playtimes may be directed to a practice level.'}
|
practiceThresholdMinutes: {type: 'number', description: 'Players with larger playtimes may be directed to a practice level.'}
|
||||||
|
shareable: { title: 'Shareable', type: ['string', 'boolean'], enum: [false, true, 'project'], description: 'Whether the level is not shareable, shareable, or a sharing-encouraged project level.' }
|
||||||
|
|
||||||
# Admin flags
|
# Admin flags
|
||||||
adventurer: { type: 'boolean' }
|
adventurer: { type: 'boolean' }
|
||||||
|
|
|
@ -223,6 +223,9 @@
|
||||||
margin-bottom: 6.5px
|
margin-bottom: 6.5px
|
||||||
|
|
||||||
#student-projects-tab
|
#student-projects-tab
|
||||||
|
.student-levels-table
|
||||||
|
margin-top: 0px
|
||||||
|
|
||||||
.student-info
|
.student-info
|
||||||
margin-top: 5px
|
margin-top: 5px
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ block content
|
||||||
if previousLevelCompleted || view.teacherMode || !passedLastCompletedLevel || levelStatus
|
if previousLevelCompleted || view.teacherMode || !passedLastCompletedLevel || levelStatus
|
||||||
- var i18n = level.isType('course-ladder') ? 'play.compete' : 'home.play';
|
- var i18n = level.isType('course-ladder') ? 'play.compete' : 'home.play';
|
||||||
button.btn.btn-success.btn-play-level(data-level-slug=level.get('slug'), data-i18n=i18n, data-level-id=level.get('original'))
|
button.btn.btn-success.btn-play-level(data-level-slug=level.get('slug'), data-i18n=i18n, data-level-id=level.get('original'))
|
||||||
if level.isType('game-dev', 'web-dev')
|
if level.get('shareable')
|
||||||
- var levelOriginal = level.get('original');
|
- var levelOriginal = level.get('original');
|
||||||
- var session = view.levelSessions.find(function(session) { return session.get('level').original === levelOriginal });
|
- var session = view.levelSessions.find(function(session) { return session.get('level').original === levelOriginal });
|
||||||
if session
|
if session
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
.btn.btn-small.btn-illustrated.hints-button
|
.btn.btn-small.btn-illustrated.hints-button
|
||||||
span(data-i18n="play_level.hints")
|
span(data-i18n="play_level.hints")
|
||||||
|
|
||||||
if view.options.level.isType('game-dev', 'web-dev')
|
if view.options.level.get('shareable')
|
||||||
- var url = '/play/' + view.options.level.get('type') + '-level/' + view.options.level.get('slug') + '/' + view.options.session.id;
|
- var url = '/play/' + view.options.level.get('type') + '-level/' + view.options.level.get('slug') + '/' + view.options.session.id;
|
||||||
- if (view.options.courseID) url += '?course=' + view.options.courseID;
|
- if (view.options.courseID) url += '?course=' + view.options.courseID;
|
||||||
a.btn.btn-small.btn-illustrated(href=url)
|
a.btn.btn-small.btn-illustrated(href=url)
|
||||||
|
|
|
@ -52,7 +52,7 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@supermodel.trackRequest(@classroom.fetch())
|
@supermodel.trackRequest(@classroom.fetch())
|
||||||
|
|
||||||
levelsLoaded = @supermodel.trackRequest(@levels.fetchForClassroomAndCourse(classroomID, @courseID, {
|
levelsLoaded = @supermodel.trackRequest(@levels.fetchForClassroomAndCourse(classroomID, @courseID, {
|
||||||
data: { project: 'concepts,practice,type,slug,name,original,description' }
|
data: { project: 'concepts,practice,type,slug,name,original,description,shareable' }
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@supermodel.trackRequest($.when(levelsLoaded, sessionsLoaded).then(=>
|
@supermodel.trackRequest($.when(levelsLoaded, sessionsLoaded).then(=>
|
||||||
|
|
|
@ -119,7 +119,7 @@ module.exports = class TeacherClassView extends RootView
|
||||||
@supermodel.trackRequest @courseInstances.fetchForClassroom(classroomID)
|
@supermodel.trackRequest @courseInstances.fetchForClassroom(classroomID)
|
||||||
|
|
||||||
@levels = new Levels()
|
@levels = new Levels()
|
||||||
@supermodel.trackRequest @levels.fetchForClassroom(classroomID, {data: {project: 'original,concepts,practice'}})
|
@supermodel.trackRequest @levels.fetchForClassroom(classroomID, {data: {project: 'original,concepts,practice,shareable'}})
|
||||||
|
|
||||||
@attachMediatorEvents()
|
@attachMediatorEvents()
|
||||||
window.tracker?.trackEvent 'Teachers Class Loaded', category: 'Teachers', classroomID: @classroom.id, ['Mixpanel']
|
window.tracker?.trackEvent 'Teachers Class Loaded', category: 'Teachers', classroomID: @classroom.id, ['Mixpanel']
|
||||||
|
@ -389,6 +389,7 @@ module.exports = class TeacherClassView extends RootView
|
||||||
not @students.get(userID).isEnrolled()
|
not @students.get(userID).isEnrolled()
|
||||||
assigningToNobody = selectedIDs.length is 0
|
assigningToNobody = selectedIDs.length is 0
|
||||||
@state.set errors: { assigningToNobody, assigningToUnenrolled }
|
@state.set errors: { assigningToNobody, assigningToUnenrolled }
|
||||||
|
return if assigningToNobody
|
||||||
@assignCourse courseID, members
|
@assignCourse courseID, members
|
||||||
window.tracker?.trackEvent 'Teachers Class Students Assign Selected', category: 'Teachers', classroomID: @classroom.id, courseID: courseID, ['Mixpanel']
|
window.tracker?.trackEvent 'Teachers Class Students Assign Selected', category: 'Teachers', classroomID: @classroom.id, courseID: courseID, ['Mixpanel']
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,8 @@ module.exports = class CampaignView extends RootView
|
||||||
@particleMan.removeEmitters()
|
@particleMan.removeEmitters()
|
||||||
@particleMan.attach @$el.find('.map')
|
@particleMan.attach @$el.find('.map')
|
||||||
for level in @campaign.renderedLevels ? {}
|
for level in @campaign.renderedLevels ? {}
|
||||||
particleKey = ['level', @terrain.replace('-branching-test', '')]
|
terrain = @terrain.replace('-branching-test', '').replace(/(game|web)-dev-\d/, 'forest')
|
||||||
|
particleKey = ['level', terrain]
|
||||||
particleKey.push level.type if level.type and not (level.type in ['hero', 'course']) # Would use isType, but it's not a Level model
|
particleKey.push level.type if level.type and not (level.type in ['hero', 'course']) # Would use isType, but it's not a Level model
|
||||||
particleKey.push 'replayable' if level.replayable
|
particleKey.push 'replayable' if level.replayable
|
||||||
particleKey.push 'premium' if level.requiresSubscription
|
particleKey.push 'premium' if level.requiresSubscription
|
||||||
|
|
|
@ -143,6 +143,7 @@ module.exports = class PlayLevelView extends RootView
|
||||||
|
|
||||||
onLevelLoaded: (e) ->
|
onLevelLoaded: (e) ->
|
||||||
@god = new God({@gameUIState}) unless e.level.isType('web-dev')
|
@god = new God({@gameUIState}) unless e.level.isType('web-dev')
|
||||||
|
@setUpGod() if @waitingToSetUpGod
|
||||||
|
|
||||||
trackLevelLoadEnd: ->
|
trackLevelLoadEnd: ->
|
||||||
return if @isEditorPreview
|
return if @isEditorPreview
|
||||||
|
@ -242,6 +243,8 @@ module.exports = class PlayLevelView extends RootView
|
||||||
|
|
||||||
setupGod: ->
|
setupGod: ->
|
||||||
return if @level.isType('web-dev')
|
return if @level.isType('web-dev')
|
||||||
|
return @waitingToSetUpGod = true unless @god
|
||||||
|
@waitingToSetUpGod = undefined
|
||||||
@god.setLevel @level.serialize {@supermodel, @session, @otherSession, headless: false, sessionless: false}
|
@god.setLevel @level.serialize {@supermodel, @session, @otherSession, headless: false, sessionless: false}
|
||||||
@god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
|
@god.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
|
||||||
@god.setWorldClassMap @world.classMap
|
@god.setWorldClassMap @world.classMap
|
||||||
|
|
|
@ -75,7 +75,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
||||||
@saveReviewEventually = _.debounce(@saveReviewEventually, 2000)
|
@saveReviewEventually = _.debounce(@saveReviewEventually, 2000)
|
||||||
@loadExistingFeedback()
|
@loadExistingFeedback()
|
||||||
|
|
||||||
if @level.isType('game-dev', 'web-dev')
|
if @level.get('shareable') is 'project'
|
||||||
@shareURL = "#{window.location.origin}/play/#{@level.get('type')}-level/#{@level.get('slug')}/#{@session.id}"
|
@shareURL = "#{window.location.origin}/play/#{@level.get('type')}-level/#{@level.get('slug')}/#{@session.id}"
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
|
|
|
@ -24,7 +24,7 @@ module.exports = class ProgressView extends CocoView
|
||||||
# Images in Markdown are like 
|
# Images in Markdown are like 
|
||||||
@nextLevel.get('description', true) # Make sure the defaults are available
|
@nextLevel.get('description', true) # Make sure the defaults are available
|
||||||
@nextLevelDescription = marked(utils.i18n(@nextLevel.attributesWithDefaults, 'description').replace(/!\[.*?\]\(.*?\)\n*/g, ''))
|
@nextLevelDescription = marked(utils.i18n(@nextLevel.attributesWithDefaults, 'description').replace(/!\[.*?\]\(.*?\)\n*/g, ''))
|
||||||
if @level.isType('game-dev', 'web-dev')
|
if @level.get('shareable') is 'project'
|
||||||
@shareURL = "#{window.location.origin}/play/#{@level.get('type')}-level/#{@level.get('slug')}/#{@session.id}"
|
@shareURL = "#{window.location.origin}/play/#{@level.get('type')}-level/#{@level.get('slug')}/#{@session.id}"
|
||||||
@shareURL += "?course=#{@course.id}" if @course
|
@shareURL += "?course=#{@course.id}" if @course
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue