Use shareable false/true/'project' for different levels of shareability

This commit is contained in:
Nick Winter 2016-07-15 23:26:43 -07:00
parent 6ae89e31f1
commit b64bcd9f02
13 changed files with 21 additions and 12 deletions

View file

@ -87,7 +87,7 @@ module.exports = class Classroom extends CocoModel
if options.withoutLadderLevels
levels.remove(levels.filter((level) -> level.isLadder()))
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
getLadderLevel: (courseID) ->

View file

@ -67,6 +67,7 @@ _.extend CampaignSchema.properties, {
adventurer: { type: 'boolean' }
practice: { type: 'boolean' }
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' }
disableSpaces: { type: ['boolean','number'] }
hidesSubmitUntilRun: { type: 'boolean' }

View file

@ -25,7 +25,7 @@ _.extend ClassroomSchema.properties,
levels: c.array { title: 'Levels' }, c.object { title: 'Level' }, {
practice: {type: 'boolean'}
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()
original: c.objectId()
name: {type: 'string'}

View file

@ -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.'}
buildTime: {type: 'number', description: 'How long it has taken to build this level.'}
practice: { type: 'boolean' }
shareable: { type: 'boolean', title: 'Shareable' }
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
adventurer: { type: 'boolean' }

View file

@ -223,6 +223,9 @@
margin-bottom: 6.5px
#student-projects-tab
.student-levels-table
margin-top: 0px
.student-info
margin-top: 5px

View file

@ -106,7 +106,7 @@ block content
if previousLevelCompleted || view.teacherMode || !passedLastCompletedLevel || levelStatus
- 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'))
if level.isType('game-dev', 'web-dev')
if level.get('shareable')
- var levelOriginal = level.get('original');
- var session = view.levelSessions.find(function(session) { return session.get('level').original === levelOriginal });
if session

View file

@ -21,7 +21,7 @@
.btn.btn-small.btn-illustrated.hints-button
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;
- if (view.options.courseID) url += '?course=' + view.options.courseID;
a.btn.btn-small.btn-illustrated(href=url)

View file

@ -52,7 +52,7 @@ module.exports = class CourseDetailsView extends RootView
@supermodel.trackRequest(@classroom.fetch())
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(=>

View file

@ -114,13 +114,13 @@ module.exports = class TeacherClassView extends RootView
@courses = new Courses()
@supermodel.trackRequest @courses.fetch()
@courseInstances = new CourseInstances()
@supermodel.trackRequest @courseInstances.fetchForClassroom(classroomID)
@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()
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()
assigningToNobody = selectedIDs.length is 0
@state.set errors: { assigningToNobody, assigningToUnenrolled }
return if assigningToNobody
@assignCourse courseID, members
window.tracker?.trackEvent 'Teachers Class Students Assign Selected', category: 'Teachers', classroomID: @classroom.id, courseID: courseID, ['Mixpanel']

View file

@ -397,7 +397,8 @@ module.exports = class CampaignView extends RootView
@particleMan.removeEmitters()
@particleMan.attach @$el.find('.map')
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 'replayable' if level.replayable
particleKey.push 'premium' if level.requiresSubscription

View file

@ -143,6 +143,7 @@ module.exports = class PlayLevelView extends RootView
onLevelLoaded: (e) ->
@god = new God({@gameUIState}) unless e.level.isType('web-dev')
@setUpGod() if @waitingToSetUpGod
trackLevelLoadEnd: ->
return if @isEditorPreview
@ -242,6 +243,8 @@ module.exports = class PlayLevelView extends RootView
setupGod: ->
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.setLevelSessionIDs if @otherSession then [@session.id, @otherSession.id] else [@session.id]
@god.setWorldClassMap @world.classMap

View file

@ -75,7 +75,7 @@ module.exports = class HeroVictoryModal extends ModalView
@saveReviewEventually = _.debounce(@saveReviewEventually, 2000)
@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}"
destroy: ->

View file

@ -24,7 +24,7 @@ module.exports = class ProgressView extends CocoView
# Images in Markdown are like ![description](url)
@nextLevel.get('description', true) # Make sure the defaults are available
@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 += "?course=#{@course.id}" if @course