mirror of
https://github.com/sudoxnym/habitica-self-host.git
synced 2026-05-21 13:18:43 +00:00
challenges: pull in updates from the old 0.5 branch
This commit is contained in:
parent
e0c95b3a86
commit
e81193ef28
4 changed files with 355 additions and 234 deletions
|
|
@ -1,83 +1,239 @@
|
|||
_ = require 'lodash'
|
||||
helpers = require 'habitrpg-shared/script/helpers'
|
||||
{helpers} = require 'habitrpg-shared'
|
||||
async = require 'async'
|
||||
|
||||
module.exports.app = (appExports, model) ->
|
||||
browser = require './browser'
|
||||
user = model.at '_user'
|
||||
module.exports.app = (app) ->
|
||||
|
||||
$('#profile-challenges-tab-link').on 'show', (e) ->
|
||||
_.each model.get('groups'), (g) ->
|
||||
_.each g.challenges, (chal) ->
|
||||
_.each ['habit','daily','todo'], (type) ->
|
||||
_.each chal["#{type}s"], (task) ->
|
||||
_.each chal.users, (member) ->
|
||||
if (history = member?["#{type}s"]?[task.id]?.history) and !!history
|
||||
data = google.visualization.arrayToDataTable _.map(history, (h)-> [h.date,h.value])
|
||||
options =
|
||||
backgroundColor: { fill:'transparent' }
|
||||
width: 150
|
||||
height: 50
|
||||
chartArea: width: '80%', height: '80%'
|
||||
axisTitlePosition: 'none'
|
||||
legend: position: 'bottom'
|
||||
hAxis: gridlines: color: 'transparent' # since you can't seem to *remove* gridlines...
|
||||
vAxis: gridlines: color: 'transparent'
|
||||
chart = new google.visualization.LineChart $(".challenge-#{chal.id}-member-#{member.id}-history-#{task.id}")[0]
|
||||
chart.draw(data, options)
|
||||
|
||||
|
||||
appExports.challengeCreate = (e,el) ->
|
||||
[type, gid] = [$(el).attr('data-type'), $(el).attr('data-gid')]
|
||||
model.set '_challenge.new',
|
||||
name: ''
|
||||
habits: []
|
||||
dailys: []
|
||||
todos: []
|
||||
rewards: []
|
||||
id: model.id()
|
||||
uid: user.get('id')
|
||||
user: helpers.username(model.get('_user.auth'), model.get('_user.profile.name'))
|
||||
group: {type, id:gid}
|
||||
timestamp: +new Date
|
||||
|
||||
appExports.challengeSave = ->
|
||||
gid = model.get('_challenge.new.group.id')
|
||||
model.unshift "groups.#{gid}.challenges", model.get('_challenge.new'), ->
|
||||
browser.growlNotification('Challenge Created','success')
|
||||
challengeDiscard()
|
||||
|
||||
appExports.toggleChallengeEdit = (e, el) ->
|
||||
path = "_editing.challenges.#{$(el).attr('data-id')}"
|
||||
model.set path, !model.get(path)
|
||||
|
||||
appExports.challengeDiscard = challengeDiscard = -> model.del '_challenge.new'
|
||||
|
||||
appExports.challengeSubscribe = (e) ->
|
||||
chal = e.get()
|
||||
|
||||
# Add challenge name as a tag for user
|
||||
tags = user.get('tags')
|
||||
unless tags and _.find(tags,{id: chal.id})
|
||||
model.push '_user.tags', {id: chal.id, name: chal.name, challenge: true}
|
||||
|
||||
tags = {}; tags[chal.id] = true
|
||||
# Add all challenge's tasks to user's tasks
|
||||
userChallenges = user.get('challenges')
|
||||
user.unshift('challenges', chal.id) unless userChallenges and (userChallenges.indexOf(chal.id) != -1)
|
||||
_.each ['habit', 'daily', 'todo', 'reward'], (type) ->
|
||||
_.each chal["#{type}s"], (task) ->
|
||||
task.tags = tags
|
||||
task.challenge = chal.id
|
||||
task.group = {id: chal.group.id, type: chal.group.type}
|
||||
model.push("_#{type}List", task)
|
||||
###
|
||||
Sync any updates to challenges since last refresh. Do it after cron, so we don't punish them for new tasks
|
||||
This is challenge->user sync. user->challenge happens when user interacts with their tasks
|
||||
###
|
||||
app.on 'ready', (model) ->
|
||||
window.setTimeout ->
|
||||
_.each model.get('groups'), (g) ->
|
||||
if (@uid in g.members) and g.challenges
|
||||
_.each(g.challenges, ->app.challenges.syncChalToUser g)
|
||||
true
|
||||
, 500
|
||||
|
||||
appExports.challengeUnsubscribe = (e) ->
|
||||
chal = e.get()
|
||||
i = user.get('challenges')?.indexOf chal.id
|
||||
user.remove("challenges.#{i}") if i? and i != -1
|
||||
_.each ['habit', 'daily', 'todo', 'reward'], (type) ->
|
||||
_.each chal["#{type}s"], (task) ->
|
||||
model.remove "_#{type}List", _.findIndex(model.get("_#{type}List",{id:task.id}))
|
||||
model.del "_user.tasks.#{task.id}"
|
||||
true
|
||||
###
|
||||
Sync user to challenge (when they score, add to statistics)
|
||||
###
|
||||
app.model.on "change", "_page.user.priv.tasks.*.value", (id, value, previous, passed) ->
|
||||
### Sync to challenge, but do it later ###
|
||||
async.nextTick =>
|
||||
model = app.model
|
||||
ctx = {model: model}
|
||||
task = model.at "_page.user.priv.tasks.#{id}"
|
||||
tobj = task.get()
|
||||
pub = model.get "_page.user.pub"
|
||||
|
||||
if (chalTask = helpers.taskInChallenge.call ctx, tobj)? and chalTask.get()
|
||||
chalTask.increment "value", value - previous
|
||||
chal = model.at "groups.#{tobj.group.id}.challenges.#{tobj.challenge}"
|
||||
chalUser = -> helpers.indexedAt.call(ctx, chal.path(), 'members', {id:pub.id})
|
||||
cu = chalUser()
|
||||
unless cu?.get()
|
||||
chal.push "members", {id: pub.id, name: model.get(pub.profile.name)}
|
||||
cu = model.at chalUser()
|
||||
else
|
||||
cu.set 'name', pub.profile.name # update their name incase it changed
|
||||
cu.set "#{tobj.type}s.#{tobj.id}",
|
||||
value: tobj.value
|
||||
history: tobj.history
|
||||
|
||||
###
|
||||
Render graphs for user scores when the "Challenges" tab is clicked
|
||||
###
|
||||
|
||||
###
|
||||
TODO
|
||||
1) on main tab click or party
|
||||
* sort & render graphs for party
|
||||
2) guild -> all guilds
|
||||
3) public -> all public
|
||||
###
|
||||
|
||||
|
||||
###
|
||||
$('#profile-challenges-tab-link').on 'shown', ->
|
||||
async.each _.toArray(model.get('groups')), (g) ->
|
||||
async.each _.toArray(g.challenges), (chal) ->
|
||||
async.each _.toArray(chal.tasks), (task) ->
|
||||
async.each _.toArray(chal.members), (member) ->
|
||||
if (history = member?["#{task.type}s"]?[task.id]?.history) and !!history
|
||||
data = google.visualization.arrayToDataTable _.map(history, (h)-> [h.date,h.value])
|
||||
options =
|
||||
backgroundColor: { fill:'transparent' }
|
||||
width: 150
|
||||
height: 50
|
||||
chartArea: width: '80%', height: '80%'
|
||||
axisTitlePosition: 'none'
|
||||
legend: position: 'bottom'
|
||||
hAxis: gridlines: color: 'transparent' # since you can't seem to *remove* gridlines...
|
||||
vAxis: gridlines: color: 'transparent'
|
||||
chart = new google.visualization.LineChart $(".challenge-#{chal.id}-member-#{member.id}-history-#{task.id}")[0]
|
||||
chart.draw(data, options)
|
||||
###
|
||||
|
||||
app.fn
|
||||
challenges:
|
||||
|
||||
###
|
||||
Create
|
||||
###
|
||||
create: (e,el) ->
|
||||
[type, gid] = [$(el).attr('data-type'), $(el).attr('data-gid')]
|
||||
cid = @model.id()
|
||||
@model.set '_page.new.challenge',
|
||||
id: cid
|
||||
name: ''
|
||||
habits: []
|
||||
dailys: []
|
||||
todos: []
|
||||
rewards: []
|
||||
user:
|
||||
uid: @uid
|
||||
name: @pub.get('profile.name')
|
||||
group: {type, id:gid}
|
||||
timestamp: +new Date
|
||||
|
||||
###
|
||||
Save
|
||||
###
|
||||
save: ->
|
||||
newChal = @model.get('_page.new.challenge')
|
||||
[gid, cid] = [newChal.group.id, newChal.id]
|
||||
@model.push "_page.lists.challenges.#{gid}", newChal, ->
|
||||
app.browser.growlNotification('Challenge Created','success')
|
||||
app.challenges.discard()
|
||||
app.browser.resetDom() # something is going absolutely haywire here, all model data at end of reflist after chal created
|
||||
|
||||
###
|
||||
Toggle Edit
|
||||
###
|
||||
toggleEdit: (e, el) ->
|
||||
path = "_page.editing.challenges.#{$(el).attr('data-id')}"
|
||||
@model.set path, !@model.get(path)
|
||||
|
||||
###
|
||||
Discard
|
||||
###
|
||||
discard: ->
|
||||
@model.del '_page.new.challenge'
|
||||
|
||||
###
|
||||
Delete
|
||||
###
|
||||
delete: (e) ->
|
||||
return unless confirm("Delete challenge, are you sure?") is true
|
||||
e.at().remove()
|
||||
|
||||
###
|
||||
Add challenge name as a tag for user
|
||||
###
|
||||
syncChalToUser: (chal) ->
|
||||
return unless chal
|
||||
### Sync tags ###
|
||||
tags = @priv.get('tags') or []
|
||||
idx = _.findIndex tags, {id: chal.id}
|
||||
if ~idx and (tags[idx].name isnt chal.name)
|
||||
### update the name - it's been changed since ###
|
||||
@priv.set "tags.#{idx}.name", chal.name
|
||||
else
|
||||
@priv.push 'tags', {id: chal.id, name: chal.name, challenge: true}
|
||||
|
||||
tags = {}; tags[chal.id] = true
|
||||
_.each chal.habits.concat(chal.dailys.concat(chal.todos.concat(chal.rewards))), (task) =>
|
||||
_.defaults task, { tags, challenge: chal.id, group: {id: chal.group.id, type: chal.group.type} }
|
||||
path = "tasks.#{task.id}"
|
||||
if @priv.get path
|
||||
@priv.set path, _.defaults(@priv.get(path), task)
|
||||
else
|
||||
@model.push "_page.lists.tasks.#{@uid}.#{task.type}s", task
|
||||
true
|
||||
|
||||
###
|
||||
Subscribe
|
||||
###
|
||||
subscribe: (e) ->
|
||||
chal = e.get()
|
||||
### Add all challenge's tasks to user's tasks ###
|
||||
currChallenges = @pub.get('challenges')
|
||||
@pub.unshift('challenges', chal.id) unless currChallenges and ~currChallenges.indexOf(chal.id)
|
||||
e.at().push "members",
|
||||
id: @uid
|
||||
name: @pub.get('profile.name')
|
||||
app.challenges.syncChalToUser(chal)
|
||||
|
||||
###
|
||||
--------------------------
|
||||
Unsubscribe functions
|
||||
--------------------------
|
||||
###
|
||||
|
||||
unsubscribe: (chal, keep=true) ->
|
||||
|
||||
### Remove challenge from user ###
|
||||
i = @pub.get('challenges')?.indexOf(chal.id)
|
||||
if i? and ~i
|
||||
@pub.remove("challenges", i, 1)
|
||||
|
||||
### Remove user from challenge ###
|
||||
if ~(i = _.findIndex chal.members, {id: @uid})
|
||||
@model.remove "groups.#{chal.group.id}.challenges.#{chal.id}.members", i, 1
|
||||
|
||||
### Remove tasks from user ###
|
||||
async.each chal.habits.concat(chal.dailys.concat(chal.todos.concat(chal.rewards))), (task) =>
|
||||
if keep is true
|
||||
@priv.del "tasks.#{task.id}.challenge"
|
||||
else
|
||||
path = "_page.lists.tasks.#{@uid}.#{task.type}s"
|
||||
if ~(i = _.findIndex(@model.get(path), {id:task.id}))
|
||||
@model.remove(path, i, 1)
|
||||
true
|
||||
|
||||
taskUnsubscribe: (e, el) ->
|
||||
|
||||
###
|
||||
since the challenge was deleted, we don't have its data to unsubscribe from - but we have the vestiges on the task
|
||||
FIXME this is a really dumb way of doing this
|
||||
###
|
||||
tasks = @priv.get('tasks')
|
||||
tobj = tasks[$(el).attr("data-tid")]
|
||||
deletedChal =
|
||||
id: tobj.challenge
|
||||
members: [@uid]
|
||||
habits: _.where tasks, {type: 'habit', challenge: tobj.challenge}
|
||||
dailys: _.where tasks, {type: 'daily', challenge: tobj.challenge}
|
||||
todos: _.where tasks, {type: 'todo', challenge: tobj.challenge}
|
||||
rewards: _.where tasks, {type: 'reward', challenge: tobj.challenge}
|
||||
|
||||
switch $(el).attr('data-action')
|
||||
when 'keep'
|
||||
@priv.del "tasks.#{tobj.id}.challenge"
|
||||
@priv.del "tasks.#{tobj.id}.group"
|
||||
when 'keep-all'
|
||||
app.challenges.unsubscribe.call @, deletedChal, true
|
||||
when 'remove'
|
||||
path = "_page.lists.tasks.#{@uid}.#{tobj.type}s"
|
||||
if ~(i = _.findIndex @model.get(path), {id: tobj.id})
|
||||
@model.remove path, i
|
||||
when 'remove-all'
|
||||
app.challenges.unsubscribe.call @, deletedChal, false
|
||||
|
||||
challengeUnsubscribe: (e, el) ->
|
||||
$(el).popover('destroy').popover({
|
||||
html: true
|
||||
placement: 'top'
|
||||
trigger: 'manual'
|
||||
title: 'Unsubscribe From Challenge And:'
|
||||
content: """
|
||||
<a class=challenge-unsubscribe-and-remove>Remove Tasks</a><br/>
|
||||
<a class=challenge-unsubscribe-and-keep>Keep Tasks</a><br/>
|
||||
<a class=challenge-unsubscribe-cancel>Cancel</a><br/>
|
||||
"""
|
||||
}).popover('show')
|
||||
$('.challenge-unsubscribe-and-remove').click => app.challenges.unsubscribe.call @, e.get(), false
|
||||
$('.challenge-unsubscribe-and-keep').click => app.challenges.unsubscribe.call @, e.get(), true
|
||||
$('[class^=challenge-unsubscribe]').click => $(el).popover('destroy')
|
||||
|
|
@ -1,72 +1,58 @@
|
|||
<main:>
|
||||
<div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-toggle='tab' data-target="#challengesViewParty">Party</a></li>
|
||||
<li><a data-toggle='tab' data-target="#challengesViewGuild">Guild</a></li>
|
||||
<li><a data-toggle='tab' data-target="#challengesViewPublic">Public</a></li>
|
||||
</ul>
|
||||
<app:widgets:tabs>
|
||||
<@headers>
|
||||
<app:widgets:tab-header group="challenges" tab="party" title="Party" default="true" />
|
||||
<app:widgets:tab-header group="challenges" tab="guild" title="Guild" />
|
||||
<app:widgets:tab-header group="challenges" tab="public" title="Public" />
|
||||
</@headers>
|
||||
|
||||
<div class="tab-content">
|
||||
<app:widgets:tab-content group="challenges" tab="party" default="true">
|
||||
{{#unless _page.party.id}}
|
||||
Join a party first.
|
||||
{{else}}
|
||||
<app:challenges:list type="party" gid="{{_page.party.id}}" text="Party" list="{_page.lists.challenges[_page.party.id]}" />
|
||||
{{/}}
|
||||
</app:widgets:tab-content>
|
||||
|
||||
<div class="tab-pane active" id="challengesViewParty">
|
||||
{{#unless _party.id}}
|
||||
Join a party first.
|
||||
{{else}}
|
||||
{#if _challenge.new}
|
||||
<app:challenges:create-form />
|
||||
{else}
|
||||
<!-- FIXME https://github.com/codeparty/derby/issues/267, see _guilds.challenges below -->
|
||||
<app:challenges:create-button type='party' gid={{_party.id}} text='Party'/>
|
||||
{#each _party.challenges as :challenge}
|
||||
<app:challenges:listing challenge={:challenge} />
|
||||
{/}
|
||||
{/}
|
||||
<app:widgets:tab-content group="challenges" tab="guild">
|
||||
<ul class="nav nav-pills">
|
||||
{{#each _page.guilds as :guild}}
|
||||
<li class="{{#if equal($index,0)}}active{{/}}"><a data-toggle='tab' data-target="#challenges-guild-{:guild.id}">{{:guild.name}}</a></li>
|
||||
{{/}}
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
{{#each _page.guilds as :guild}}
|
||||
<div class="tab-pane {{#if equal($index,0)}}active{{/}}" id="challenges-guild-{{:guild.id}}">
|
||||
<app:challenges:list type="guild" gid="{{:guild.id}}" text="Guild" list="{_page.lists.challenges[:guild.id]}" />
|
||||
</div>
|
||||
{{/}}
|
||||
</div>
|
||||
</app:widgets:tab-content>
|
||||
|
||||
<div class="tab-pane" id="challengesViewGuild">
|
||||
<ul class="nav nav-pills">
|
||||
{{#each _guilds as :guild}}
|
||||
<li class="{{#if equal($index,0)}}active{{/}}"><a data-toggle='tab' data-target="#challenges-guild-{:guild.id}">{{:guild.name}}</a></li>
|
||||
{{/}}
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
{{#each _guilds as :guild}}
|
||||
<div class="tab-pane {{#if equal($index,0)}}active{{/}}" id="challenges-guild-{:guild.id}">
|
||||
{#if _challenge.new}
|
||||
<app:challenges:create-form />
|
||||
{else}
|
||||
<app:challenges:create-button type='guild' gid={{:guild.id}} text='Guild' />
|
||||
{#each :guild.challenges as :challenge}
|
||||
<app:challenges:listing challenge={groups[:guild.id].challenges[$index]} />
|
||||
{/}
|
||||
<hr/>
|
||||
{/}
|
||||
</div>
|
||||
{{/}}
|
||||
</div>
|
||||
</div>
|
||||
<app:widgets:tab-content group="challenges" tab="public">
|
||||
<app:challenges:list type="public" gid="habitrpg" text="Public" list="{_page.lists.challenges.habitrpg}" />
|
||||
</app:widgets:tab-content>
|
||||
|
||||
<div class="tab-pane" id="challengesViewPublic">
|
||||
{#if _challenge.new}
|
||||
<app:challenges:create-form />
|
||||
{else}
|
||||
<app:challenges:create-button type='public' gid='habitrpg' text='Public' />
|
||||
{#each _habitRPG.challenges as :challenge}
|
||||
<app:challenges:listing challenge={groups.habitrpg.challenges[$index]} />
|
||||
{/}
|
||||
{/}
|
||||
</div>
|
||||
</app:widgets:tabs>
|
||||
|
||||
</div>
|
||||
<list:>
|
||||
<div class="{#unless _page.new.challenge}hidden{/}">
|
||||
<app:challenges:create-form />
|
||||
</div>
|
||||
<div class="{#if _page.new.challenge}hidden{/}">
|
||||
<app:challenges:create-button type='{{@type}}' gid={{@gid}} text={{@text}} />
|
||||
{#each @list as :challenge}
|
||||
<app:challenges:list-entry challenge={:challenge} />
|
||||
{/}
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
<listing:>
|
||||
<list-entry:>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<ul class='pull-right challenge-accordion-header-specs'>
|
||||
<li>
|
||||
{count(@challenge.users)} Subscribers
|
||||
{count(@challenge.members)} Subscribers
|
||||
</li>
|
||||
<li>
|
||||
<!-- prize -->
|
||||
|
|
@ -76,66 +62,66 @@
|
|||
</li>
|
||||
<li>
|
||||
<!-- subscribe / unsubscribe -->
|
||||
<a x-bind="click:challengeUnsubscribe" class='btn btn-small btn-danger {#unless indexOf(_user.challenges,@challenge.id)}hidden{/}'><i class='icon-ban-circle'></i> Unsubscribe</a>
|
||||
<a x-bind="click:challengeSubscribe" class='btn btn-small btn-success {#if indexOf(_user.challenges,@challenge.id)}hidden{/}'><i class='icon-ok'></i> Subscribe</a>
|
||||
{#with @challenge}
|
||||
<a x-bind="click:challenges.challengeUnsubscribe" class='btn btn-small btn-danger {#unless indexOf(_page.user.pub.challenges,@challenge.id)}hidden{/}'><i class='icon-ban-circle'></i> Unsubscribe</a>
|
||||
<a x-bind="click:challenges.subscribe" class='btn btn-small btn-success {#if indexOf(_page.user.pub.challenges,@challenge.id)}hidden{/}'><i class='icon-ok'></i> Subscribe</a>
|
||||
{/}
|
||||
</li>
|
||||
</ul>
|
||||
<a class="accordion-toggle" data-toggle="collapse" href="#accordion-challenge-{{@challenge.id}}">{@challenge.name} (by {@challenge.user})</a>
|
||||
<a class="accordion-toggle" data-toggle="collapse" href="#accordion-challenge-{{@challenge.id}}">{@challenge.name} (by {@challenge.user.name})</a>
|
||||
|
||||
|
||||
</div>
|
||||
<div id="accordion-challenge-{{@challenge.id}}" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Edit button -->
|
||||
<span style='position:absolute; right:0;'>
|
||||
{#if and(not(_editing.challenges[@challenge.id]),equal(@challenge.uid,_user.id))}
|
||||
{#if and(not(_page.editing.challenges[@challenge.id]),equal(@challenge.user.uid,_session.userId))}
|
||||
<ul class='nav nav-pills'><li>
|
||||
<a x-bind='click:toggleChallengeEdit' data-id={{@challenge.id}} ><i class=icon-pencil></i></a>
|
||||
<a x-bind='click:challenges.toggleEdit' data-id={{@challenge.id}} ><i class=icon-pencil></i></a>
|
||||
</li></ul>
|
||||
{else}
|
||||
<ul class='nav nav-pills'><li>
|
||||
<a x-bind='click:toggleChallengeEdit' data-id={{@challenge.id}} ><i class=icon-ok></i></a>
|
||||
<a x-bind='click:challenges.toggleEdit' data-id={{@challenge.id}} ><i class=icon-ok></i></a>
|
||||
</li></ul>
|
||||
{/}
|
||||
</span>
|
||||
|
||||
{#if _editing.challenges[@challenge.id]}
|
||||
{#if _page.editing.challenges[@challenge.id]}
|
||||
<div class='-options'>
|
||||
<input type=text class='option-content' value={@challenge.name} />
|
||||
<textarea cols=3 class='option-content' placeholder='Description'>{@challenge.description}</textarea>
|
||||
<input type=number class='option-content' placeholder='Gems Prize' value={@challenge.prize} />
|
||||
<!--<input type=number class='option-content' placeholder='Gems Prize' value={@challenge.prize} />-->
|
||||
</div>
|
||||
{{#with @challenge}}
|
||||
<a class='btn btn-small btn-danger' x-bind=click:removeAt >Delete</a>
|
||||
<a class='btn btn-small btn-danger' x-bind=click:challenges.delete >Delete</a>
|
||||
{{/}}
|
||||
{/}
|
||||
{#if @challenge.description}<div>{@challenge.description}</div>{/}
|
||||
|
||||
<div class="grid">
|
||||
<app:tasks:task-lists
|
||||
editable={_editing.challenges[@challenge.id]}
|
||||
editable={_page.editing.challenges[@challenge.id]}
|
||||
habits={@challenge.habits}
|
||||
dailys={@challenge.dailys}
|
||||
todos={@challenge.todos}
|
||||
rewards={@challenge.rewards} />
|
||||
rewards={@challenge.rewards}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3>Statistics</h3>
|
||||
{#each @challenge.users as :member}
|
||||
{#each @challenge.members as :member}
|
||||
<h4>{:member.name}</h4>
|
||||
<div class="grid">
|
||||
<div class="module">
|
||||
<app:challenges:stats header=Habits challenge={@challenge} member={:member} taskType=habit />
|
||||
<app:challenges:stats header=Habits challenge={@challenge} member={:member} list={@challenge.habits} />
|
||||
</div>
|
||||
<div class="module">
|
||||
<app:challenges:stats header=Dailies challenge={@challenge} member={:member} taskType=daily />
|
||||
<app:challenges:stats header=Dailies challenge={@challenge} member={:member} list={@challenge.dailys} />
|
||||
</div>
|
||||
<div class="module">
|
||||
<app:challenges:stats header=Todos challenge={@challenge} member={:member} taskType=todos />
|
||||
<app:challenges:stats header=Todos challenge={@challenge} member={:member} list={@challenge.todos} />
|
||||
</div>
|
||||
</div>
|
||||
{/}
|
||||
|
|
@ -146,11 +132,11 @@
|
|||
<stats:>
|
||||
<h5>{@header}</h5>
|
||||
<div>
|
||||
{#each @challenge[@taskType]s as :task}
|
||||
{#each @list as :task}
|
||||
<table><tr>
|
||||
<td>
|
||||
<!-- FIXME commented section below isn't getting updated dynamically, temp solution is less efficient -->
|
||||
<strong>{:task.text}</strong>: {challengeMemberScore(@member,@taskType,:task.id)} <!--{round(@member[@taskType]s[:task.id].value)}-->
|
||||
<strong>{:task.text}</strong>: {challengeMemberScore(@member,:task)} <!--{round(@member[@taskType]s[:task.id].value)}-->
|
||||
</td>
|
||||
<td>
|
||||
<div style='margin-left: 10px' class="challenge-{{@challenge.id}}-member-{{@member.id}}-history-{{:task.id}}"></div>
|
||||
|
|
@ -160,67 +146,25 @@
|
|||
</div>
|
||||
|
||||
<create-button:>
|
||||
<a x-bind='click:challengeCreate' class='btn btn-success' data-type={{@type}} data-gid={{@gid}} >Create {{@text}} Challenge</a>
|
||||
<a x-bind='click:challenges.create' class='btn btn-success' data-type={{@type}} data-gid={{@gid}} >Create {{@text}} Challenge</a>
|
||||
|
||||
<create-form:>
|
||||
<form x-bind="submit:challengeSave">
|
||||
<form x-bind="submit:challenges.save">
|
||||
<div>
|
||||
<input type='submit' class='btn btn-success' value='Save' />
|
||||
<input type='button' x-bind='click:challengeDiscard' class='btn btn-danger' value=Discard />
|
||||
<input type='button' x-bind='click:challenges.discard' class='btn btn-danger' value=Discard />
|
||||
</div>
|
||||
|
||||
<div class='challenge-options'>
|
||||
<input type='text' class='option-content' value={_challenge.new.name} placeholder="Challenge Title" required />
|
||||
<input type='text' class='option-content' value={_page.new.challenge.name} placeholder="Challenge Title" required />
|
||||
</div>
|
||||
|
||||
<!--<fieldset>
|
||||
<div>
|
||||
<select>
|
||||
<option selected="{equal('party',_challenge.new.group.type)}" >Party</option>
|
||||
<option selected="{equal('guild',_challenge.new.group.type)}" >Guild</option>
|
||||
<option selected="{equal('public',_challenge.new.group.type)}" >Public</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
{#if equal(_challenge.new.assignTo,'Party')}
|
||||
<div class='row-fluid'>
|
||||
<div class='span4 well'>
|
||||
<div><input type='radio' name='challenge-party-selection' checked={_challenge.new.partyAssignees} >All Party</input></div>
|
||||
<small>No individual privacy on the challenge, all party members can see progress even if they decline the challenge. Any new party members can subscribe to this challenge.</small>
|
||||
</div>
|
||||
<div class='span8 well'>
|
||||
<div><input type='radio' name='challenge-party-selection' checked={not(_challenge.new.partyAssignees)} >Individual Members</input></div>
|
||||
<div>
|
||||
<select multiple="multiple">
|
||||
{{#each _party.members as :memberId}}
|
||||
<option>{{username(_members[:memberId].auth,_members[:memberId].profile.name)}}</option>
|
||||
{{/}}
|
||||
</select>
|
||||
</div>
|
||||
<div><small>Only the invited party members can subscribe to this challenge. New party joins won't see this challenge.</small></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/}
|
||||
{#if equal(_challenge.new.group.type,'guild')}
|
||||
<select>
|
||||
{{#each _guilds as :guild}}
|
||||
<option selected="{equal(:guild.id,_challenge.new.group.id)}" >{:guild.name}</option>
|
||||
{{/}}
|
||||
</select>
|
||||
{/}
|
||||
</div>
|
||||
</fieldset>-->
|
||||
|
||||
</form>
|
||||
|
||||
<div class="grid">
|
||||
<app:tasks:task-lists
|
||||
habits={_challenge.new.habits}
|
||||
dailys={_challenge.new.dailys}
|
||||
todos={_challenge.new.todos}
|
||||
rewards={_challenge.new.rewards}
|
||||
habits={_page.new.challenge.habits}
|
||||
dailys={_page.new.challenge.dailys}
|
||||
todos={_page.new.challenge.todos}
|
||||
rewards={_page.new.challenge.rewards}
|
||||
editable=true />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
@ -78,24 +78,30 @@ a.pull-right.gem-wallet(popover-trigger='mouseenter', popover-title='Guild Bank'
|
|||
input.btn(type='submit', value='Invite')
|
||||
|
||||
|
||||
//-accordion-group(heading='Challenges')
|
||||
span.label
|
||||
i.icon-bullhorn
|
||||
| Challenges
|
||||
| coming soon!
|
||||
a(target='_blank', href='https://trello.com/card/challenges-individual-party-guild-public/50e5d3684fe3a7266b0036d6/58') Details
|
||||
//-{#if group.challenges}
|
||||
//- <table class="table table-striped">
|
||||
//- {#each group.challenges as :challenge}
|
||||
//- <tr><td>
|
||||
//- {:challenge.name}
|
||||
//- </td></tr>
|
||||
//- {/}
|
||||
//- </table>
|
||||
//- Visit the <span class=label><i class=icon-bullhorn></i> Challenges</span> for more information.
|
||||
//-{else}
|
||||
//- No challenges yet, visit the <span class=label><i class=icon-bullhorn></i> Challenges</span> tab to create one.
|
||||
//-{/}
|
||||
//.accordion-group
|
||||
.accordion-heading
|
||||
a.accordion-toggle(data-toggle='collapse', data-parent='#accordion-{{@group.id}}-parent', href='#accordion-{{@group.id}}-challenges') Challenges
|
||||
#accordion-{{@group.id}}-challenges.accordion-body.collapse
|
||||
.accordion-inner
|
||||
span.label
|
||||
i.icon-bullhorn
|
||||
| Challenges
|
||||
| coming soon!
|
||||
a(target='_blank', href='https://trello.com/card/challenges-individual-party-guild-public/50e5d3684fe3a7266b0036d6/58') Details
|
||||
//
|
||||
// {#if @group.challenges}
|
||||
// <table class="table table-striped">
|
||||
// {#each @group.challenges as :challenge}
|
||||
// <tr><td>
|
||||
// {:challenge.name}
|
||||
// </td></tr>
|
||||
// {/}
|
||||
// </table>
|
||||
// Visit the <span class=label><i class=icon-bullhorn></i> Challenges</span> for more information.
|
||||
// {else}
|
||||
// No challenges yet, visit the <span class=label><i class=icon-bullhorn></i> Challenges</span> tab to create one.
|
||||
// {/}
|
||||
|
||||
a.btn.btn-danger(data-id='{{group.id}}', ng-click='leave(group)') Leave
|
||||
|
||||
.span8
|
||||
|
|
|
|||
|
|
@ -18,13 +18,16 @@ li(ng-repeat='task in user[list.type + "s"]', class='task {{taskClasses(task,use
|
|||
a(ng-hide='!task._editing', ng-click='toggleEdit(task)', tooltip='Cancel')
|
||||
i.icon-remove(ng-hide='!task._editing')
|
||||
//- challenges
|
||||
// {{#if task.challenge}}
|
||||
// {{#if brokenChallengeLink(task)}}
|
||||
// <i class='icon-bullhorn' style='background-color:red;' x-bind=click:toggleTaskEdit tooltip="Broken Challenge Link"></i>
|
||||
// {{else}}
|
||||
// <i class='icon-bullhorn' tooltip="Challenge Task"></i>
|
||||
// {{/}}
|
||||
// {{#if :task.challenge}}
|
||||
// {{#if brokenChallengeLink(:task)}}
|
||||
// <i class='icon-bullhorn' style='background-color:red;' x-bind=click:tasks.toggleTaskEdit rel=tooltip title="Broken Challenge Link"></i>
|
||||
// {{else}}
|
||||
// <i class='icon-bullhorn' rel=tooltip title="Challenge Task"></i>
|
||||
// {{/}}
|
||||
// {{else}}
|
||||
// <!-- delete -->
|
||||
// <a x-bind="click:tasks.del" rel=tooltip title="Delete"><i class="icon-trash"></i></a>
|
||||
// {{/}}
|
||||
|
||||
// delete
|
||||
a(ng-click='remove(task)', tooltip='Delete')
|
||||
|
|
@ -78,12 +81,24 @@ li(ng-repeat='task in user[list.type + "s"]', class='task {{taskClasses(task,use
|
|||
|
||||
// edit/options dialog
|
||||
.task-options(ng-show='task._editing')
|
||||
// {{#if brokenChallengeLink(task)}}
|
||||
// <div class='well'>
|
||||
// <p>Broken Challenge Link: this task was part of a challenge, but (a) challenge (or containing group) has been deleted, or (b) the task was deleted from the challenge.</p>
|
||||
// <p><a>Keep</a> | <a>Keep all from challenge</a> | <a>Delete</a> | <a>Delete all from challenge</a></p>
|
||||
// </div>
|
||||
// {{/}}
|
||||
//
|
||||
// {#if brokenChallengeLink(:task)}
|
||||
// <div class='well'>
|
||||
// {{#if groups[:task.group.id].challenges[:task.challenge]}}
|
||||
// <p>Broken Challenge Link: this task was part of a challenge, but has been removed from it. What would you like to do?</p>
|
||||
// <p>
|
||||
// <a x-bind="click:challenges.taskUnsubscribe" data-action="keep" data-tid="{{:task.id}}">Keep It</a> |
|
||||
// <a x-bind="click:challenges.taskUnsubscribe" data-action="remove" data-tid="{{:task.id}}">Remove It</a>
|
||||
// </p>
|
||||
// {{else}}
|
||||
// <p>Broken Challenge Link: this task was part of a challenge, but the challenge (or group) has been deleted. What would you like to do with these poor lil' orphans?</p>
|
||||
// <p>
|
||||
// <a x-bind="click:challenges.taskUnsubscribe" data-action="keep-all" data-tid="{{:task.id}}">Keep Them</a> |
|
||||
// <a x-bind="click:challenges.taskUnsubscribe" data-action="remove-all" data-tid="{{:task.id}}">Remove Them</a>
|
||||
// </p>
|
||||
// {{/}}
|
||||
// </div>
|
||||
// {/}
|
||||
form(ng-controller="TaskDetailsCtrl", ng-submit='save(task)')
|
||||
// text & notes
|
||||
fieldset.option-group
|
||||
|
|
|
|||
Loading…
Reference in a new issue