mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-02 03:47:09 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
ff953dbd5a
14 changed files with 397 additions and 166 deletions
Binary file not shown.
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 192 KiB |
|
@ -790,6 +790,7 @@
|
|||
make_private: "Make clan private"
|
||||
subs_only: "subscribers only"
|
||||
create_clan: "Create New Clan"
|
||||
private_preview: "Preview"
|
||||
public_clans: "Public Clans"
|
||||
my_clans: "My Clans"
|
||||
clan_name: "Clan Name"
|
||||
|
|
|
@ -158,7 +158,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
unwatch: "No seguir"
|
||||
submit_patch: "Enviar Parche"
|
||||
submit_changes: "Enviar cambios"
|
||||
# save_changes: "Save Changes"
|
||||
save_changes: "Guardar cambios"
|
||||
|
||||
general:
|
||||
and: "y"
|
||||
|
@ -609,7 +609,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
sub_includes_4: "Soporte de correo electronico Premium"
|
||||
sub_includes_5: "7 heroes nuevos con habilidades unicas que dominar"
|
||||
sub_includes_6: "bonificación de 3500 gemas cada mes"
|
||||
# sub_includes_7: "Private Clans"
|
||||
sub_includes_7: "Clanes privados"
|
||||
# monitor_progress_title: "How do I monitor student progress?"
|
||||
# monitor_progress_1: "Student progress can be monitored by creating a"
|
||||
# monitor_progress_2: "for your class."
|
||||
|
@ -635,39 +635,39 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
# how_much_6: "for more details."
|
||||
# more_info_title: "Where can I find more information?"
|
||||
# more_info_1: "Our"
|
||||
# more_info_2: "teachers forum"
|
||||
# more_info_3: "is a good place to connect with fellow educators who are using CodeCombat."
|
||||
more_info_2: "el foro de profesores"
|
||||
more_info_3: "es un buen lugar para connectarse con los educadores que estan usando CodeCombat."
|
||||
sys_requirements_title: "Requerimientos del sistema"
|
||||
sys_requirements_1: "Debido que CodeCombat es un juego, es más difícil para las computadoras correrlo en relación a un tutorial escrito o un video. Para que todos puedan jugar, hemos optimizado la web para correr rápidamente en todos los navegadores modernos y en maquinas antiguas. Dicho esto, aquí están nuestras sugerencias para sacar el máximo provecho de su experiencia en la Hora del Código:" # {change}
|
||||
sys_requirements_2: "Usar una versión actualizada del navegador Chrome o Firefox." # {change}
|
||||
|
||||
# teachers_survey:
|
||||
teachers_survey:
|
||||
# title: "Teacher Survey"
|
||||
# must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
|
||||
# retrieving: "Retrieving information..."
|
||||
# being_reviewed_1: "Your application for a free trial subscription is being"
|
||||
# being_reviewed_2: "reviewed."
|
||||
# approved_1: "Your application for a free trial subscription was"
|
||||
# approved_2: "approved."
|
||||
approved_2: "Aprobada."
|
||||
# approved_3: "Further instructions have been sent to"
|
||||
# denied_1: "Your application for a free trial subscription has been"
|
||||
# denied_2: "denied."
|
||||
# contact_1: "Please contact"
|
||||
denied_2: "denegadae."
|
||||
contact_1: "Porfavor contactarse"
|
||||
# contact_2: "if you have further questions."
|
||||
# description_1: "We offer free subscriptions to teachers for evaluation purposes. You can find more information on our"
|
||||
# description_2: "teachers"
|
||||
# description_3: "page."
|
||||
# description_4: "Please fill out this quick survey and we’ll email you setup instructions."
|
||||
# email: "Email Address"
|
||||
# school: "Name of School"
|
||||
# location: "Name of City"
|
||||
# age_students: "How old are your students?"
|
||||
email: "Dirección de email"
|
||||
school: "Nombre del colegio"
|
||||
location: "Nombre de la ciudad"
|
||||
age_students: "¿Qué edad tienen tus estudiantes?"
|
||||
# under: "Under"
|
||||
# other: "Other:"
|
||||
# amount_students: "How many students do you teach?"
|
||||
# hear_about: "How did you hear about CodeCombat?"
|
||||
# fill_fields: "Please fill out all fields."
|
||||
# thanks: "Thanks! We'll send you setup instructions shortly."
|
||||
amount_students: "¿A cuantos alumnos les enseñas?"
|
||||
hear_about: "¿Donde escuchaste sobre CodeCombat?"
|
||||
fill_fields: "Porfavor llenar todos los campos."
|
||||
thanks: "Gracias! Vamos a mandarte instrucciónes para iniciar proximamente."
|
||||
|
||||
versions:
|
||||
save_version_title: "Guardar nueva versión"
|
||||
|
@ -705,7 +705,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
picture_tab: "Imagen"
|
||||
delete_account_tab: "Borra tu cuenta"
|
||||
wrong_email: "Mail Incorrecto"
|
||||
# wrong_password: "Wrong Password"
|
||||
wrong_password: "Contraseña incorrecta"
|
||||
upload_picture: "Sube una imagen"
|
||||
delete_this_account: "Borrar esta cuenta permanentemente"
|
||||
god_mode: "Modo Dios"
|
||||
|
@ -746,7 +746,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
keyboard_shortcuts: "Atajos de teclado"
|
||||
space: "Barra espaciadora"
|
||||
enter: "Enter"
|
||||
# press_enter: "press enter"
|
||||
press_enter: "Toca enter"
|
||||
escape: "Escape"
|
||||
shift: "Shift"
|
||||
run_code: "Ejecutar el código."
|
||||
|
@ -781,48 +781,48 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
social_hipchat: "Chatea con nosotros en el chat público de CodeCombat en la sala HipChat"
|
||||
contribute_to_the_project: "Contribuir al proyecto"
|
||||
|
||||
# clans:
|
||||
# clan: "Clan"
|
||||
# clans: "Clans"
|
||||
# new_name: "New clan name"
|
||||
# new_description: "New clan description"
|
||||
# make_private: "Make clan private"
|
||||
# subs_only: "subscribers only"
|
||||
# create_clan: "Create New Clan"
|
||||
# public_clans: "Public Clans"
|
||||
# my_clans: "My Clans"
|
||||
# clan_name: "Clan Name"
|
||||
# name: "Name"
|
||||
clans:
|
||||
clan: "Clan"
|
||||
clans: "Clanes"
|
||||
new_name: "Nuevo nombre de clan"
|
||||
new_description: "descripción del clan"
|
||||
make_private: "Hacer clan privado"
|
||||
subs_only: "solo suscriptores"
|
||||
create_clan: "Crear nuevo clan"
|
||||
public_clans: "Clanes publicos"
|
||||
my_clans: "Mis Clanes"
|
||||
clan_name: "Nombre del clan"
|
||||
name: "Nombre"
|
||||
# chieftain: "Chieftain"
|
||||
# type: "Type"
|
||||
# edit_clan_name: "Edit Clan Name"
|
||||
# edit_clan_description: "Edit Clan Description"
|
||||
# edit_name: "edit name"
|
||||
# edit_description: "edit description"
|
||||
# private: "(private)"
|
||||
type: "Tipo"
|
||||
edit_clan_name: "Editar el nombre del Clan"
|
||||
edit_clan_description: "Editar descripción del clan"
|
||||
edit_name: "editar nombre"
|
||||
edit_description: "editar descripción"
|
||||
private: "(privado)"
|
||||
# summary: "Summary"
|
||||
# average_level: "Average Level"
|
||||
# average_achievements: "Average Achievements"
|
||||
# delete_clan: "Delete Clan"
|
||||
# leave_clan: "Leave Clan"
|
||||
# join_clan: "Join Clan"
|
||||
# invite_1: "Invite:"
|
||||
# invite_2: "*Invite players to this Clan by sending them this link."
|
||||
# members: "Members"
|
||||
# progress: "Progress"
|
||||
# not_started_1: "not started"
|
||||
# started_1: "started"
|
||||
# complete_1: "complete"
|
||||
# exp_levels: "Expand levels"
|
||||
# rem_hero: "Remove Hero"
|
||||
# status: "Status"
|
||||
# complete_2: "Complete"
|
||||
# started_2: "Started"
|
||||
# not_started_2: "Not Started"
|
||||
# view_solution: "Click to view solution."
|
||||
# latest_achievement: "Latest Achievement"
|
||||
# playtime: "Playtime"
|
||||
# last_played: "Last played"
|
||||
average_level: "Nivel Promedio"
|
||||
average_achievements: "Logros Promedio"
|
||||
delete_clan: "Borrar Clan"
|
||||
leave_clan: "Abandonar Clan"
|
||||
join_clan: "Ingresar Clan"
|
||||
invite_1: "Invitar:"
|
||||
invite_2: "*Invitar jugadores al clan, mandandoles este link."
|
||||
members: "Miembros"
|
||||
progress: "Progreso"
|
||||
not_started_1: "no iniciado"
|
||||
started_1: "iniciado"
|
||||
complete_1: "completo"
|
||||
exp_levels: "Expand levels"
|
||||
rem_hero: "Remover Heróe"
|
||||
status: "Stado"
|
||||
complete_2: "Completo"
|
||||
started_2: "Iniciado"
|
||||
not_started_2: "No inciiado"
|
||||
view_solution: "Click para ver la solución."
|
||||
latest_achievement: "último logro"
|
||||
playtime: "Tiempo de juego"
|
||||
last_played: "Último jugado"
|
||||
|
||||
classes:
|
||||
archmage_title: "Archimago"
|
||||
|
@ -1074,7 +1074,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
no_achievements: "Sin Logros todavía."
|
||||
favorite_prefix: "Idioma favorito "
|
||||
favorite_postfix: "."
|
||||
# not_member_of_clans: "Not a member of any clans yet."
|
||||
not_member_of_clans: "No se es miembro de ningún clan todavía."
|
||||
|
||||
achievements:
|
||||
last_earned: "Último Ganado"
|
||||
|
@ -1180,7 +1180,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
|
|||
user_remarks: "Observaciones del usuario"
|
||||
versions: "Versiones"
|
||||
items: "Items"
|
||||
# hero: "Hero"
|
||||
hero: "Heróe"
|
||||
heroes: "Héroes"
|
||||
achievement: "Logros"
|
||||
clas: "CLAs"
|
||||
|
|
|
@ -641,7 +641,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
sys_requirements_1: "モダンなブラウザ。最新の Chrome や FireFox, Safari など。Internet Explorer 9 以上。"
|
||||
sys_requirements_2: "CodeCombat はまだ iPad をサポートしていません。"
|
||||
|
||||
# teachers_survey:
|
||||
teachers_survey:
|
||||
# title: "Teacher Survey"
|
||||
# must_be_logged: "You must be logged in first. Please create an account or log in from the menu above."
|
||||
# retrieving: "Retrieving information..."
|
||||
|
@ -659,8 +659,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
# description_3: "page."
|
||||
# description_4: "Please fill out this quick survey and we’ll email you setup instructions."
|
||||
# email: "Email Address"
|
||||
# school: "Name of School"
|
||||
# location: "Name of City"
|
||||
school: "学校名"
|
||||
location: "市町村"
|
||||
# age_students: "How old are your students?"
|
||||
# under: "Under"
|
||||
# other: "Other:"
|
||||
|
@ -705,7 +705,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
picture_tab: "画像"
|
||||
delete_account_tab: "アカウントの削除"
|
||||
wrong_email: "間違ったメールアドレス"
|
||||
# wrong_password: "Wrong Password"
|
||||
wrong_password: "間違ったパスワード"
|
||||
upload_picture: "画像をアップロード"
|
||||
delete_this_account: "アカウントを完全削除する"
|
||||
god_mode: "ゴッドモード"
|
||||
|
@ -714,8 +714,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
admin: "管理者"
|
||||
new_password: "新パスワード"
|
||||
new_password_verify: "新パスワードを再入力"
|
||||
type_in_email: "削除を確認するため、メールを入力して下さい" # {change}
|
||||
# type_in_password: "Also, type in your password."
|
||||
type_in_email: "アカウントの削除を確認するために、メールアドレスを入力して下さい"
|
||||
type_in_password: "そして、パスワードを入力してください。"
|
||||
email_subscriptions: "ニュースレターの購読"
|
||||
email_subscriptions_none: "No Email Subscriptions."
|
||||
email_announcements: "お知らせ"
|
||||
|
@ -746,7 +746,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
keyboard_shortcuts: "キーボードショートカット"
|
||||
space: "スペース"
|
||||
enter: "エンター"
|
||||
# press_enter: "press enter"
|
||||
press_enter: "エンターを押す"
|
||||
escape: "エスケープ"
|
||||
shift: "シフト"
|
||||
run_code: "現在のコードを実行"
|
||||
|
|
|
@ -55,8 +55,11 @@
|
|||
vertical-align: middle
|
||||
|
||||
|
||||
.member-header
|
||||
cursor: pointer
|
||||
|
||||
.progress-header
|
||||
margin-right: 14px
|
||||
cursor: pointer
|
||||
|
||||
.progress-key
|
||||
cursor: default
|
||||
|
@ -74,6 +77,7 @@
|
|||
|
||||
.progress-key-complete
|
||||
background-color: lightgray
|
||||
margin-left: 14px
|
||||
|
||||
.expand-progress-checkbox
|
||||
margin-left: 14px
|
||||
|
@ -95,9 +99,23 @@
|
|||
background-color: blanchedalmond
|
||||
font-size: 10pt
|
||||
|
||||
.level-progression-campaign
|
||||
.level-progression-concepts
|
||||
color: #317EAC
|
||||
font-size: 12pt
|
||||
font-weight: bold
|
||||
margin-top: 8px
|
||||
margin-bottom: 4px
|
||||
|
||||
.level-progression-levels
|
||||
color: #317EAC
|
||||
font-size: 12pt
|
||||
font-weight: bold
|
||||
margin-top: 8px
|
||||
|
||||
.level-progression-campaign
|
||||
font-size: 10pt
|
||||
font-weight: bold
|
||||
margin-bottom: 4px
|
||||
margin-top: 4px
|
||||
|
||||
.progress-level-cell
|
||||
|
|
|
@ -10,3 +10,60 @@
|
|||
.select-session
|
||||
width: 300px
|
||||
display: inline
|
||||
|
||||
.progress-header
|
||||
margin-right: 14px
|
||||
|
||||
.progress-key
|
||||
cursor: default
|
||||
display: inline-block
|
||||
white-space: nowrap
|
||||
font-size: 9pt
|
||||
font-weight: normal
|
||||
border: 1px solid gray
|
||||
border-radius: 5px
|
||||
margin: 0px
|
||||
padding: 2px
|
||||
|
||||
.progress-key-started
|
||||
background-color: lightgreen
|
||||
|
||||
.progress-key-complete
|
||||
background-color: lightgray
|
||||
|
||||
.expand-progress-checkbox
|
||||
margin-left: 14px
|
||||
|
||||
.expand-progress-label
|
||||
font-weight: normal
|
||||
font-size: 14px
|
||||
|
||||
.progress-cell
|
||||
padding: 2px
|
||||
padding-bottom: 10px
|
||||
|
||||
.level-popup-container
|
||||
display: none
|
||||
position: absolute
|
||||
padding: 10px
|
||||
border: 1px solid black
|
||||
z-index: 3
|
||||
background-color: blanchedalmond
|
||||
font-size: 10pt
|
||||
|
||||
.progress-level-cell
|
||||
display: inline-block
|
||||
white-space: nowrap
|
||||
font-size: 9pt
|
||||
border: 1px solid gray
|
||||
border-radius: 5px
|
||||
margin: 0px
|
||||
padding: 2px
|
||||
|
||||
.progress-level-cell-started
|
||||
cursor: pointer
|
||||
background-color: lightgreen
|
||||
|
||||
.progress-level-cell-complete
|
||||
cursor: pointer
|
||||
background-color: lightgray
|
||||
|
|
|
@ -83,92 +83,111 @@ block content
|
|||
table.table.table-condensed
|
||||
thead
|
||||
tr
|
||||
th(data-i18n="resources.hero") Hero
|
||||
th
|
||||
span.progress-header(data-i18n="clans.progress") Progress
|
||||
span.progress-key(data-i18n="clans.not_started_1") not started
|
||||
span.member-header.spr(data-i18n="resources.hero") Hero
|
||||
if memberSort === 'nameAsc'
|
||||
span.member-header.glyphicon.glyphicon-chevron-up
|
||||
else if memberSort === 'nameDesc'
|
||||
span.member-header.glyphicon.glyphicon-chevron-down
|
||||
th
|
||||
span.progress-header.spr(data-i18n="clans.progress") Progress
|
||||
if memberSort === 'progressAsc'
|
||||
span.progress-header.glyphicon.glyphicon-chevron-up
|
||||
else if memberSort === 'progressDesc'
|
||||
span.progress-header.glyphicon.glyphicon-chevron-down
|
||||
else
|
||||
span(style='padding-left:16px;')
|
||||
span.spl.progress-key.progress-key-complete(data-i18n="clans.complete_1") complete
|
||||
span.progress-key.progress-key-started(data-i18n="clans.started_1") started
|
||||
span.progress-key.progress-key-complete(data-i18n="clans.complete_1") complete
|
||||
span.progress-key(data-i18n="clans.not_started_1") not started
|
||||
input.expand-progress-checkbox(type='checkbox')
|
||||
span.spl.expand-progress-label(data-i18n="clans.exp_levels") Expand levels
|
||||
tbody
|
||||
each member in members
|
||||
tr
|
||||
td
|
||||
div
|
||||
span.hero-icon-cell
|
||||
span.spr.player-hero-icon(data-memberid="#{member.id}")
|
||||
span.code-language-cell
|
||||
if memberLanguageMap && memberLanguageMap[member.id]
|
||||
span.code-language-cell(style="background-image: url(/images/common/code_languages/#{memberLanguageMap[member.id]}_small.png)", title=memberLanguageMap[member.id])
|
||||
div
|
||||
a(href="/user/#{member.id}")= member.get('name') || 'Anoner'
|
||||
div Level #{member.level()}
|
||||
if isOwner && member.id !== clan.get('ownerID')
|
||||
button.btn.btn-xs.btn-warning.remove-member-btn(data-id="#{member.id}", data-i18n="clans.rem_hero") Remove Hero
|
||||
td.progress-cell
|
||||
td
|
||||
div
|
||||
span.hero-icon-cell
|
||||
span.spr.player-hero-icon(data-memberid="#{member.id}")
|
||||
span.code-language-cell
|
||||
if memberLanguageMap && memberLanguageMap[member.id]
|
||||
span.code-language-cell(style="background-image: url(/images/common/code_languages/#{memberLanguageMap[member.id]}_small.png)", title=memberLanguageMap[member.id])
|
||||
div
|
||||
a(href="/user/#{member.id}")= member.get('name') || 'Anoner'
|
||||
div Level #{member.level()}
|
||||
if isOwner && member.id !== clan.get('ownerID')
|
||||
button.btn.btn-xs.btn-warning.remove-member-btn(data-id="#{member.id}", data-i18n="clans.rem_hero") Remove Hero
|
||||
td.progress-cell
|
||||
.level-progression-concepts Concepts
|
||||
each concept in conceptsProgression
|
||||
if userConceptsMap[member.id] && userConceptsMap[member.id][concept] === 'complete'
|
||||
span.spr.progress-level-cell.progress-level-cell-complete(data-i18n="concepts." + concept)
|
||||
else if userConceptsMap[member.id] && userConceptsMap[member.id][concept] === 'started'
|
||||
span.spr.progress-level-cell.progress-level-cell-started(data-i18n="concepts." + concept)
|
||||
else
|
||||
span.spr.progress-level-cell.progress-level-cell-not-started(data-i18n="concepts." + concept)
|
||||
.level-progression-levels Levels
|
||||
each campaign in campaignLevelProgressions
|
||||
if lastUserCampaignLevelMap[member.id] && lastUserCampaignLevelMap[member.id][campaign.ID]
|
||||
div.level-progression-campaign= campaign.name
|
||||
- var i = 0
|
||||
|
||||
each campaign in campaignLevelProgressions
|
||||
if lastUserCampaignLevelMap[member.id] && lastUserCampaignLevelMap[member.id][campaign.ID]
|
||||
div.level-progression-campaign= campaign.name
|
||||
- var i = 0
|
||||
|
||||
each level in campaign.levels
|
||||
- i++
|
||||
- var state = null, levelInfo = null
|
||||
if memberLevelStateMap[member.id][level.slug]
|
||||
- levelInfo = memberLevelStateMap[member.id][level.slug].levelInfo
|
||||
- state = memberLevelStateMap[member.id][level.slug].state
|
||||
if state === 'complete'
|
||||
span.progress-level-cell.progress-level-cell-complete(data-level-info=levelInfo) #{i}
|
||||
if showExpandedProgress || i === 1 || i === lastUserCampaignLevelMap[member.id][campaign.ID].index + 1
|
||||
span.spl #{level.name}
|
||||
.level-popup-container
|
||||
h3 #{i}. #{levelInfo.level}
|
||||
p
|
||||
each level in campaign.levels
|
||||
- i++
|
||||
- var state = null, levelInfo = null
|
||||
if memberLevelStateMap[member.id][level.slug]
|
||||
- levelInfo = memberLevelStateMap[member.id][level.slug].levelInfo
|
||||
- state = memberLevelStateMap[member.id][level.slug].state
|
||||
if state === 'complete'
|
||||
span.progress-level-cell.progress-level-cell-complete(data-level-info=levelInfo) #{i}
|
||||
if showExpandedProgress || i === 1 || i === lastUserCampaignLevelMap[member.id][campaign.ID].index + 1
|
||||
span.spl #{level.name}
|
||||
.level-popup-container
|
||||
h3 #{i}. #{levelInfo.level}
|
||||
p
|
||||
div
|
||||
span(data-i18n="clans.status") Status
|
||||
span.spr :
|
||||
span(data-i18n="clans.complete_2") Complete
|
||||
div
|
||||
span(data-i18n="clans.playtime") Playtime
|
||||
span : #{levelInfo.playtime}s
|
||||
div
|
||||
span(data-i18n="clans.last_played") Last played
|
||||
span : #{levelInfo.changed}
|
||||
if isOwner || me.isAdmin()
|
||||
strong(data-i18n="clans.view_solution") Click to view solution.
|
||||
else if state === 'started'
|
||||
span.progress-level-cell.progress-level-cell-started(data-level-info=levelInfo) #{i}
|
||||
if showExpandedProgress || i === 1 || i === lastUserCampaignLevelMap[member.id][campaign.ID].index + 1
|
||||
span.spl #{level.name}
|
||||
.level-popup-container
|
||||
h3 #{i}. #{level.name}
|
||||
p
|
||||
div
|
||||
span(data-i18n="clans.status") Status
|
||||
span.spr :
|
||||
span(data-i18n="clans.started_2") Started
|
||||
div
|
||||
span(data-i18n="clans.playtime") Playtime
|
||||
span : #{levelInfo.playtime}s
|
||||
div
|
||||
span(data-i18n="clans.last_played") Last played
|
||||
span : #{levelInfo.changed}
|
||||
if isOwner || me.isAdmin()
|
||||
strong(data-i18n="clans.view_solution") Click to view solution.
|
||||
else
|
||||
span.progress-level-cell.level-progression-level-not-started #{i}
|
||||
if showExpandedProgress || i === 1 || i === lastUserCampaignLevelMap[member.id][campaign.ID].index + 1
|
||||
span.spl #{level.name}
|
||||
.level-popup-container
|
||||
h3 #{i}. #{level.name}
|
||||
div
|
||||
span(data-i18n="choose_hero.status") Status
|
||||
span.spr :
|
||||
span(data-i18n="clans.complete_2") Complete
|
||||
div
|
||||
span(data-i18n="clans.playtime") Playtime
|
||||
span : #{levelInfo.playtime}s
|
||||
div
|
||||
span(data-i18n="clans.last_played") Last played
|
||||
span : #{levelInfo.changed}
|
||||
if isOwner || me.isAdmin()
|
||||
strong(data-i18n="clans.view_solution") Click to view solution.
|
||||
else if state === 'started'
|
||||
span.progress-level-cell.progress-level-cell-started(data-level-info=levelInfo) #{i}
|
||||
if showExpandedProgress || i === 1 || i === lastUserCampaignLevelMap[member.id][campaign.ID].index + 1
|
||||
span.spl #{level.name}
|
||||
.level-popup-container
|
||||
h3 #{i}. #{level.name}
|
||||
p
|
||||
div
|
||||
span(data-i18n="choose_hero.status") Status
|
||||
span.spr :
|
||||
span(data-i18n="clans.started_2") Started
|
||||
div
|
||||
span(data-i18n="clans.playtime") Playtime
|
||||
span : #{levelInfo.playtime}s
|
||||
div
|
||||
span(data-i18n="clans.last_played") Last played
|
||||
span : #{levelInfo.changed}
|
||||
if isOwner || me.isAdmin()
|
||||
strong(data-i18n="clans.view_solution") Click to view solution.
|
||||
else
|
||||
span.progress-level-cell.level-progression-level-not-started #{i}
|
||||
if showExpandedProgress || i === 1 || i === lastUserCampaignLevelMap[member.id][campaign.ID].index + 1
|
||||
span.spl #{level.name}
|
||||
.level-popup-container
|
||||
h3 #{i}. #{level.name}
|
||||
div
|
||||
span(data-i18n="choose_hero.status") Status
|
||||
span.spr :
|
||||
span(data-i18n="clans.not_started_2") Not Started
|
||||
if lastUserCampaignLevelMap[member.id][campaign.ID].levelSlug === level.slug
|
||||
- break
|
||||
span(data-i18n="clans.status") Status
|
||||
span.spr :
|
||||
span(data-i18n="clans.not_started_2") Not Started
|
||||
if lastUserCampaignLevelMap[member.id][campaign.ID].levelSlug === level.slug
|
||||
- break
|
||||
|
||||
//- Basic dashboard
|
||||
else
|
||||
|
|
|
@ -10,7 +10,7 @@ block content
|
|||
input(type='checkbox').private-clan-checkbox
|
||||
span.spl(data-i18n="clans.make_private") Make clan private
|
||||
span.spl (
|
||||
a.private-more-info(data-i18n="clans.subs_only") subscribers only
|
||||
a.private-more-info(data-i18n="clans.private_preview")
|
||||
span )
|
||||
p
|
||||
button.btn.btn-success.create-clan-btn(data-i18n="clans.create_clan") Create New Clan
|
||||
|
|
|
@ -11,9 +11,11 @@ block content
|
|||
input.student-view-checkbox(type='checkbox')
|
||||
span.spl Student view
|
||||
div TODO: fix ugly tabs
|
||||
div TODO: add student progress monitoring
|
||||
div TODO: level concepts, status, working play button
|
||||
div TODO: student view
|
||||
div TODO: aggregate student progress
|
||||
div TODO: student level progress popups
|
||||
div TODO: student concept progress
|
||||
div(style='border-bottom: 1px solid black;')
|
||||
|
||||
h1= course.title
|
||||
|
@ -64,24 +66,48 @@ block content
|
|||
table.table.table-condensed
|
||||
thead
|
||||
tr
|
||||
th Name
|
||||
th Progress
|
||||
th
|
||||
th
|
||||
span.progress-header Progress
|
||||
span.progress-key.progress-key-complete complete
|
||||
span.progress-key.progress-key-started started
|
||||
span.progress-key not started
|
||||
if maxLastStartedIndex > 30
|
||||
input.expand-progress-checkbox(type='checkbox')
|
||||
span.spl.expand-progress-label(data-i18n="clans.exp_levels") Expand levels
|
||||
tbody
|
||||
each student in instance.students
|
||||
tr
|
||||
td
|
||||
a= student
|
||||
td TODO: level progress
|
||||
td
|
||||
a= student
|
||||
td.progress-cell
|
||||
- var i = 0
|
||||
each level in course.levels
|
||||
if i <= userLevelStateMap[student].lastCompletedIndex
|
||||
span.progress-level-cell.progress-level-cell-complete #{i + 1}
|
||||
if showExpandedProgress || i === 0 || i === course.levels.length - 1
|
||||
span.spl #{level}
|
||||
else if i <= userLevelStateMap[student].lastStartedIndex
|
||||
span.progress-level-cell.progress-level-cell-started #{i + 1}
|
||||
if showExpandedProgress || i === 1 || i === userLevelStateMap[student].lastStartedIndex
|
||||
span.spl #{level}
|
||||
else
|
||||
span.progress-level-cell.level-progression-level-not-started #{i + 1}
|
||||
if showExpandedProgress || i === 1 || i === userLevelStateMap[student].lastStartedIndex
|
||||
span.spl #{level}
|
||||
if i === maxLastStartedIndex
|
||||
- break
|
||||
- i++
|
||||
|
||||
.tab-pane#invite(role='tabpanel')
|
||||
p Invite students to join this class.
|
||||
if course.title !== 'Introduction to Computer Science'
|
||||
p Student unlock code: #{instance.code}
|
||||
p Class capacity: 34/50
|
||||
|
||||
textarea.textarea-emails(rows=3, placeholder="Enter student emails to invite, one per line")
|
||||
div
|
||||
button.btn.btn-success.btn-invite Send Invites
|
||||
|
||||
.tab-pane#levels(role='tabpanel')
|
||||
table.table.table-condensed
|
||||
thead
|
||||
|
|
|
@ -48,11 +48,25 @@ block content
|
|||
span.spl(data-i18n="teachers.monitor_progress_4")
|
||||
p(data-i18n="teachers.monitor_progress_5")
|
||||
h4(data-i18n="teachers.sub_includes_7")
|
||||
p(data-i18n="teachers.private_clans_1")
|
||||
ul
|
||||
li
|
||||
strong Track concepts
|
||||
span.spl learned by each student
|
||||
li Track levels completed for each student
|
||||
li
|
||||
span See your students'
|
||||
strong.spl solutions
|
||||
li Sort students by name or progress
|
||||
li
|
||||
strong Requires invitation
|
||||
span.spl to join
|
||||
p
|
||||
img(src='/images/pages/clans/dashboard_preview.png' height='400')
|
||||
p
|
||||
span.spr(data-i18n="teachers.private_clans_2")
|
||||
a(href='/clans', data-i18n="clans.clan")
|
||||
span(data-i18n="teachers.private_clans_3")
|
||||
p Private clans require a subscription to create or join.
|
||||
|
||||
h3(data-i18n="teachers.material_title")
|
||||
if me.get('chinaVersion')
|
||||
|
@ -78,19 +92,19 @@ block content
|
|||
tbody
|
||||
tr
|
||||
td Syntax
|
||||
td If/Else
|
||||
td If Statements
|
||||
td Arithmetic
|
||||
td Object Literals
|
||||
tr
|
||||
td Methods
|
||||
td Relational Operators
|
||||
td While-loops
|
||||
td While Loops
|
||||
td Remote Method Invocation
|
||||
tr
|
||||
td Parameters
|
||||
td Object Properties
|
||||
td Break
|
||||
td For-Loops
|
||||
td Break Statements
|
||||
td For Loops
|
||||
tr
|
||||
td Strings
|
||||
td Input Handling
|
||||
|
|
|
@ -27,6 +27,8 @@ module.exports = class ClanDetailsView extends RootView
|
|||
'click .edit-name-save-btn': 'onEditNameSave'
|
||||
'click .join-clan-btn': 'onJoinClan'
|
||||
'click .leave-clan-btn': 'onLeaveClan'
|
||||
'click .member-header': 'onClickMemberHeader'
|
||||
'click .progress-header': 'onClickProgressHeader'
|
||||
'click .progress-level-cell': 'onClickLevel'
|
||||
'click .remove-member-btn': 'onRemoveMember'
|
||||
'mouseenter .progress-level-cell': 'onMouseEnterPoint'
|
||||
|
@ -41,6 +43,7 @@ module.exports = class ClanDetailsView extends RootView
|
|||
|
||||
initData: ->
|
||||
@showExpandedProgress = false
|
||||
@memberSort = 'nameAsc'
|
||||
@stats = {}
|
||||
|
||||
@campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign, comparator:'_id' })
|
||||
|
@ -67,6 +70,7 @@ module.exports = class ClanDetailsView extends RootView
|
|||
context = super()
|
||||
context.campaignLevelProgressions = @campaignLevelProgressions ? []
|
||||
context.clan = @clan
|
||||
context.conceptsProgression = @conceptsProgression ? []
|
||||
if application.isProduction()
|
||||
context.joinClanLink = "https://codecombat.com/clans/#{@clanID}"
|
||||
else
|
||||
|
@ -76,21 +80,25 @@ module.exports = class ClanDetailsView extends RootView
|
|||
context.memberLanguageMap = @memberLanguageMap
|
||||
context.memberLevelStateMap = @memberLevelMap ? {}
|
||||
context.memberMaxLevelCount = @memberMaxLevelCount
|
||||
context.members = @members?.models
|
||||
context.memberSort = @memberSort
|
||||
context.isOwner = @clan.get('ownerID') is me.id
|
||||
context.isMember = @clanID in (me.get('clans') ? [])
|
||||
context.stats = @stats
|
||||
|
||||
# Find last campaign level for each user
|
||||
# TODO: why do we do this for every render?
|
||||
highestUserLevelCountMap = {}
|
||||
lastUserCampaignLevelMap = {}
|
||||
maxLastUserCampaignLevel = 0
|
||||
userConceptsMap = {}
|
||||
if @campaigns.loaded
|
||||
levelCount = 0
|
||||
for campaign in @campaigns.models
|
||||
campaignID = campaign.id
|
||||
lastLevelIndex = 0
|
||||
for levelID, level of campaign.get('levels')
|
||||
levelSlug = level.slug
|
||||
for member in context.members
|
||||
for member in @members?.models ? []
|
||||
if context.memberLevelStateMap[member.id]?[levelSlug]
|
||||
lastUserCampaignLevelMap[member.id] ?= {}
|
||||
lastUserCampaignLevelMap[member.id][campaignID] ?= {}
|
||||
|
@ -98,10 +106,20 @@ module.exports = class ClanDetailsView extends RootView
|
|||
levelSlug: levelSlug
|
||||
index: lastLevelIndex
|
||||
maxLastUserCampaignLevel = lastLevelIndex if lastLevelIndex > maxLastUserCampaignLevel
|
||||
if level.concepts?
|
||||
userConceptsMap[member.id] ?= {}
|
||||
for concept in level.concepts
|
||||
continue if userConceptsMap[member.id][concept] is 'complete'
|
||||
userConceptsMap[member.id][concept] = context.memberLevelStateMap[member.id][levelSlug].state
|
||||
highestUserLevelCountMap[member.id] = levelCount
|
||||
lastLevelIndex++
|
||||
levelCount++
|
||||
|
||||
@sortMembers(highestUserLevelCountMap, userConceptsMap) if @clan.get('dashboardType') is 'premium'
|
||||
context.members = @members?.models ? []
|
||||
context.lastUserCampaignLevelMap = lastUserCampaignLevelMap
|
||||
context.showExpandedProgress = maxLastUserCampaignLevel <= 30 or @showExpandedProgress
|
||||
context.userConceptsMap = userConceptsMap
|
||||
context
|
||||
|
||||
afterRender: ->
|
||||
|
@ -114,6 +132,42 @@ module.exports = class ClanDetailsView extends RootView
|
|||
@memberAchievements.fetch cache: false
|
||||
@memberSessions.fetch cache: false
|
||||
|
||||
sortMembers: (highestUserLevelCountMap, userConceptsMap) ->
|
||||
# Progress sort precedence: most completed concepts, most started concepts, most levels, name sort
|
||||
return unless @members? and @memberSort?
|
||||
switch @memberSort
|
||||
when "nameDesc"
|
||||
@members.comparator = (a, b) -> return (b.get('name') or 'Anoner').localeCompare(a.get('name') or 'Anoner')
|
||||
when "progressAsc"
|
||||
@members.comparator = (a, b) ->
|
||||
aComplete = (concept for concept, state of userConceptsMap[a.id] when state is 'complete')
|
||||
bComplete = (concept for concept, state of userConceptsMap[b.id] when state is 'complete')
|
||||
aStarted = (concept for concept, state of userConceptsMap[a.id] when state is 'started')
|
||||
bStarted = (concept for concept, state of userConceptsMap[b.id] when state is 'started')
|
||||
if aComplete < bComplete then return -1
|
||||
else if aComplete > bComplete then return 1
|
||||
else if aStarted < bStarted then return -1
|
||||
else if aStarted > bStarted then return 1
|
||||
if highestUserLevelCountMap[a.id] < highestUserLevelCountMap[b.id] then return -1
|
||||
else if highestUserLevelCountMap[a.id] > highestUserLevelCountMap[b.id] then return 1
|
||||
(a.get('name') or 'Anoner').localeCompare(b.get('name') or 'Anoner')
|
||||
when "progressDesc"
|
||||
@members.comparator = (a, b) ->
|
||||
aComplete = (concept for concept, state of userConceptsMap[a.id] when state is 'complete')
|
||||
bComplete = (concept for concept, state of userConceptsMap[b.id] when state is 'complete')
|
||||
aStarted = (concept for concept, state of userConceptsMap[a.id] when state is 'started')
|
||||
bStarted = (concept for concept, state of userConceptsMap[b.id] when state is 'started')
|
||||
if aComplete > bComplete then return -1
|
||||
else if aComplete < bComplete then return 1
|
||||
else if aStarted > bStarted then return -1
|
||||
else if aStarted < bStarted then return 1
|
||||
if highestUserLevelCountMap[a.id] > highestUserLevelCountMap[b.id] then return -1
|
||||
else if highestUserLevelCountMap[a.id] < highestUserLevelCountMap[b.id] then return 1
|
||||
(b.get('name') or 'Anoner').localeCompare(a.get('name') or 'Anoner')
|
||||
else
|
||||
@members.comparator = (a, b) -> return (a.get('name') or 'Anoner').localeCompare(b.get('name') or 'Anoner')
|
||||
@members.sort()
|
||||
|
||||
updateHeroIcons: ->
|
||||
return unless @members?.models?
|
||||
for member in @members.models
|
||||
|
@ -124,6 +178,7 @@ module.exports = class ClanDetailsView extends RootView
|
|||
onCampaignSync: ->
|
||||
return unless @campaigns.loaded
|
||||
@campaignLevelProgressions = []
|
||||
@conceptsProgression = []
|
||||
for campaign in @campaigns.models
|
||||
continue if campaign.get('slug') is 'auditions'
|
||||
campaignLevelProgression =
|
||||
|
@ -136,6 +191,9 @@ module.exports = class ClanDetailsView extends RootView
|
|||
ID: levelID
|
||||
slug: level.slug
|
||||
name: level.name
|
||||
if level.concepts?
|
||||
for concept in level.concepts
|
||||
@conceptsProgression.push concept unless concept in @conceptsProgression
|
||||
@campaignLevelProgressions.push campaignLevelProgression
|
||||
@render?()
|
||||
|
||||
|
@ -272,6 +330,14 @@ module.exports = class ClanDetailsView extends RootView
|
|||
success: (model, response, options) => @refreshData()
|
||||
@supermodel.addRequestResource( 'leave_clan', options).load()
|
||||
|
||||
onClickMemberHeader: (e) ->
|
||||
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
||||
@render?()
|
||||
|
||||
onClickProgressHeader: (e) ->
|
||||
@memberSort = if @memberSort is 'progressAsc' then 'progressDesc' else 'progressAsc'
|
||||
@render?()
|
||||
|
||||
onRemoveMember: (e) ->
|
||||
return unless window.confirm("Remove Hero?")
|
||||
if memberID = $(e.target).data('id')
|
||||
|
|
|
@ -73,9 +73,15 @@ module.exports = class ClansView extends RootView
|
|||
|
||||
setupPrivateInfoPopover: ->
|
||||
popoverTitle = "<h3>Private Clans</h3>"
|
||||
popoverContent = "<p>Invite only</p>"
|
||||
popoverContent += "<p>Detailed dashboard:</p>"
|
||||
popoverContent += "<p><img src='/images/pages/clans/dashboard_preview.png' width='700'></p>"
|
||||
popoverContent = "<ul>"
|
||||
popoverContent += "<li><span style='font-weight:bold;'>Track concepts</span> learned by each member"
|
||||
popoverContent += "<li>Track levels completed for each member"
|
||||
popoverContent += "<li>See your members' <span style='font-weight:bold;'>solutions</span>"
|
||||
popoverContent += "<li>Sort members by name or progress"
|
||||
popoverContent += "<li><span style='font-weight:bold;'>Requires invitation</span> to join"
|
||||
popoverContent += "</ul>"
|
||||
popoverContent += "<p><img src='/images/pages/clans/dashboard_preview.png' height='400'></p>"
|
||||
popoverContent += "<p>Private clans require a subscription to create or join.</p>"
|
||||
@$el.find('.private-more-info').popover(
|
||||
animation: true
|
||||
html: true
|
||||
|
|
|
@ -78,6 +78,7 @@ module.exports = class SubscribeModal extends ModalView
|
|||
|
||||
setupPaymentMethodsInfoPopover: ->
|
||||
popoverTitle = $.i18n.t('subscribe.payment_methods_title')
|
||||
popoverTitle += '<button type="button" class="close" onclick="$('#payment-methods-info').popover('hide');">×</button>'
|
||||
popoverContent = "<p>" + $.i18n.t('subscribe.payment_methods_blurb1') + "</p>"
|
||||
popoverContent += "<p>" + $.i18n.t('subscribe.payment_methods_blurb2') + " <a href='mailto:support@codecombat.com'>support@codecombat.com</a>."
|
||||
@$el.find('#payment-methods-info').popover(
|
||||
|
|
|
@ -7,9 +7,10 @@ module.exports = class CourseDetailsView extends RootView
|
|||
template: template
|
||||
|
||||
events:
|
||||
'change .expand-progress-checkbox': 'onExpandedProgressCheckbox'
|
||||
'change .select-session': 'onChangeSession'
|
||||
'click .edit-class-name-btn': 'onClickEditClassName'
|
||||
'click .edit-description-btn': 'onClickEditClassDescription'
|
||||
'change .select-session': 'onChangeSession'
|
||||
|
||||
constructor: (options, @courseID) ->
|
||||
super options
|
||||
|
@ -20,21 +21,43 @@ module.exports = class CourseDetailsView extends RootView
|
|||
context.course = @course ? {}
|
||||
context.instance = @instances?[@currentInstanceIndex] ? {}
|
||||
context.instances = @instances ? []
|
||||
context.maxLastStartedIndex = @maxLastStartedIndex ? 0
|
||||
context.userLevelStateMap = @userLevelStateMap ? {}
|
||||
context.showExpandedProgress = @maxLastStartedIndex <= 30 or @showExpandedProgress
|
||||
context
|
||||
|
||||
initData: ->
|
||||
mockData = require 'views/courses/mock1/CoursesMockData'
|
||||
@course = mockData.courses[@courseID]
|
||||
# @instance = mockData.instances[_.random(0, mockData.instances.length - 1)]
|
||||
@currentInstanceIndex = 0
|
||||
@instances = mockData.instances
|
||||
@updateLevelMaps()
|
||||
|
||||
updateLevelMaps: ->
|
||||
@userLevelStateMap = {}
|
||||
@maxLastStartedIndex = -1
|
||||
for student in @instances?[@currentInstanceIndex].students
|
||||
lastCompletedIndex = _.random(0, @course.levels.length)
|
||||
lastStartedIndex = lastCompletedIndex + 1
|
||||
@userLevelStateMap[student] =
|
||||
lastCompletedIndex: lastCompletedIndex
|
||||
lastStartedIndex: lastStartedIndex
|
||||
@maxLastStartedIndex = lastStartedIndex if lastStartedIndex > @maxLastStartedIndex
|
||||
|
||||
onChangeSession: (e) ->
|
||||
@showExpandedProgress = false
|
||||
newSessionValue = $(e.target).val()
|
||||
for val, index in @instances when val.name is newSessionValue
|
||||
@currentInstanceIndex = index
|
||||
@updateLevelMaps()
|
||||
@render?()
|
||||
|
||||
onExpandedProgressCheckbox: (e) ->
|
||||
@showExpandedProgress = $('.expand-progress-checkbox').prop('checked')
|
||||
# TODO: why does render reset the checkbox to be unchecked?
|
||||
@render?()
|
||||
$('.expand-progress-checkbox').attr('checked', @showExpandedProgress)
|
||||
|
||||
onClickEditClassName: (e) ->
|
||||
alert 'TODO: Popup for editing name for this course session'
|
||||
|
||||
|
|
Loading…
Reference in a new issue