mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Merged. Turn off chained rankings for now since they are slow and don't work anyway
This commit is contained in:
commit
f38eea3590
25 changed files with 290 additions and 203 deletions
|
@ -3,7 +3,7 @@ sudo: false
|
|||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.10
|
||||
- 5.1.1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
|
|
23
app/collections/Prepaids.coffee
Normal file
23
app/collections/Prepaids.coffee
Normal file
|
@ -0,0 +1,23 @@
|
|||
CocoCollection = require 'collections/CocoCollection'
|
||||
Prepaid = require 'models/Prepaid'
|
||||
|
||||
sum = (numbers) -> _.reduce(numbers, (a, b) -> a + b)
|
||||
|
||||
module.exports = class Prepaids extends CocoCollection
|
||||
model: Prepaid
|
||||
|
||||
url: "/db/prepaid"
|
||||
|
||||
totalMaxRedeemers: ->
|
||||
sum((prepaid.get('maxRedeemers') for prepaid in @models)) or 0
|
||||
|
||||
totalRedeemers: ->
|
||||
sum((_.size(prepaid.get('redeemers')) for prepaid in @models)) or 0
|
||||
|
||||
totalAvailable: -> Math.max(@totalMaxRedeemers() - @totalRedeemers(), 0)
|
||||
|
||||
fetchByCreator: (creatorID, opts) ->
|
||||
opts ?= {}
|
||||
opts.data ?= {}
|
||||
opts.data.creator = creatorID
|
||||
@fetch opts
|
|
@ -79,6 +79,7 @@ module.exports = class Tracker
|
|||
trackPageView: ->
|
||||
name = Backbone.history.getFragment()
|
||||
console.log "Would track analytics pageview: '/#{name}'" if debugAnalytics
|
||||
@trackEventInternal 'Pageview', url: name unless me?.isAdmin() and @isProduction
|
||||
return unless @isProduction and not me.isAdmin()
|
||||
|
||||
# Google Analytics
|
||||
|
|
|
@ -139,6 +139,8 @@ module.exports = class Simulator extends CocoClass
|
|||
|
||||
fetchAndSimulateTask: =>
|
||||
return if @destroyed
|
||||
# Because there's some bug where the chained rankings don't work, let's just do getTwoGames until we fix it.
|
||||
return @fetchAndSimulateOneGame()
|
||||
|
||||
if @options.headlessClient
|
||||
if @dumpThisTime # The first heapdump would be useless to find leaks.
|
||||
|
|
|
@ -480,10 +480,15 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
|||
unless thangType.rasterImage
|
||||
console.error("Cannot render the LayerAdapter SpriteSheet until the raster image for <#{thangType.get('name')}> is loaded.")
|
||||
|
||||
# hack for IE9, otherwise width/height are not set
|
||||
$img = $(thangType.rasterImage[0])
|
||||
$('body').append($img)
|
||||
|
||||
bm = new createjs.Bitmap(thangType.rasterImage[0])
|
||||
scale = thangType.get('scale') or 1
|
||||
frame = spriteSheetBuilder.addFrame(bm, null, scale)
|
||||
spriteSheetBuilder.addAnimation(@renderGroupingKey(thangType), [frame], false)
|
||||
$img.remove()
|
||||
|
||||
#- Distributing new Segmented/Singular/RasterSprites to Lanks
|
||||
|
||||
|
|
|
@ -12,14 +12,14 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
multiplayer: "Πολλαπλοί Παίκτες" # Not currently shown on home page
|
||||
for_developers: "Για προγραμματιστές" # Not currently shown on home page.
|
||||
or_ipad: "Ή κατεβάστε για iPad"
|
||||
# hoc_class_code: "I Have a Class Code"
|
||||
# hoc_enter: "Enter"
|
||||
# hoc_title: "Hour of Code?"
|
||||
hoc_class_code: "Έχω Κωδικό Τάξης "
|
||||
hoc_enter: "Είσοδος"
|
||||
hoc_title: "Ώρα του Κώδικα?"
|
||||
|
||||
nav:
|
||||
play: "Επίπεδα" # The top nav bar entry where players choose which levels to play
|
||||
community: "Κοινότητα"
|
||||
# courses: "Courses"
|
||||
courses: "Μαθήματα"
|
||||
editor: "Συγγραφέας"
|
||||
blog: "Ιστολόγιο"
|
||||
forum: "Φόρουμ"
|
||||
|
@ -54,7 +54,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
|
||||
play:
|
||||
play_as: "Παίξτε ως" # Ladder page
|
||||
# compete: "Compete!" # Course details page
|
||||
compete: "Αγωνίσου!" # Course details page
|
||||
spectate: "Θεατής" # Ladder page
|
||||
players: "παίκτες" # Hover over a level on /play
|
||||
hours_played: "ώρες παιχνιδιού" # Hover over a level on /play
|
||||
|
@ -65,7 +65,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
locked: "Κλειδωμένο"
|
||||
purchasable: "Διαθέσιμο για αγορά" # For a hero you unlocked but haven't purchased
|
||||
available: "Διαθέσιμο"
|
||||
# skills_granted: "Skills Granted" # Property documentation details
|
||||
skills_granted: "Παρεχόμενες Ικανότητες" # Property documentation details
|
||||
heroes: "Ήρωες" # Tooltip on hero shop button from /play
|
||||
achievements: "Επιτεύγματα" # Tooltip on achievement list button from /play
|
||||
account: "Λογαριασμός" # Tooltip on account button from /play
|
||||
|
@ -187,7 +187,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
password: "Κωδικός"
|
||||
message: "Μήνυμα"
|
||||
code: "Κώδικας"
|
||||
# ladder: "Ladder"
|
||||
ladder: "Κατατάξη"
|
||||
when: "Όταν"
|
||||
opponent: "Αντίπαλος"
|
||||
rank: "Κατηγορία"
|
||||
|
@ -221,10 +221,10 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
years: "χρόνια"
|
||||
|
||||
play_level:
|
||||
# completed_level: "Completed Level:"
|
||||
# course: "Course:"
|
||||
completed_level: "Ολοκληρωμένο Επίπεδο:"
|
||||
course: "Μάθημα:"
|
||||
done: "Έτοιμο"
|
||||
# next_level: "Next Level:"
|
||||
next_level: "Επομένο Επίπεδο:"
|
||||
next_game: "Επόμενο παιχνίδι"
|
||||
show_menu: "Εμφάνιση μενού παιχνιδιού"
|
||||
home: "Αρχική" # Not used any more, will be removed soon.
|
||||
|
@ -254,7 +254,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
victory_sign_up: "Εγγράψου για ενημερώσεις"
|
||||
victory_sign_up_poke: "Θέλεις να λαμβάνεις τα τελευταία νέα μέσω e-mail; Δημιούργησε έναν δωρεάν λογαριασμό και θα σε κρατάμε ενήμερο!"
|
||||
victory_rate_the_level: "Βαθμολογήστε το επίπεδο: " # {change}
|
||||
victory_return_to_ladder: "Επιστροφή στη Σκάλα"
|
||||
victory_return_to_ladder: "Επιστροφή στη Κατατάξη"
|
||||
victory_play_continue: "Συνέχισε"
|
||||
victory_saving_progress: "Αποθήκευση προόδου"
|
||||
victory_go_home: "Πήγαινε στην Αρχική"
|
||||
|
@ -262,8 +262,8 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
victory_review_placeholder: "Πως σου φάνηκε το επίπεδο;"
|
||||
victory_hour_of_code_done: "Τελείωσες;"
|
||||
victory_hour_of_code_done_yes: "Ναι, έχω τελειώσει με την Hour of Code!"
|
||||
victory_experience_gained: "Κερδισμενη Εμπειρία"
|
||||
victory_gems_gained: "Κερδισμενα Πετραδια"
|
||||
victory_experience_gained: "Εμπειρία"
|
||||
victory_gems_gained: "Πετραδια"
|
||||
victory_new_item: "Νέο αντικείμενο"
|
||||
victory_viking_code_school: "Μπράβο σου, μόλις πέρασες ένα δύσκολο επίπεδο! Αν δεν είσαι ήδη προγραμματιστής, πρέπει να γίνεις. Είσαι σε καλό δρόμο για να γίνεις δεκτός στο Σχολείο Προγρααματισμού των Βίκινγκ, όπου μπορείς να πας τις ικανότητες στο επόμενο επίπεδο και να γίνεις ένας επαγγελματίας προγραμματιστής ιστού σε 14 weeks."
|
||||
victory_become_a_viking: "Γίνε Βίκιγκ"
|
||||
|
@ -371,11 +371,11 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
leaderboard:
|
||||
view_other_solutions: "Προβολή Πίνακα Πρωτοπόρων"
|
||||
scores: "Σκορ"
|
||||
top_players: "Κορυφαίοι Παίκτες Κατά"
|
||||
day: "Ημέρα"
|
||||
week: "Αυτήν την εβδομάδα"
|
||||
all: "Παντοτινά"
|
||||
time: "Χρόνος"
|
||||
top_players: "Κορυφαιοι Παικτες "
|
||||
day: "Ημερας"
|
||||
week: "Εβδομαδας"
|
||||
all: "Ολων των Εποχων"
|
||||
time: "τη διαρκεια της"
|
||||
damage_taken: "Ζημιά που δέχθηκες"
|
||||
damage_dealt: "Ζημιά που αντιμετώπησες"
|
||||
difficulty: "δυσκολία"
|
||||
|
@ -621,10 +621,10 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
cost_premium_server: "Το CodeCombat είναι δωρεάν για τα πέντε πρώτα επίπεδα, μετά τα οποία κοστίζει $9.99 Δολλάρια ΗΠΑ το μήνα για να έχετε πρόσβαση στα πάνω από 190 επίπεδα στους αποκλειστικούς για τη χώρα εξυπηρετητές."
|
||||
free_1: "Υπάρχουν πάνω από 100 ΔΩΡΕΑΝ επίπεδα που καλύπτουν όλα τα αντικείμενα."
|
||||
free_2: "Η μηνιαία συνδρομή παρέχει πρόσβαση σε βίντεο βοηθήματα και παραπάνω επίπεδα για εξάσκηση."
|
||||
# free_3: "The CodeCombat content is divided into"
|
||||
# free_4: "courses"
|
||||
# free_5: ". The first course is free, and about an hour of material."
|
||||
# free_6: "Access to the additional courses can be unlocked with a one-time purchase."
|
||||
free_3: "Το περιεχομένο του CodeCombat χωρίζεται σε"
|
||||
free_4: "μαθήματα"
|
||||
free_5: ". Η πρώτη σειρά μαθημάτων είναι δωρεάν και περιέχει περίπου μια ώρα υλικού."
|
||||
free_6: "Πρόσβαση σε πρόσθετα μαθημάτα μπορεί να αποκτηθεί με αγορά συνδρομής."
|
||||
teacher_subs_title: "Οι εκπαιδευτικοί παίρνουν δωρεάν συνδρομές!" # {change}
|
||||
teacher_subs_0: "Προσφέρουμε δωρεάν συνδρομές σε εκπαιδευτικούς για να μπορέσουν να αξιολογήσουν το παιχνίδι." # {change}
|
||||
teacher_subs_1: "παρακαλούμε συμπληρώστε το"
|
||||
|
@ -678,15 +678,15 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
approved_1: "Η αίτησή σας για δωρεάν δοκιμαστική συνδρομή" # {change}
|
||||
approved_2: "εγκρίθηκε."
|
||||
approved_3: "Σας στείλαμε περισσότερες οδηγίες στο"
|
||||
# approved_4: "Enroll your students on the"
|
||||
# approved_5: "courses"
|
||||
# approved_6: "page."
|
||||
approved_4: "Γράψτε τους μάθητες σας στη"
|
||||
approved_5: "μαθήματα"
|
||||
approved_6: "σελίδα."
|
||||
denied_1: "Η αίτησή σας για δωρεάν δοκιμαστική συνδρομή" # {change}
|
||||
denied_2: "απορίφθηκε."
|
||||
contact_1: "Παρακαλούμε επικοινωνείστε"
|
||||
contact_2: "αν έχετε περαιτέρω ερωτήσεις."
|
||||
description_1: "Δίνουμε δωρεάν συνδρομές σε εκπαιδευτικούς για να αξιολογήσουν το παιχνίδι. Μπορείτε να βρείτε περισσότερες πληροφορίες στις"
|
||||
# description_1b: "You can find more information on our"
|
||||
description_1b: "Μπορείτε να βρείτε περισσότερες πληροφορίες στη"
|
||||
description_2: "εκπαιδευτική"
|
||||
description_3: "σελίδα."
|
||||
description_4: "Παρακαλούμε, συμπληρώστε αυτή τη φόρμα και θα σας στείλουμε οδηγίες."
|
||||
|
@ -779,7 +779,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
view_profile: "Προβολή του προφίλ σου"
|
||||
|
||||
keyboard_shortcuts:
|
||||
keyboard_shortcuts: "Συντομεύσει πληκτρολογίοθ"
|
||||
keyboard_shortcuts: "Συντομεύσεις πληκτρολογίου"
|
||||
space: "Κενό"
|
||||
enter: "Enter"
|
||||
press_enter: "πατείστε enter"
|
||||
|
@ -1289,9 +1289,9 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
|
|||
quantity: "Ποσότητα"
|
||||
redeemed: "Εξαγοράστηκε"
|
||||
no_codes: "No codes yet!"
|
||||
# you_can1: "You can"
|
||||
# you_can2: "purchase a prepaid code"
|
||||
# you_can3: "that can be applied to your own account or given to others."
|
||||
you_can1: "Μπορείτε"
|
||||
you_can2: "να αγοράσετε ένα προπληρωμένο κωδικό"
|
||||
you_can3: "που θα χρησιμοποιήσετε στο δικό σας λογαριασμό ή θα το δώσετε σε άλλους."
|
||||
|
||||
loading_error:
|
||||
could_not_load: "Σφάλμα φόρτωσης από τον εξυπηρετητή"
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
nav:
|
||||
play: "ゲームマップへ" # The top nav bar entry where players choose which levels to play
|
||||
community: "コミュニティー"
|
||||
# courses: "Courses"
|
||||
courses: "コース"
|
||||
editor: "レベルエディター"
|
||||
blog: "ブログ"
|
||||
forum: "掲示板"
|
||||
|
@ -53,8 +53,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
subscribe_as_diplomat: "外交官登録"
|
||||
|
||||
play:
|
||||
play_as: "としてプレー" # Ladder page
|
||||
# compete: "Compete!" # Course details page
|
||||
play_as: "プレイモード" # Ladder page
|
||||
compete: "コンプリート!" # Course details page
|
||||
spectate: "観戦" # Ladder page
|
||||
players: "プレイヤー" # Hover over a level on /play
|
||||
hours_played: "プレイ時間" # Hover over a level on /play
|
||||
|
@ -221,10 +221,10 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
years: "年"
|
||||
|
||||
play_level:
|
||||
# completed_level: "Completed Level:"
|
||||
# course: "Course:"
|
||||
completed_level: "コンプリートレベル:"
|
||||
course: "コース:"
|
||||
done: "完了"
|
||||
# next_level: "Next Level:"
|
||||
next_level: "次のレベル:"
|
||||
next_game: "次のゲーム"
|
||||
show_menu: "ゲームメニューを見る"
|
||||
home: "ホーム" # Not used any more, will be removed soon.
|
||||
|
@ -418,7 +418,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
feature7: "プライベート<strong>クラン</strong>"
|
||||
free: "無料"
|
||||
month: "月"
|
||||
# must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
|
||||
must_be_logged: "まずログインしてください。 アカウントを作るかメニューの上からログインをお願いします。"
|
||||
subscribe_title: "課金"
|
||||
unsubscribe: "無課金"
|
||||
confirm_unsubscribe: "課金の解約確認"
|
||||
|
@ -606,12 +606,12 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
jose_blurb: "テークオフ"
|
||||
retrostyle_title: "イラスト"
|
||||
retrostyle_blurb: "レトロスタイルのゲーム"
|
||||
# rob_title: "Compiler Engineer"
|
||||
# rob_blurb: "Codes things and stuff"
|
||||
# josh_c_title: "Game Designer"
|
||||
# josh_c_blurb: "Designs games"
|
||||
# carlos_title: "Region Manager, Brazil"
|
||||
# carlos_blurb: "Celery Man"
|
||||
rob_title: "コンパイラーエンジニアー"
|
||||
rob_blurb: "コードの道具と材料"
|
||||
josh_c_title: "ゲームデザイナー"
|
||||
josh_c_blurb: "ゲームのデザイン"
|
||||
carlos_title: "地域部長, ブラジル"
|
||||
carlos_blurb: "サラリーマン"
|
||||
|
||||
teachers:
|
||||
more_info: "教育関係者へのお知らせ"
|
||||
|
@ -1010,25 +1010,25 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
thang_main: "メイン"
|
||||
thang_spritesheets: "スプライトシート"
|
||||
thang_colors: "色"
|
||||
# level_some_options: "Some Options?"
|
||||
# level_tab_thangs: "Thangs"
|
||||
# level_tab_scripts: "Scripts"
|
||||
# level_tab_settings: "Settings"
|
||||
# level_tab_components: "Components"
|
||||
# level_tab_systems: "Systems"
|
||||
# level_tab_docs: "Documentation"
|
||||
# level_tab_thangs_title: "Current Thangs"
|
||||
# level_tab_thangs_all: "All"
|
||||
# level_tab_thangs_conditions: "Starting Conditions"
|
||||
# level_tab_thangs_add: "Add Thangs"
|
||||
# level_tab_thangs_search: "Search thangs"
|
||||
# add_components: "Add Components"
|
||||
# component_configs: "Component Configurations"
|
||||
# config_thang: "Double click to configure a thang"
|
||||
# delete: "Delete"
|
||||
# duplicate: "Duplicate"
|
||||
# stop_duplicate: "Stop Duplicate"
|
||||
# rotate: "Rotate"
|
||||
level_some_options: "オプションを付けますか?"
|
||||
level_tab_thangs: "サング"
|
||||
level_tab_scripts: "スクリプト"
|
||||
level_tab_settings: "セッティング"
|
||||
level_tab_components: "コンポーネント"
|
||||
level_tab_systems: "システム"
|
||||
level_tab_docs: "文章"
|
||||
level_tab_thangs_title: "現在のサング"
|
||||
level_tab_thangs_all: "すべて"
|
||||
level_tab_thangs_conditions: "コンディションの開始"
|
||||
level_tab_thangs_add: "サングの追加"
|
||||
level_tab_thangs_search: "サングの検索"
|
||||
add_components: "コンポーネントの追加"
|
||||
component_configs: "コンポーネントの設定"
|
||||
config_thang: "ダブルクリックでサングの設定"
|
||||
delete: "削除"
|
||||
duplicate: "重複"
|
||||
stop_duplicate: "重複をやめる"
|
||||
rotate: "回転"
|
||||
# level_settings_title: "Settings"
|
||||
# level_component_tab_title: "Current Components"
|
||||
# level_component_btn_new: "Create New Component"
|
||||
|
@ -1070,9 +1070,9 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
# add_system_title: "Add Systems to Level"
|
||||
# done_adding: "Done Adding"
|
||||
|
||||
# article:
|
||||
# edit_btn_preview: "Preview"
|
||||
# edit_article_title: "Edit Article"
|
||||
article:
|
||||
edit_btn_preview: "プレビュー"
|
||||
edit_article_title: "アーティクルの設定"
|
||||
|
||||
polls:
|
||||
priority: "プライオリティ"
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#classroom-view
|
||||
|
||||
.enable-btn
|
||||
margin: 1px
|
||||
|
||||
#main-button-area
|
||||
.btn
|
||||
margin-left: 10px
|
||||
|
||||
|
||||
#student-stats-row
|
||||
margin-bottom: 20px
|
||||
|
||||
|
||||
.progress
|
||||
margin-bottom: 5px
|
||||
|
||||
|
@ -14,4 +18,4 @@
|
|||
|
||||
.progress-bar-default
|
||||
background-color: white
|
||||
color: grey
|
||||
color: grey
|
||||
|
|
|
@ -39,6 +39,10 @@ block modal-body-content
|
|||
- var paid = user.get('coursePrepaidID')
|
||||
input(type="checkbox", disabled=paid, checked=true, data-user-id=user.id, name='user')
|
||||
span.spr= user.broadName()
|
||||
if paid
|
||||
span (
|
||||
span already enrolled
|
||||
span )
|
||||
|
||||
#error-alert.alert.alert-danger.hide
|
||||
|
||||
|
@ -61,7 +65,7 @@ block modal-body-content
|
|||
| )
|
||||
|
||||
p
|
||||
button#activate-licenses-btn.btn.btn-success.text-uppercase(type="submit") Activate Licenses
|
||||
button#activate-licenses-btn.btn.btn-success.text-uppercase(type="submit") Enroll Students
|
||||
|
||||
p
|
||||
a#get-more-licenses-btn.btn.btn-info.text-uppercase(href="/courses/purchase") Get More Licenses
|
||||
|
|
|
@ -2,109 +2,119 @@ extends /templates/base
|
|||
|
||||
block content
|
||||
|
||||
- var isOwner = view.classroom.get('ownerID') === me.id;
|
||||
- var isOwner = view.classroom ? view.classroom.get('ownerID') === me.id : false;
|
||||
if isOwner
|
||||
a(href="/courses/teachers") Back to my classrooms
|
||||
else
|
||||
a(href="/courses") Back to my courses
|
||||
|
||||
h1
|
||||
span.spr= view.classroom.get('name')
|
||||
if isOwner
|
||||
a#edit-class-details-link
|
||||
small Edit class details
|
||||
|
||||
if view.classroom.get('description')
|
||||
p= view.classroom.get('description')
|
||||
|
||||
h3(data-i18n="courses.stats")
|
||||
table.progress-stats-container
|
||||
- var stats = view.classStats()
|
||||
tr
|
||||
td(data-i18n="courses.total_students")
|
||||
td= _.size(view.classroom.get('members'))
|
||||
tr
|
||||
td(data-i18n="courses.average_time")
|
||||
td= stats.averagePlaytime
|
||||
tr
|
||||
td(data-i18n="courses.total_time")
|
||||
td= stats.totalPlaytime
|
||||
tr
|
||||
td(data-i18n="courses.average_levels")
|
||||
td= stats.averageLevelsComplete
|
||||
tr
|
||||
td(data-i18n="courses.total_levels")
|
||||
td= stats.totalLevelsComplete
|
||||
|
||||
h1
|
||||
| Students
|
||||
if view.teacherMode
|
||||
.pull-right#main-button-area
|
||||
button#add-students-btn.btn.btn-success Add Students
|
||||
button#activate-licenses-btn.btn.btn-warning Activate Licenses
|
||||
a.btn.btn-warning(href="/courses/purchase?from-classroom="+view.classroom.id) Purchase Licenses
|
||||
|
||||
hr
|
||||
|
||||
for user in view.users.models
|
||||
if view.teacherMode
|
||||
a.remove-student-link.pull-right.text-uppercase(data-user-id=user.id)
|
||||
span.glyphicon.glyphicon-remove
|
||||
span.spl remove student
|
||||
|
||||
h2= user.broadName()
|
||||
- var lastPlayedString = view.userLastPlayedString(user);
|
||||
- var playtime = view.userPlaytimeString(user);
|
||||
if lastPlayedString || playtime
|
||||
#student-stats-row.row
|
||||
if lastPlayedString
|
||||
.col-sm-6 Last Played: #{lastPlayedString}
|
||||
if playtime
|
||||
.col-sm-6 Playtime: #{playtime}
|
||||
|
||||
- var paidFor = user.get('coursePrepaidID');
|
||||
for courseInstance in view.courseInstances.models
|
||||
- var inCourse = _.contains(courseInstance.get('members'), user.id);
|
||||
if !(inCourse || view.teacherMode)
|
||||
- continue;
|
||||
- var course = view.courses.get(courseInstance.get('courseID'));
|
||||
- var campaign = view.campaigns.get(course.get('campaignID'));
|
||||
- var sessions = courseInstance.sessionsByUser[user.id] || [];
|
||||
if !(course.get('free') || paidFor)
|
||||
- continue;
|
||||
.row
|
||||
.col-sm-3.text-right= campaign.get('fullName')
|
||||
.col-sm-9
|
||||
if inCourse
|
||||
- var levels = campaign.get('levels');
|
||||
- var numLevels = Object.keys(levels).length;
|
||||
- var sessionMap = _.zipObject(_.map(sessions, function(s) { return s.get('level').original; }), sessions);
|
||||
- var levelCellWidth = 100.00;
|
||||
if numLevels > 0
|
||||
- levelCellWidth = 100.00 / numLevels;
|
||||
- var css = "width:"+levelCellWidth+"%;"
|
||||
- var i = 0;
|
||||
.progress
|
||||
each level, levelID in campaign.get('levels')
|
||||
- i++
|
||||
- var session = sessionMap[levelID];
|
||||
a(href=view.getLevelURL(level, course, courseInstance, session))
|
||||
- var content = view.levelPopoverContent(level, session, i);
|
||||
if session && session.get('state') && session.get('state').complete
|
||||
.progress-bar.progress-bar-success(style=css, data-content=content, data-toggle='popover')= i
|
||||
else if session
|
||||
.progress-bar.progress-bar-warning(style=css, data-content=content, data-toggle='popover')= i
|
||||
else
|
||||
.progress-bar.progress-bar-default(style=css, data-content=content, data-toggle='popover')= i
|
||||
else if paidFor
|
||||
button.enable-btn.btn.btn-info.btn-sm(data-user-id=user.id, data-course-instance-cid=courseInstance.cid) Enable
|
||||
|
||||
|
||||
if view.teacherMode && !paidFor
|
||||
.text-center
|
||||
p
|
||||
em Activate a license to enable more courses for this student.
|
||||
p
|
||||
button.activate-single-license-btn.btn.btn-info.btn-sm(data-user-id=user.id) Activate
|
||||
if !me.isAnonymous()
|
||||
h1
|
||||
span.spr= view.classroom.get('name')
|
||||
if isOwner
|
||||
a#edit-class-details-link
|
||||
small Edit class details
|
||||
|
||||
if view.classroom.get('description')
|
||||
p= view.classroom.get('description')
|
||||
|
||||
h3(data-i18n="courses.stats")
|
||||
table.progress-stats-container
|
||||
- var stats = view.classStats()
|
||||
tr
|
||||
td(data-i18n="courses.total_students")
|
||||
td
|
||||
span.spr= _.size(view.classroom.get('members'))
|
||||
span (
|
||||
span.spr enrolled in paid courses:
|
||||
span= stats.enrolledUsers
|
||||
span )
|
||||
tr
|
||||
td(data-i18n="courses.average_time")
|
||||
td= stats.averagePlaytime
|
||||
tr
|
||||
td(data-i18n="courses.total_time")
|
||||
td= stats.totalPlaytime
|
||||
tr
|
||||
td(data-i18n="courses.average_levels")
|
||||
td= stats.averageLevelsComplete
|
||||
tr
|
||||
td(data-i18n="courses.total_levels")
|
||||
td= stats.totalLevelsComplete
|
||||
|
||||
h1
|
||||
| Students
|
||||
if view.teacherMode
|
||||
.pull-right#main-button-area
|
||||
button#add-students-btn.btn.btn-primary.text-uppercase Add Students
|
||||
button#activate-licenses-btn.btn.btn-info.text-uppercase Enroll Students in Paid Courses
|
||||
a.btn.btn-success.text-uppercase(href="/courses/purchase?from-classroom="+view.classroom.id) Purchase Enrollments
|
||||
|
||||
hr
|
||||
|
||||
for user in view.users.models
|
||||
if view.teacherMode
|
||||
a.remove-student-link.pull-right.text-uppercase(data-user-id=user.id)
|
||||
span.glyphicon.glyphicon-remove
|
||||
span.spl remove student
|
||||
|
||||
h2= user.broadName()
|
||||
- var lastPlayedString = view.userLastPlayedString(user);
|
||||
- var playtime = view.userPlaytimeString(user);
|
||||
if lastPlayedString || playtime
|
||||
#student-stats-row.row
|
||||
if lastPlayedString
|
||||
.col-sm-6 Last Played: #{lastPlayedString}
|
||||
if playtime
|
||||
.col-sm-6 Playtime: #{playtime}
|
||||
|
||||
- var paidFor = user.get('coursePrepaidID');
|
||||
for courseInstance in view.courseInstances.models
|
||||
- var inCourse = _.contains(courseInstance.get('members'), user.id);
|
||||
if !(inCourse || view.teacherMode)
|
||||
- continue;
|
||||
- var course = view.courses.get(courseInstance.get('courseID'));
|
||||
- var campaign = view.campaigns.get(course.get('campaignID'));
|
||||
- var sessions = courseInstance.sessionsByUser[user.id] || [];
|
||||
if !(course.get('free') || paidFor)
|
||||
- continue;
|
||||
if inCourse
|
||||
.row
|
||||
.col-sm-3.text-right= course.get('name')
|
||||
.col-sm-9
|
||||
if inCourse
|
||||
- var levels = campaign.get('levels');
|
||||
- var numLevels = Object.keys(levels).length;
|
||||
- var sessionMap = _.zipObject(_.map(sessions, function(s) { return s.get('level').original; }), sessions);
|
||||
- var levelCellWidth = 100.00;
|
||||
if numLevels > 0
|
||||
- levelCellWidth = 100.00 / numLevels;
|
||||
- var css = "width:"+levelCellWidth+"%;"
|
||||
- var i = 0;
|
||||
.progress
|
||||
each level, levelID in campaign.get('levels')
|
||||
- i++
|
||||
- var session = sessionMap[levelID];
|
||||
a(href=view.getLevelURL(level, course, courseInstance, session))
|
||||
- var content = view.levelPopoverContent(level, session, i);
|
||||
if session && session.get('state') && session.get('state').complete
|
||||
.progress-bar.progress-bar-success(style=css, data-content=content, data-toggle='popover')= i
|
||||
else if session
|
||||
.progress-bar.progress-bar-warning(style=css, data-content=content, data-toggle='popover')= i
|
||||
else
|
||||
.progress-bar.progress-bar-default(style=css, data-content=content, data-toggle='popover')= i
|
||||
else if paidFor
|
||||
.text-center
|
||||
button.enable-btn.btn.btn-info.btn-sm.text-uppercase(data-user-id=user.id, data-course-instance-cid=courseInstance.cid) Assign #{course.get('name')}
|
||||
|
||||
|
||||
if view.teacherMode && !paidFor
|
||||
.text-center
|
||||
p
|
||||
em
|
||||
span.spr Enroll
|
||||
strong.spr= user.broadName()
|
||||
span to assign paid courses.
|
||||
p
|
||||
button.activate-single-license-btn.btn.btn-info.btn-sm.text-uppercase(data-user-id=user.id) Enroll #{user.broadName()}
|
||||
hr
|
||||
|
|
|
@ -25,7 +25,7 @@ block content
|
|||
.alert.alert-danger= view.stateMessage
|
||||
|
||||
p.text-center
|
||||
strong How many enrollments do you need?
|
||||
strong How many additional paid enrollments do you need?
|
||||
br
|
||||
|
||||
p.text-center
|
||||
|
@ -38,7 +38,9 @@ block content
|
|||
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-offset-3.col-md-6 One enrollment per student is required to assign them to paid CodeCombat courses. A single student does not need multiple enrollments to access all paid courses.
|
||||
.col-md-offset-3.col-md-6
|
||||
| Each student in a class will get access to Course 2 and up once they are enrolled in paid courses.
|
||||
| You may assign each course to each student individually.
|
||||
br
|
||||
|
||||
p.text-center#price-form-group
|
||||
|
|
|
@ -54,6 +54,18 @@ block content
|
|||
|
||||
br
|
||||
.section-header Available Courses
|
||||
|
||||
if !me.isAnonymous()
|
||||
p.text-center
|
||||
strong.spr Unused enrollments available:
|
||||
strong.spr= view.prepaids.totalAvailable()
|
||||
a.btn.btn-success.btn(href="/courses/purchase") Purchase Enrollments
|
||||
|
||||
p
|
||||
| All students get access to Introduction to Computer Science for free.
|
||||
| One enrollment per student is required to assign them to paid CodeCombat courses.
|
||||
| A single student does not need multiple enrollments to access all paid courses.
|
||||
|
||||
.container-fluid
|
||||
- var courses = view.courses.models;
|
||||
- var i = 0;
|
||||
|
|
|
@ -11,13 +11,13 @@ p.simulation-count
|
|||
span.spr(data-i18n="ladder.games_simulated_by") Games simulated by you:
|
||||
span#simulated-by-you= me.get('simulatedBy') || 0
|
||||
|
||||
p.simulation-count
|
||||
span.spr(data-i18n="ladder.games_simulated_for") Games simulated for you:
|
||||
span#simulated-for-you= me.get('simulatedFor') || 0
|
||||
//p.simulation-count
|
||||
// span.spr(data-i18n="ladder.games_simulated_for") Games simulated for you:
|
||||
// span#simulated-for-you= me.get('simulatedFor') || 0
|
||||
|
||||
p.simulation-count
|
||||
span.spr(data-i18n="ladder.games_in_queue") Games currently in the queue:
|
||||
span#games-in-queue= numberOfGamesInQueue || 0
|
||||
//p.simulation-count
|
||||
// span.spr(data-i18n="ladder.games_in_queue") Games currently in the queue:
|
||||
// span#games-in-queue= numberOfGamesInQueue || 0
|
||||
|
||||
table.table.table-bordered.table-condensed.table-hover
|
||||
thead
|
||||
|
@ -25,8 +25,8 @@ table.table.table-bordered.table-condensed.table-hover
|
|||
th
|
||||
th(data-i18n="general.player").name-col-cell Player
|
||||
th(data-i18n="ladder.games_simulated") Games simulated
|
||||
th(data-i18n="ladder.games_played") Games played
|
||||
th(data-i18n="ladder.ratio") Ratio
|
||||
//th(data-i18n="ladder.games_played") Games played
|
||||
//th(data-i18n="ladder.ratio") Ratio
|
||||
tbody
|
||||
- var topSimulators = simulatorsLeaderboardData.topSimulators.models;
|
||||
- var showJustTop = simulatorsLeaderboardData.inTopSimulators() || me.get('anonymous');
|
||||
|
@ -37,8 +37,8 @@ table.table.table-bordered.table-condensed.table-hover
|
|||
td.simulator-leaderboard-cell= rank + 1
|
||||
td.name-col-cell= user.get('name') || "Anonymous"
|
||||
td.simulator-leaderboard-cell= user.get('simulatedBy')
|
||||
td.simulator-leaderboard-cell= user.get('simulatedFor')
|
||||
td.simulator-leaderboard-cell= Math.round((user.get('simulatedBy') / user.get('simulatedFor')) * 10) / 10
|
||||
//td.simulator-leaderboard-cell= user.get('simulatedFor')
|
||||
//td.simulator-leaderboard-cell= Math.round((user.get('simulatedBy') / user.get('simulatedFor')) * 10) / 10
|
||||
|
||||
if !showJustTop && simulatorsLeaderboardData.nearbySimulators().length
|
||||
tr(class="active")
|
||||
|
@ -50,5 +50,5 @@ table.table.table-bordered.table-condensed.table-hover
|
|||
td.simulator-leaderboard-cell= user.rank
|
||||
td.name-col-cell= user.get('name') || "Anonymous"
|
||||
td.simulator-leaderboard-cell= user.get('simulatedBy')
|
||||
td.simulator-leaderboard-cell= user.get('simulatedFor')
|
||||
td.simulator-leaderboard-cell= _.isNaN(ratio) || ratio == Infinity ? '' : ratio.toFixed(1)
|
||||
//td.simulator-leaderboard-cell= user.get('simulatedFor')
|
||||
//td.simulator-leaderboard-cell= _.isNaN(ratio) || ratio == Infinity ? '' : ratio.toFixed(1)
|
||||
|
|
|
@ -111,7 +111,7 @@ module.exports = class DiplomatView extends ContributeClassView
|
|||
cs: ['Martin005', 'Gygram', 'vanous'] # čeština, Czech
|
||||
sv: ['iamhj', 'Galaky'] # Svenska, Swedish
|
||||
id: ['mlewisno-oberlin'] # Bahasa Indonesia, Indonesian
|
||||
el: ['Stergios'] # ελληνικά, Greek
|
||||
el: ['Stergios','micman','zsdregas'] # ελληνικά, Greek
|
||||
ro: [] # limba română, Romanian
|
||||
vi: ['An Nguyen Hoang Thien'] # Tiếng Việt, Vietnamese
|
||||
hu: ['Anon', 'atlantisguru', 'bbeasmile', 'csuvsaregal', 'divaDseidnA', 'ferpeter', 'kinez'] # magyar, Hungarian
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
ModalView = require 'views/core/ModalView'
|
||||
template = require 'templates/courses/activate-licenses-modal'
|
||||
CocoCollection = require 'collections/CocoCollection'
|
||||
Prepaid = require 'models/Prepaid'
|
||||
Prepaids = require 'collections/Prepaids'
|
||||
User = require 'models/User'
|
||||
|
||||
module.exports = class ActivateLicensesModal extends ModalView
|
||||
|
@ -16,12 +16,10 @@ module.exports = class ActivateLicensesModal extends ModalView
|
|||
@classroom = options.classroom
|
||||
@users = options.users
|
||||
@user = options.user
|
||||
@prepaids = new CocoCollection([], { url: "/db/prepaid", model: Prepaid })
|
||||
sum = (numbers) -> _.reduce(numbers, (a, b) -> a + b)
|
||||
@prepaids.totalMaxRedeemers = -> sum((prepaid.get('maxRedeemers') for prepaid in @models)) or 0
|
||||
@prepaids.totalRedeemers = -> sum((_.size(prepaid.get('redeemers')) for prepaid in @models)) or 0
|
||||
@prepaids = new Prepaids()
|
||||
@prepaids.comparator = '_id'
|
||||
@supermodel.loadCollection(@prepaids, 'prepaids', {data: {creator: me.id}})
|
||||
@prepaids.fetchByCreator(me.id)
|
||||
@supermodel.loadCollection(@prepaids, 'prepaids')
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
|
@ -39,7 +37,7 @@ module.exports = class ActivateLicensesModal extends ModalView
|
|||
depleted = remaining < 0
|
||||
@$('#not-depleted-span').toggleClass('hide', depleted)
|
||||
@$('#depleted-span').toggleClass('hide', !depleted)
|
||||
@$('#activate-licenses-btn').toggleClass('disabled', depleted)
|
||||
@$('#activate-licenses-btn').toggleClass('disabled', depleted).toggleClass('btn-success', not depleted).toggleClass('btn-default', depleted)
|
||||
|
||||
showProgress: ->
|
||||
@$('#submit-form-area').addClass('hide')
|
||||
|
|
|
@ -11,6 +11,10 @@ module.exports = class AddLevelSystemModal extends ModalView
|
|||
|
||||
initialize: (options) ->
|
||||
@classroom = options.classroom
|
||||
if @classroom
|
||||
application.tracker?.trackEvent 'Classroom started edit settings', category: 'Courses', classroomID: @classroom.id
|
||||
else
|
||||
application.tracker?.trackEvent 'Create new class', category: 'Courses'
|
||||
|
||||
onClickSaveSettingsButton: ->
|
||||
name = $('.settings-name-input').val()
|
||||
|
|
|
@ -29,6 +29,7 @@ module.exports = class ClassroomView extends RootView
|
|||
'click .remove-student-link': 'onClickRemoveStudentLink'
|
||||
|
||||
initialize: (options, classroomID) ->
|
||||
return if me.isAnonymous()
|
||||
@classroom = new Classroom({_id: classroomID})
|
||||
@supermodel.loadModel @classroom, 'classroom'
|
||||
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
||||
|
@ -99,6 +100,7 @@ module.exports = class ClassroomView extends RootView
|
|||
})
|
||||
@openModalView(modal)
|
||||
modal.once 'redeem-users', -> document.location.reload()
|
||||
application.tracker?.trackEvent 'Classroom started enroll students', category: 'Courses'
|
||||
|
||||
onClickActivateSingleLicenseButton: (e) ->
|
||||
userID = $(e.target).data('user-id')
|
||||
|
@ -110,6 +112,7 @@ module.exports = class ClassroomView extends RootView
|
|||
})
|
||||
@openModalView(modal)
|
||||
modal.once 'redeem-users', -> document.location.reload()
|
||||
application.tracker?.trackEvent 'Classroom started enroll student', category: 'Courses', userID: userID
|
||||
|
||||
onClickEditClassDetailsLink: ->
|
||||
modal = new ClassroomSettingsModal({classroom: @classroom})
|
||||
|
@ -144,16 +147,21 @@ module.exports = class ClassroomView extends RootView
|
|||
completeSessions = @sessions.filter (s) -> s.get('state')?.complete
|
||||
stats.averageLevelsComplete = if @users.size() then (_.size(completeSessions) / @users.size()).toFixed(1) else 'N/A'
|
||||
stats.totalLevelsComplete = _.size(completeSessions)
|
||||
|
||||
enrolledUsers = @users.filter (user) -> user.get('coursePrepaidID')
|
||||
stats.enrolledUsers = _.size(enrolledUsers)
|
||||
return stats
|
||||
|
||||
onClickAddStudentsButton: (e) ->
|
||||
modal = new InviteToClassroomModal({classroom: @classroom})
|
||||
@openModalView(modal)
|
||||
application.tracker?.trackEvent 'Classroom started add students', category: 'Courses', classroomID: @classroom.id
|
||||
|
||||
onClickEnableButton: (e) ->
|
||||
courseInstance = @courseInstances.get($(e.target).data('course-instance-cid'))
|
||||
userID = $(e.target).data('user-id')
|
||||
$(e.target).attr('disabled', true)
|
||||
application.tracker?.trackEvent 'Course assign student', category: 'Courses', courseInstanceID: courseInstance.id, userID: userID
|
||||
|
||||
onCourseInstanceCreated = =>
|
||||
courseInstance.addMember(userID)
|
||||
|
@ -179,6 +187,7 @@ module.exports = class ClassroomView extends RootView
|
|||
onStudentRemoved: (e) ->
|
||||
@users.remove(e.user)
|
||||
@render()
|
||||
application.tracker?.trackEvent 'Classroom removed student', category: 'Courses', courseInstanceID: @courseInstance.id, userID: e.user.id
|
||||
|
||||
levelPopoverContent: (level, session, i) ->
|
||||
return null unless level
|
||||
|
|
|
@ -199,8 +199,8 @@ module.exports = class CourseDetailsView extends RootView
|
|||
@loadAllCourses()
|
||||
|
||||
onClickPlayLevel: (e) ->
|
||||
levelSlug = $(e.target).data('level-slug')
|
||||
levelID = $(e.target).data('level-id')
|
||||
levelSlug = $(e.target).closest('.btn-play-level').data('level-slug')
|
||||
levelID = $(e.target).closest('.btn-play-level').data('level-id')
|
||||
level = @campaign.get('levels')[levelID]
|
||||
if level.type is 'course-ladder'
|
||||
viewClass = 'views/ladder/LadderView'
|
||||
|
|
|
@ -139,6 +139,7 @@ module.exports = class CoursesView extends RootView
|
|||
classroomName: newClassroom.get('name')
|
||||
ownerID: newClassroom.get('ownerID')
|
||||
}
|
||||
location.search = '' # Prevent another student from logging in later with the _cc query param in place
|
||||
@classrooms.add(newClassroom)
|
||||
@render()
|
||||
@classroomJustAdded = newClassroom.id
|
||||
|
|
|
@ -28,7 +28,7 @@ module.exports = class HourOfCodeView extends RootView
|
|||
@courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
|
||||
@listenToOnce @courseInstances, 'sync', @onCourseInstancesLoaded
|
||||
@courseInstances.comparator = (ci) -> return ci.get('classroomID') + ci.get('courseID')
|
||||
@supermodel.loadCollection(@courseInstances, 'course_instances')
|
||||
@supermodel.loadCollection(@courseInstances, 'course_instances', { cache: false })
|
||||
|
||||
onCourseInstancesLoaded: ->
|
||||
@hourOfCodeCourseInstance = @courseInstances.findWhere({hourOfCode: true})
|
||||
|
@ -39,7 +39,7 @@ module.exports = class HourOfCodeView extends RootView
|
|||
})
|
||||
@sessions.comparator = 'created'
|
||||
@listenTo @sessions, 'sync', @onSessionsLoaded
|
||||
@supermodel.loadCollection(@sessions, 'sessions')
|
||||
@supermodel.loadCollection(@sessions, 'sessions', { cache: false })
|
||||
|
||||
onSessionsLoaded: ->
|
||||
@lastSession = @sessions.last()
|
||||
|
@ -88,10 +88,10 @@ module.exports = class HourOfCodeView extends RootView
|
|||
@$('#main-content').hide()
|
||||
@$('#begin-hoc-area').removeClass('hide')
|
||||
hocCourseInstance = new CourseInstance()
|
||||
hocCourseInstance.upsertForHOC()
|
||||
hocCourseInstance.upsertForHOC({cache: false})
|
||||
@listenToOnce hocCourseInstance, 'sync', ->
|
||||
url = hocCourseInstance.firstLevelURL()
|
||||
app.router.navigate(url, { trigger: true })
|
||||
document.location.href = url
|
||||
|
||||
onClickLogInButton: ->
|
||||
modal = new StudentLogInModal()
|
||||
|
|
|
@ -4,7 +4,7 @@ template = require 'templates/courses/invite-to-classroom-modal'
|
|||
module.exports = class InviteToClassroomModal extends ModalView
|
||||
id: 'invite-to-classroom-modal'
|
||||
template: template
|
||||
|
||||
|
||||
events:
|
||||
'click #send-invites-btn': 'onClickSendInvitesButton'
|
||||
'click #copy-url-btn, #join-url-input': 'copyURL'
|
||||
|
@ -23,6 +23,7 @@ module.exports = class InviteToClassroomModal extends ModalView
|
|||
url = @classroom.url() + '/invite-members'
|
||||
@$('#send-invites-btn, #invite-emails-textarea').addClass('hide')
|
||||
@$('#invite-emails-sending-alert').removeClass('hide')
|
||||
application.tracker?.trackEvent 'Classroom invite via email', category: 'Courses', classroomID: @classroom.id, emails: emails
|
||||
|
||||
$.ajax({
|
||||
url: url
|
||||
|
@ -39,6 +40,7 @@ module.exports = class InviteToClassroomModal extends ModalView
|
|||
try
|
||||
document.execCommand('copy')
|
||||
@$('#copied-alert').removeClass('hide')
|
||||
application.tracker?.trackEvent 'Classroom copy URL', category: 'Courses', classroomID: @classroom.id, url: @joinURL
|
||||
catch err
|
||||
console.log('Oops, unable to copy', err)
|
||||
@$('#copy-failed-alert').removeClass('hide')
|
||||
|
|
|
@ -10,6 +10,7 @@ CourseInstance = require 'models/CourseInstance'
|
|||
RootView = require 'views/core/RootView'
|
||||
template = require 'templates/courses/teacher-courses-view'
|
||||
ClassroomSettingsModal = require 'views/courses/ClassroomSettingsModal'
|
||||
Prepaids = require 'collections/Prepaids'
|
||||
|
||||
module.exports = class TeacherCoursesView extends RootView
|
||||
id: 'teacher-courses-view'
|
||||
|
@ -32,6 +33,11 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
@courseInstances.comparator = 'courseID'
|
||||
@courseInstances.sliceWithMembers = -> return @filter (courseInstance) -> _.size(courseInstance.get('members')) and courseInstance.get('classroomID')
|
||||
@supermodel.loadCollection(@courseInstances, 'course_instances', {data: {ownerID: me.id}})
|
||||
@prepaids = new Prepaids()
|
||||
@prepaids.comparator = '_id'
|
||||
if not me.isAnonymous()
|
||||
@prepaids.fetchByCreator(me.id)
|
||||
@supermodel.loadCollection(@prepaids, 'prepaids') # just registers
|
||||
@members = new CocoCollection([], { model: User })
|
||||
@listenTo @members, 'sync', @render
|
||||
@
|
||||
|
@ -51,6 +57,7 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
return
|
||||
modal = new InviteToClassroomModal({classroom: classroom})
|
||||
@openModalView(modal)
|
||||
application.tracker?.trackEvent 'Classroom started add students', category: 'Courses', classroomID: classroom.id
|
||||
|
||||
onClickCreateNewClassButton: ->
|
||||
return @openModalView new AuthModal() if me.get('anonymous')
|
||||
|
@ -70,7 +77,7 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
modal = new ClassroomSettingsModal({classroom: classroom})
|
||||
@openModalView(modal)
|
||||
@listenToOnce modal, 'hide', @render
|
||||
|
||||
|
||||
onLoaded: ->
|
||||
super()
|
||||
@addFreeCourseInstances()
|
||||
|
@ -92,4 +99,4 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
courseInstance.save(null, {validate: false})
|
||||
@courseInstances.add(courseInstance)
|
||||
@listenToOnce courseInstance, 'sync', @addFreeCourseInstances
|
||||
return
|
||||
return
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
"moment": "~2.5.0",
|
||||
"mongodb": "^2.0.28",
|
||||
"mongoose": "3.8.x",
|
||||
"mongoose": "^4.2.9",
|
||||
"mongoose-cache": "https://github.com/nwinter/mongoose-cache/tarball/master",
|
||||
"node-force-domain": "~0.1.0",
|
||||
"node-gyp": "~0.13.0",
|
||||
|
@ -125,7 +126,7 @@
|
|||
"license": "MIT for the code, and CC-BY for the art and music",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "0.10.x",
|
||||
"node": "^5.1.1",
|
||||
"npm": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ LevelSessionSchema.pre 'save', (next) ->
|
|||
log.error err if err?
|
||||
oldCopy = user.toObject()
|
||||
oldCopy.stats = _.clone oldCopy.stats
|
||||
oldCopy.stats ?= {gamesCompleted: 0}
|
||||
--oldCopy.stats.gamesCompleted
|
||||
oldCopy.stats.concepts ?= {}
|
||||
for concept in level?.concepts ? []
|
||||
|
|
|
@ -18,8 +18,9 @@ module.exports = createNewTask = (req, res) ->
|
|||
fetchAndVerifyLevelType.bind(yetiGuru, currentLevelID)
|
||||
fetchSessionObjectToSubmit.bind(yetiGuru, requestSessionID)
|
||||
updateSessionToSubmit.bind(yetiGuru, transpiledCode, req.user)
|
||||
fetchInitialSessionsToRankAgainst.bind(yetiGuru, requestLevelMajorVersion, originalLevelID)
|
||||
generateAndSendTaskPairsToTheQueue
|
||||
# Because there's some bug where the chained rankings don't work, and this is super slow, let's just not do this until we fix it.
|
||||
#fetchInitialSessionsToRankAgainst.bind(yetiGuru, requestLevelMajorVersion, originalLevelID)
|
||||
#generateAndSendTaskPairsToTheQueue
|
||||
], (err, successMessageObject) ->
|
||||
if err? then return errors.serverError res, "There was an error submitting the game to the queue: #{err}"
|
||||
scoringUtils.sendResponseObject res, successMessageObject
|
||||
|
|
Loading…
Reference in a new issue