mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-01-31 08:39:58 -05:00
Update private clans dashboard
This commit is contained in:
parent
2f8831ea72
commit
45c070209b
4 changed files with 142 additions and 46 deletions
|
@ -25,9 +25,39 @@
|
|||
|
||||
$spriteSheetSize: 30px
|
||||
|
||||
td.hero-icon-cell
|
||||
|
||||
.remove-hero-cell
|
||||
width: 100px
|
||||
|
||||
.hero-icon-cell
|
||||
width: 30px
|
||||
|
||||
.level-cell
|
||||
width: 50px
|
||||
text-align: center
|
||||
|
||||
.name-cell
|
||||
width: 100px
|
||||
|
||||
.level-progression-cell
|
||||
background-color: lightblue
|
||||
border: 1px solid gray
|
||||
// cursor: pointer
|
||||
padding: 4px
|
||||
|
||||
.level-popup-container
|
||||
display: none
|
||||
position: absolute
|
||||
padding: 10px
|
||||
border: 1px solid black
|
||||
z-index: 3
|
||||
background-color: blanchedalmond
|
||||
font-size: 10pt
|
||||
|
||||
.level-progression-cell-name
|
||||
background-color: lightblue
|
||||
border: 1px solid gray
|
||||
|
||||
.player-hero-icon
|
||||
background: transparent url(/images/pages/play/play-spritesheet.png)
|
||||
background-size: cover
|
||||
|
|
|
@ -54,7 +54,7 @@ block content
|
|||
tr
|
||||
td Average Level
|
||||
td= stats.averageLevel
|
||||
if stats.totalAchievements
|
||||
if stats.totalAchievements && clan.get('type') === 'public'
|
||||
tr
|
||||
td Total Achievements
|
||||
td= stats.totalAchievements
|
||||
|
@ -67,40 +67,78 @@ block content
|
|||
else
|
||||
button.btn.btn-lg.btn-success.join-clan-btn Join Clan
|
||||
|
||||
div
|
||||
span.spl.spr.join-link-prompt Invite:
|
||||
input.join-clan-link(type="text", readonly, value="#{joinClanLink}")
|
||||
.small *Invite players to this Clan by sending them this link.
|
||||
if clan.get('ownerID') === me.id || clan.get('type') === 'public'
|
||||
div
|
||||
span.spl.spr.join-link-prompt Invite:
|
||||
input.join-clan-link(type="text", readonly, value="#{joinClanLink}")
|
||||
.small *Invite players to this Clan by sending them this link.
|
||||
|
||||
if members
|
||||
h3 Heroes (#{members.length})
|
||||
table.table.table-striped.table-condensed
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th
|
||||
td Name
|
||||
th Level
|
||||
th Achievements
|
||||
th Latest Achievement
|
||||
th
|
||||
tbody
|
||||
each member in members
|
||||
if clan.get('type') === 'private'
|
||||
table.table.table-condensed
|
||||
thead
|
||||
tr
|
||||
td.hero-icon-cell
|
||||
span.spr.player-hero-icon(data-memberid="#{member.id}")
|
||||
td.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])
|
||||
td
|
||||
a(href="/user/#{member.id}")= member.get('name') || 'Anoner'
|
||||
td= member.level()
|
||||
td
|
||||
if memberAchievementsMap && memberAchievementsMap[member.id]
|
||||
| #{memberAchievementsMap[member.id].length}
|
||||
td
|
||||
if memberAchievementsMap && memberAchievementsMap[member.id] && memberAchievementsMap[member.id].length
|
||||
span= memberAchievementsMap[member.id][0].get('achievementName')
|
||||
td
|
||||
if isOwner && member.id !== clan.get('ownerID')
|
||||
button.btn.btn-xs.btn-warning.remove-member-btn(data-id="#{member.id}") Remove Hero
|
||||
if isOwner
|
||||
th
|
||||
th
|
||||
th
|
||||
th Level
|
||||
th Name
|
||||
th(colspan="#{memberMaxLevelCount + 1}") Last Level Completed
|
||||
tbody
|
||||
each member in members
|
||||
tr
|
||||
if isOwner
|
||||
td.remove-hero-cell
|
||||
if member.id !== clan.get('ownerID')
|
||||
button.btn.btn-xs.btn-warning.remove-member-btn(data-id="#{member.id}") Remove Hero
|
||||
td.hero-icon-cell
|
||||
span.spr.player-hero-icon(data-memberid="#{member.id}")
|
||||
td.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])
|
||||
td.level-cell= member.level()
|
||||
td.name-cell
|
||||
a(href="/user/#{member.id}")= member.get('name') || 'Anoner'
|
||||
if memberLevelProgression && memberLevelProgression[member.id]
|
||||
each levelInfo in memberLevelProgression[member.id]
|
||||
td.level-progression-cell
|
||||
.level-popup-container
|
||||
div Level: #{levelInfo.level}
|
||||
div Playtime: #{levelInfo.playtime}
|
||||
div Last played: #{levelInfo.changed}
|
||||
td(colspan="#{memberMaxLevelCount - memberLevelProgression[member.id].length + 1}")= memberLevelProgression[member.id][memberLevelProgression[member.id].length - 1].level
|
||||
else
|
||||
td(colspan="#{memberMaxLevelCount + 1}")
|
||||
else
|
||||
table.table.table-striped.table-condensed
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th
|
||||
td Name
|
||||
th Level
|
||||
th Achievements
|
||||
th Latest Achievement
|
||||
th
|
||||
tbody
|
||||
each member in members
|
||||
tr
|
||||
td.hero-icon-cell
|
||||
span.spr.player-hero-icon(data-memberid="#{member.id}")
|
||||
td.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])
|
||||
td
|
||||
a(href="/user/#{member.id}")= member.get('name') || 'Anoner'
|
||||
td= member.level()
|
||||
td
|
||||
if memberAchievementsMap && memberAchievementsMap[member.id]
|
||||
| #{memberAchievementsMap[member.id].length}
|
||||
td
|
||||
if memberAchievementsMap && memberAchievementsMap[member.id] && memberAchievementsMap[member.id].length
|
||||
span= memberAchievementsMap[member.id][0].get('achievementName')
|
||||
td
|
||||
if isOwner && member.id !== clan.get('ownerID')
|
||||
button.btn.btn-xs.btn-warning.remove-member-btn(data-id="#{member.id}") Remove Hero
|
||||
|
|
|
@ -24,6 +24,8 @@ module.exports = class ClanDetailsView extends RootView
|
|||
'click .join-clan-btn': 'onJoinClan'
|
||||
'click .leave-clan-btn': 'onLeaveClan'
|
||||
'click .remove-member-btn': 'onRemoveMember'
|
||||
'mouseenter .level-progression-cell': 'onMouseEnterPoint'
|
||||
'mouseleave .level-progression-cell': 'onMouseLeavePoint'
|
||||
|
||||
constructor: (options, @clanID) ->
|
||||
super options
|
||||
|
@ -61,6 +63,8 @@ module.exports = class ClanDetailsView extends RootView
|
|||
context.owner = @owner
|
||||
context.memberAchievementsMap = @memberAchievementsMap
|
||||
context.memberLanguageMap = @memberLanguageMap
|
||||
context.memberLevelProgression = @memberLevelProgression
|
||||
context.memberMaxLevelCount = @memberMaxLevelCount
|
||||
context.members = @members?.models
|
||||
context.isOwner = @clan.get('ownerID') is me.id
|
||||
context.isMember = @clanID in (me.get('clans') ? [])
|
||||
|
@ -75,6 +79,7 @@ module.exports = class ClanDetailsView extends RootView
|
|||
me.fetch cache: false
|
||||
@members.fetch cache: false
|
||||
@memberAchievements.fetch cache: false
|
||||
@memberSessions.fetch cache: false
|
||||
|
||||
updateHeroIcons: ->
|
||||
return unless @members?.models?
|
||||
|
@ -106,17 +111,27 @@ module.exports = class ClanDetailsView extends RootView
|
|||
@render?()
|
||||
|
||||
onMemberSessionsSync: ->
|
||||
@memberSessionMap = {}
|
||||
@memberLevelProgression = {}
|
||||
memberSessions = {}
|
||||
for levelSession in @memberSessions.models
|
||||
user = levelSession.get('creator')
|
||||
@memberSessionMap[user] ?= []
|
||||
@memberSessionMap[user].push levelSession
|
||||
if not levelSession.isMultiplayer() and levelSession.get('state')?.complete is true
|
||||
memberSessions[user] ?= []
|
||||
memberSessions[user].push levelSession
|
||||
@memberLevelProgression[user] ?= []
|
||||
levelInfo =
|
||||
level: levelSession.get('levelName')
|
||||
changed: new Date(levelSession.get('changed')).toLocaleString()
|
||||
playtime: levelSession.get('playtime')
|
||||
@memberLevelProgression[user].push levelInfo
|
||||
@memberMaxLevelCount = 0
|
||||
@memberLanguageMap = {}
|
||||
for user of @memberSessionMap
|
||||
for user of memberSessions
|
||||
languageCounts = {}
|
||||
for levelSession in @memberSessionMap[user]
|
||||
for levelSession in memberSessions[user]
|
||||
language = levelSession.get('codeLanguage') or levelSession.get('submittedCodeLanguage')
|
||||
languageCounts[language] = (languageCounts[language] or 0) + 1 if language
|
||||
@memberMaxLevelCount = memberSessions[user].length if @memberMaxLevelCount < memberSessions[user].length
|
||||
mostUsedCount = 0
|
||||
for language, count of languageCounts
|
||||
if count > mostUsedCount
|
||||
|
@ -124,6 +139,18 @@ module.exports = class ClanDetailsView extends RootView
|
|||
@memberLanguageMap[user] = language
|
||||
@render?()
|
||||
|
||||
onMouseEnterPoint: (e) ->
|
||||
container = $(e.target).find('.level-popup-container').show()
|
||||
margin = 20
|
||||
offset = $(e.target).offset()
|
||||
scrollTop = $(e.target).offsetParent().scrollTop()
|
||||
height = container.outerHeight()
|
||||
container.css('left', offset.left + e.offsetX)
|
||||
container.css('top', offset.top + scrollTop - height - margin)
|
||||
|
||||
onMouseLeavePoint: (e) ->
|
||||
$(e.target).find('.level-popup-container').hide()
|
||||
|
||||
onDeleteClan: (e) ->
|
||||
return @openModalView(new AuthModal()) if me.isAnonymous()
|
||||
options =
|
||||
|
|
|
@ -68,7 +68,7 @@ ClanHandler = class ClanHandler extends Handler
|
|||
return @sendNotFoundError(res, err)
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendDatabaseError(res, err) unless clan
|
||||
return @sendNotFoundError(res) unless clan
|
||||
return @sendDatabaseError(res, err) unless clanType = clan.get('type')
|
||||
return @sendForbiddenError(res) unless clanType is 'public' or req.user.isPremium()
|
||||
Clan.update {_id: clanID}, {$addToSet: {members: req.user._id}}, (err) =>
|
||||
|
@ -86,7 +86,7 @@ ClanHandler = class ClanHandler extends Handler
|
|||
return @sendNotFoundError(res, err)
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendDatabaseError(res, err) unless clan
|
||||
return @sendNotFoundError(res) unless clan
|
||||
return @sendForbiddenError(res) if clan.get('ownerID')?.equals req.user._id
|
||||
Clan.update {_id: clanID}, {$pull: {members: req.user._id}}, (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
|
@ -99,7 +99,7 @@ ClanHandler = class ClanHandler extends Handler
|
|||
# TODO: add tests
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendDatabaseError(res, err) unless clan
|
||||
return @sendNotFoundError(res) unless clan
|
||||
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
|
||||
EarnedAchievement.find {user: {$in: memberIDs}}, (err, documents) =>
|
||||
return @sendDatabaseError(res, err) if err?
|
||||
|
@ -110,7 +110,7 @@ ClanHandler = class ClanHandler extends Handler
|
|||
# TODO: add tests
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendDatabaseError(res, err) unless clan
|
||||
return @sendNotFoundError(res) unless clan
|
||||
memberIDs = clan.get('members') ? []
|
||||
User.find {_id: {$in: memberIDs}}, (err, users) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
|
@ -119,9 +119,10 @@ ClanHandler = class ClanHandler extends Handler
|
|||
|
||||
getMemberSessions: (req, res, clanID) ->
|
||||
# TODO: add tests
|
||||
# TODO: restrict information returned based on clan type
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendDatabaseError(res, err) unless clan
|
||||
return @sendNotFoundError(res) unless clan
|
||||
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
|
||||
LevelSession.find {creator: {$in: memberIDs}}, (err, documents) =>
|
||||
return @sendDatabaseError(res, err) if err?
|
||||
|
@ -147,7 +148,7 @@ ClanHandler = class ClanHandler extends Handler
|
|||
return @sendNotFoundError(res, err)
|
||||
Clan.findById clanID, (err, clan) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendDatabaseError(res, err) unless clan
|
||||
return @sendNotFoundError(res) unless clan
|
||||
return @sendForbiddenError res unless @hasAccessToDocument(req, clan)
|
||||
return @sendForbiddenError(res) if clan.get('ownerID').equals memberID
|
||||
Clan.update {_id: clanID}, {$pull: {members: memberID}}, (err) =>
|
||||
|
|
Loading…
Reference in a new issue