Merge branch 'develop' into blade-feature/search
BIN
common/dist/sprites/spritesmith2.png
vendored
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 664 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 705 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 693 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 542 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.2 KiB |
@@ -49,7 +49,7 @@
|
|||||||
"classBonusText": "Your class (Warrior, if you haven't unlocked or selected another class) uses its own equipment more effectively than gear from other classes. Equipped gear from your current class gets a 50% boost to the attribute bonus it grants.",
|
"classBonusText": "Your class (Warrior, if you haven't unlocked or selected another class) uses its own equipment more effectively than gear from other classes. Equipped gear from your current class gets a 50% boost to the attribute bonus it grants.",
|
||||||
"classEquipBonus": "Class Bonus",
|
"classEquipBonus": "Class Bonus",
|
||||||
"battleGear": "Battle Gear",
|
"battleGear": "Battle Gear",
|
||||||
"battleGearText": "This is the gear you wear into battle, it affects numbers when interacting with your tasks.",
|
"battleGearText": "This is the gear you wear into battle; it affects numbers when interacting with your tasks.",
|
||||||
"costume": "Costume",
|
"costume": "Costume",
|
||||||
"costumeText": "If you prefer the look of other gear to what you have equipped, check the \"Use Costume\" box to visually don a costume while wearing your battle gear underneath.",
|
"costumeText": "If you prefer the look of other gear to what you have equipped, check the \"Use Costume\" box to visually don a costume while wearing your battle gear underneath.",
|
||||||
"useCostume": "Use Costume",
|
"useCostume": "Use Costume",
|
||||||
|
|||||||
@@ -70,7 +70,6 @@
|
|||||||
"lastLoggedIn": "- Last logged in",
|
"lastLoggedIn": "- Last logged in",
|
||||||
"notPorted": "This feature is not yet ported from the original site.",
|
"notPorted": "This feature is not yet ported from the original site.",
|
||||||
"buyThis": "Buy this <%= text %> with <%= price %> of your <%= gems %> Gems?",
|
"buyThis": "Buy this <%= text %> with <%= price %> of your <%= gems %> Gems?",
|
||||||
"untilNoFace": "Until we add Facebook, use your UUID and API Token to log in (found at https://habitrpg.com > Options > Settings).",
|
|
||||||
"noReachServer": "Server not currently reachable, try again later",
|
"noReachServer": "Server not currently reachable, try again later",
|
||||||
"errorUpCase": "ERROR:",
|
"errorUpCase": "ERROR:",
|
||||||
"newPassSent": "New password sent.",
|
"newPassSent": "New password sent.",
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
"editGroup": "Edit Group",
|
"editGroup": "Edit Group",
|
||||||
"newGroupName": "<%= groupType %> Name",
|
"newGroupName": "<%= groupType %> Name",
|
||||||
"groupName": "Group Name",
|
"groupName": "Group Name",
|
||||||
|
"groupLeader": "Group Leader",
|
||||||
|
"groupID": "Group ID",
|
||||||
"groupDescr": "Description shown in public Guilds list (Markdown OK)",
|
"groupDescr": "Description shown in public Guilds list (Markdown OK)",
|
||||||
"logoUrl": "Logo URL",
|
"logoUrl": "Logo URL",
|
||||||
"assignLeader": "Assign Group Leader",
|
"assignLeader": "Assign Group Leader",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"quest": "quest",
|
"quest": "quest",
|
||||||
"completed": "Completed!",
|
"completed": "Completed!",
|
||||||
"youReceived": "You've Received",
|
"youReceived": "You've Received",
|
||||||
"questSend": "Clicking \"Invite\" will send an invitation to your party members. When all members have accepted or denied, the quest begins. See status under Options > Social > Party.",
|
"questSend": "Clicking \"Invite\" will send an invitation to your party members. When all members have accepted or denied, the quest begins. See status under Social > Party.",
|
||||||
"inviteParty": "Invite Party",
|
"inviteParty": "Invite Party",
|
||||||
"questInvitation": "Quest Invitation: ",
|
"questInvitation": "Quest Invitation: ",
|
||||||
"questInvitationTitle": "Quest Invitation",
|
"questInvitationTitle": "Quest Invitation",
|
||||||
|
|||||||
@@ -36,6 +36,11 @@
|
|||||||
"newDailyBulk": "New Dailies (one per line)",
|
"newDailyBulk": "New Dailies (one per line)",
|
||||||
"streakCounter": "Streak Counter",
|
"streakCounter": "Streak Counter",
|
||||||
"repeat": "Repeat",
|
"repeat": "Repeat",
|
||||||
|
"repeatEvery": "Repeat Every",
|
||||||
|
"repeatDays": "Every X Days",
|
||||||
|
"repeatWeek": "On Certain Days of the Week",
|
||||||
|
"day": "Day",
|
||||||
|
"days": "Days",
|
||||||
"restoreStreak": "Restore Streak",
|
"restoreStreak": "Restore Streak",
|
||||||
"todos": "To-Dos",
|
"todos": "To-Dos",
|
||||||
"newTodo": "New To-Do",
|
"newTodo": "New To-Do",
|
||||||
@@ -60,6 +65,9 @@
|
|||||||
"clearTags": "Clear",
|
"clearTags": "Clear",
|
||||||
"hideTags": "Hide",
|
"hideTags": "Hide",
|
||||||
"showTags": "Show",
|
"showTags": "Show",
|
||||||
|
"startDate": "Start Date",
|
||||||
|
"startDateHelpTitle": "When should this task start?",
|
||||||
|
"startDateHelp": "Set the date for which this task takes effect. Will not be due on earlier days.",
|
||||||
"streakName": "Streak Achievements",
|
"streakName": "Streak Achievements",
|
||||||
"streakText": "Has performed <%= streaks %> 21-day streaks on Dailies",
|
"streakText": "Has performed <%= streaks %> 21-day streaks on Dailies",
|
||||||
"streakSingular": "Streaker",
|
"streakSingular": "Streaker",
|
||||||
@@ -81,17 +89,17 @@
|
|||||||
"dailiesRestingInInn": "You're Resting in the Inn! Your Dailies will NOT hurt you tonight, but they WILL still refresh every day. If you're in a quest, you won't deal damage/collect items until you check out of the Inn, but you can still be injured by a Boss if your Party mates skip their own Dailies.",
|
"dailiesRestingInInn": "You're Resting in the Inn! Your Dailies will NOT hurt you tonight, but they WILL still refresh every day. If you're in a quest, you won't deal damage/collect items until you check out of the Inn, but you can still be injured by a Boss if your Party mates skip their own Dailies.",
|
||||||
"habitHelp1": "Good Habits are things that you do often. They award Gold and Experience every time you click the <%= plusIcon %>.",
|
"habitHelp1": "Good Habits are things that you do often. They award Gold and Experience every time you click the <%= plusIcon %>.",
|
||||||
"habitHelp2": "Bad Habits are things you want to avoid doing. They remove Health every time you click the <%= minusIcon %>.",
|
"habitHelp2": "Bad Habits are things you want to avoid doing. They remove Health every time you click the <%= minusIcon %>.",
|
||||||
"habitHelp3": "For inspiration, check out <%= linkStart %>these sample Habits<%= linkEnd %>.",
|
"habitHelp3": "For inspiration, check out these <a href='http://habitrpg.wikia.com/wiki/Sample_Habits' target='_blank'>sample Habits</a>!",
|
||||||
"newbieGuild": "More questions? Ask in the <%= linkStart %>Newbies Guild<%= linkEnd %>!",
|
"newbieGuild": "More questions? Ask in the <%= linkStart %>Newbies Guild<%= linkEnd %>!",
|
||||||
"dailyHelp1": "Dailies repeat <%= emphasisStart %>every day<%= emphasisEnd %> that they are active. Click the <%= pencilIcon %> to change the days a Daily is active.",
|
"dailyHelp1": "Dailies repeat <%= emphasisStart %>every day<%= emphasisEnd %> that they are active. Click the <%= pencilIcon %> to change the days a Daily is active.",
|
||||||
"dailyHelp2": "If you don't complete active Dailies, you lose Health when your day rolls over.",
|
"dailyHelp2": "If you don't complete active Dailies, you lose Health when your day rolls over.",
|
||||||
"dailyHelp3": "Dailies turn <%= emphasisStart %>redder<%= emphasisEnd %> when you miss them, and <%= emphasisStart %>bluer<%= emphasisEnd %> when you complete them. The redder the Daily, the more it will reward you... or hurt you.",
|
"dailyHelp3": "Dailies turn <%= emphasisStart %>redder<%= emphasisEnd %> when you miss them, and <%= emphasisStart %>bluer<%= emphasisEnd %> when you complete them. The redder the Daily, the more it will reward you... or hurt you.",
|
||||||
"dailyHelp4": "To change when your day rolls over, go to <%= linkStart %> Settings > Site<%= linkEnd %> > Custom Day Start.",
|
"dailyHelp4": "To change when your day rolls over, go to <%= linkStart %> Settings > Site<%= linkEnd %> > Custom Day Start.",
|
||||||
"dailyHelp5": "For inspiration, check out these <%= linkStart %>sample Dailies<%= linkEnd %>!",
|
"dailyHelp5": "For inspiration, check out these <a href='http://habitrpg.wikia.com/wiki/Sample_Dailies' target='_blank'>sample Dailies</a>!",
|
||||||
"toDoHelp1": "To-Dos start yellow, and get redder (more valuable) the longer it takes to complete them.",
|
"toDoHelp1": "To-Dos start yellow, and get redder (more valuable) the longer it takes to complete them.",
|
||||||
"toDoHelp2": "To-Dos never hurt you! They only award Gold and Experience.",
|
"toDoHelp2": "To-Dos never hurt you! They only award Gold and Experience.",
|
||||||
"toDoHelp3": "Breaking a To-Do down into a checklist of smaller items will make it less scary, and will increase your points!",
|
"toDoHelp3": "Breaking a To-Do down into a checklist of smaller items will make it less scary, and will increase your points!",
|
||||||
"toDoHelp4": "For inspiration, check out these <%= linkStart %>sample To-Dos<%= linkEnd %>!",
|
"toDoHelp4": "For inspiration, check out these <a href='http://habitrpg.wikia.com/wiki/Sample_To-Dos' target='_blank'>sample To-Dos</a>!",
|
||||||
"rewardHelp1": "The Equipment you buy for your avatar is stored in <%= linkStart %>Inventory > Equipment<%= linkEnd %>.",
|
"rewardHelp1": "The Equipment you buy for your avatar is stored in <%= linkStart %>Inventory > Equipment<%= linkEnd %>.",
|
||||||
"rewardHelp2": "Equipment affects your stats (<%= linkStart %>Avatar > Stats<%= linkEnd %>).",
|
"rewardHelp2": "Equipment affects your stats (<%= linkStart %>Avatar > Stats<%= linkEnd %>).",
|
||||||
"rewardHelp3": "Special equipment will appear here during World Events.",
|
"rewardHelp3": "Special equipment will appear here during World Events.",
|
||||||
|
|||||||
@@ -1877,9 +1877,9 @@ _.each api.subscriptionBlocks, (b,k)->b.key = k
|
|||||||
repeat = {m:true,t:true,w:true,th:true,f:true,s:true,su:true}
|
repeat = {m:true,t:true,w:true,th:true,f:true,s:true,su:true}
|
||||||
api.userDefaults =
|
api.userDefaults =
|
||||||
habits: [
|
habits: [
|
||||||
{type: 'habit', text: t('defaultHabit1Text'), notes: t('defaultTaskNotes'), value: 0, up: true, down: false, attribute: 'per' }
|
{type: 'habit', text: t('defaultHabit1Text'), value: 0, up: true, down: false, attribute: 'per' }
|
||||||
{type: 'habit', text: t('defaultHabit2Text'), notes: t('defaultTaskNotes'), value: 0, up: false, down: true, attribute: 'str'}
|
{type: 'habit', text: t('defaultHabit2Text'), value: 0, up: false, down: true, attribute: 'str'}
|
||||||
{type: 'habit', text: t('defaultHabit3Text'), notes: t('defaultTaskNotes'), value: 0, up: true, down: true, attribute: 'str'}
|
{type: 'habit', text: t('defaultHabit3Text'), value: 0, up: true, down: true, attribute: 'str'}
|
||||||
]
|
]
|
||||||
|
|
||||||
dailys: [
|
dailys: [
|
||||||
@@ -1898,7 +1898,7 @@ api.userDefaults =
|
|||||||
]
|
]
|
||||||
|
|
||||||
rewards: [
|
rewards: [
|
||||||
{type: 'reward', text: t('defaultReward1Text'), notes: t('defaultTaskNotes'), value: 10 }
|
{type: 'reward', text: t('defaultReward1Text'), value: 10 }
|
||||||
# {type: 'reward', text: t('defaultReward2Text'), notes: t('defaultReward2Notes'), value: 10 }
|
# {type: 'reward', text: t('defaultReward2Text'), notes: t('defaultReward2Notes'), value: 10 }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -72,13 +72,37 @@ api.daysSince = (yesterday, options = {}) ->
|
|||||||
Math.abs api.startOfDay(_.defaults {now:yesterday}, o).diff(api.startOfDay(_.defaults {now:o.now}, o), 'days')
|
Math.abs api.startOfDay(_.defaults {now:yesterday}, o).diff(api.startOfDay(_.defaults {now:o.now}, o), 'days')
|
||||||
|
|
||||||
###
|
###
|
||||||
Should the user do this taks on this date, given the task's repeat options and user.preferences.dayStart?
|
Should the user do this task on this date, given the task's repeat options and user.preferences.dayStart?
|
||||||
###
|
###
|
||||||
api.shouldDo = (day, repeat, options={}) ->
|
api.shouldDo = (day, dailyTask, options = {}) ->
|
||||||
return false unless repeat
|
return false unless dailyTask.type == 'daily' && dailyTask.repeat
|
||||||
|
if !dailyTask.startDate
|
||||||
|
dailyTask.startDate = moment().toDate()
|
||||||
|
if dailyTask.startDate instanceof String
|
||||||
|
dailyTask.startDate = moment(dailyTask.startDate).toDate()
|
||||||
o = sanitizeOptions options
|
o = sanitizeOptions options
|
||||||
selected = repeat[api.dayMapping[api.startOfDay(_.defaults {now:day}, o).day()]]
|
day = api.startOfDay(_.defaults {now:day}, o)
|
||||||
return selected
|
dayOfWeekNum = day.day() # e.g. 1 for Monday if week starts on Mon
|
||||||
|
|
||||||
|
# check if event is today or in the future
|
||||||
|
hasStartedCheck = day >= api.startOfDay(_.defaults {now:dailyTask.startDate}, o)
|
||||||
|
|
||||||
|
if dailyTask.frequency == 'daily'
|
||||||
|
daysSinceTaskStart = api.numDaysApart(day.startOf('day'), dailyTask.startDate, o)
|
||||||
|
everyXCheck = (daysSinceTaskStart % dailyTask.everyX == 0)
|
||||||
|
return everyXCheck && hasStartedCheck
|
||||||
|
else if dailyTask.frequency == 'weekly'
|
||||||
|
dayOfWeekCheck = dailyTask.repeat[api.dayMapping[dayOfWeekNum]]
|
||||||
|
return dayOfWeekCheck && hasStartedCheck
|
||||||
|
else
|
||||||
|
# unexpected frequency string
|
||||||
|
return false
|
||||||
|
|
||||||
|
api.numDaysApart = (day1, day2, o) ->
|
||||||
|
startOfDay1 = api.startOfDay(_.defaults {now:day1}, o)
|
||||||
|
startOfDay2 = api.startOfDay(_.defaults {now:day2}, o)
|
||||||
|
numDays = Math.abs(startOfDay1.diff(startOfDay2, 'days'))
|
||||||
|
return numDays
|
||||||
|
|
||||||
###
|
###
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
@@ -211,7 +235,7 @@ api.taskDefaults = (task={}) ->
|
|||||||
_.defaults(task, {up:true,down:true}) if task.type is 'habit'
|
_.defaults(task, {up:true,down:true}) if task.type is 'habit'
|
||||||
_.defaults(task, {history: []}) if task.type in ['habit', 'daily']
|
_.defaults(task, {history: []}) if task.type in ['habit', 'daily']
|
||||||
_.defaults(task, {completed:false}) if task.type in ['daily', 'todo']
|
_.defaults(task, {completed:false}) if task.type in ['daily', 'todo']
|
||||||
_.defaults(task, {streak:0, repeat: {su:1,m:1,t:1,w:1,th:1,f:1,s:1}}) if task.type is 'daily'
|
_.defaults(task, {streak:0, repeat: {su:1,m:1,t:1,w:1,th:1,f:1,s:1}}, startDate: new Date(), everyX: 1, frequency: 'weekly') if task.type is 'daily'
|
||||||
task._id = task.id # may need this for TaskSchema if we go back to using it, see http://goo.gl/a5irq4
|
task._id = task.id # may need this for TaskSchema if we go back to using it, see http://goo.gl/a5irq4
|
||||||
task.value ?= if task.type is 'reward' then 10 else 0
|
task.value ?= if task.type is 'reward' then 10 else 0
|
||||||
task.priority = 1 unless _.isNumber(task.priority) # hotfix for apiv1. once we're off apiv1, we can remove this
|
task.priority = 1 unless _.isNumber(task.priority) # hotfix for apiv1. once we're off apiv1, we can remove this
|
||||||
@@ -281,7 +305,7 @@ api.taskClasses = (task, filters=[], dayStart=0, lastCron=+new Date, showComplet
|
|||||||
|
|
||||||
# show as completed if completed (naturally) or not required for today
|
# show as completed if completed (naturally) or not required for today
|
||||||
if type in ['todo', 'daily']
|
if type in ['todo', 'daily']
|
||||||
if completed or (type is 'daily' and !api.shouldDo(+new Date, task.repeat, {dayStart}))
|
if completed or (type is 'daily' and !api.shouldDo(+new Date, task, {dayStart}))
|
||||||
classes += " completed"
|
classes += " completed"
|
||||||
else
|
else
|
||||||
classes += " uncompleted"
|
classes += " uncompleted"
|
||||||
@@ -1565,7 +1589,7 @@ api.wrap = (user, main=true) ->
|
|||||||
{completed, repeat} = daily
|
{completed, repeat} = daily
|
||||||
thatDay = moment(now).subtract({days: 1})
|
thatDay = moment(now).subtract({days: 1})
|
||||||
|
|
||||||
if api.shouldDo(thatDay, repeat, user.preferences) || completed
|
if api.shouldDo(thatDay.toDate(), daily, user.preferences) || completed
|
||||||
_.each daily.checklist, ((box)->box.completed=false;true)
|
_.each daily.checklist, ((box)->box.completed=false;true)
|
||||||
daily.completed = false
|
daily.completed = false
|
||||||
return
|
return
|
||||||
@@ -1592,7 +1616,7 @@ api.wrap = (user, main=true) ->
|
|||||||
scheduleMisses = 0
|
scheduleMisses = 0
|
||||||
_.times daysMissed, (n) ->
|
_.times daysMissed, (n) ->
|
||||||
thatDay = moment(now).subtract({days: n + 1})
|
thatDay = moment(now).subtract({days: n + 1})
|
||||||
if api.shouldDo(thatDay, repeat, user.preferences)
|
if api.shouldDo(thatDay.toDate(), task, user.preferences)
|
||||||
scheduleMisses++
|
scheduleMisses++
|
||||||
if user.stats.buffs.stealth
|
if user.stats.buffs.stealth
|
||||||
user.stats.buffs.stealth--
|
user.stats.buffs.stealth--
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Group = require("../../website/src/models/group").model
|
|||||||
app = require("../../website/src/server")
|
app = require("../../website/src/server")
|
||||||
|
|
||||||
describe "Guilds", ->
|
describe "Guilds", ->
|
||||||
|
context "creating groups", ->
|
||||||
before (done) ->
|
before (done) ->
|
||||||
registerNewUser ->
|
registerNewUser ->
|
||||||
User.findByIdAndUpdate user._id,
|
User.findByIdAndUpdate user._id,
|
||||||
@@ -15,7 +16,6 @@ describe "Guilds", ->
|
|||||||
done()
|
done()
|
||||||
, true
|
, true
|
||||||
|
|
||||||
context "creating groups", ->
|
|
||||||
it "can create a public guild", (done) ->
|
it "can create a public guild", (done) ->
|
||||||
request.post(baseURL + "/groups").send(
|
request.post(baseURL + "/groups").send(
|
||||||
name: "TestGroup"
|
name: "TestGroup"
|
||||||
@@ -53,19 +53,42 @@ describe "Guilds", ->
|
|||||||
done()
|
done()
|
||||||
, false
|
, false
|
||||||
|
|
||||||
context "finding groups", ->
|
context "get guilds", ->
|
||||||
it "can find a guild", (done) ->
|
|
||||||
guild = undefined
|
guild = undefined
|
||||||
|
|
||||||
|
beforeEach (done)->
|
||||||
request.post(baseURL + "/groups").send(
|
request.post(baseURL + "/groups").send(
|
||||||
name: "TestGroup2"
|
name: "TestGroup2"
|
||||||
type: "guild"
|
type: "guild"
|
||||||
).end (res) ->
|
).end (res) ->
|
||||||
guild = res.body
|
guild = res.body
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "can find a guild", (done) ->
|
||||||
request.get(baseURL + "/groups/" + guild._id)
|
request.get(baseURL + "/groups/" + guild._id)
|
||||||
.send()
|
|
||||||
.end (res) ->
|
.end (res) ->
|
||||||
expectCode res, 200
|
expectCode res, 200
|
||||||
expect(guild._id).to.equal res.body._id
|
expect(res.body._id).to.equal res.body._id
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "transforms members array to an arrray of user objects", (done) ->
|
||||||
|
request.get(baseURL + "/groups/" + guild._id)
|
||||||
|
.end (res) ->
|
||||||
|
expectCode res, 200
|
||||||
|
members = res.body.members
|
||||||
|
# @TODO: would be more instructive if it had more members in guild :(
|
||||||
|
_(members).each (member) ->
|
||||||
|
expect(member).to.be.an 'object'
|
||||||
|
expect(member.profile.name).to.exist
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "transforms leader id to a user object", (done) ->
|
||||||
|
request.get(baseURL + "/groups/" + guild._id)
|
||||||
|
.end (res) ->
|
||||||
|
expectCode res, 200
|
||||||
|
leader = res.body.leader
|
||||||
|
expect(leader).to.be.an 'object'
|
||||||
|
expect(leader.profile.name).to.exist
|
||||||
done()
|
done()
|
||||||
|
|
||||||
it "can list guilds", (done) ->
|
it "can list guilds", (done) ->
|
||||||
@@ -228,17 +251,24 @@ describe "Guilds", ->
|
|||||||
describe "Public Guilds", ->
|
describe "Public Guilds", ->
|
||||||
guild = undefined
|
guild = undefined
|
||||||
before (done) ->
|
before (done) ->
|
||||||
|
async.waterfall [
|
||||||
|
(cb) ->
|
||||||
|
registerNewUser ->
|
||||||
|
User.findByIdAndUpdate user._id, {$set: { "balance": 10 } }, (err, _user) ->
|
||||||
|
cb()
|
||||||
|
, true
|
||||||
|
(cb) ->
|
||||||
request.post(baseURL + "/groups").send(
|
request.post(baseURL + "/groups").send(
|
||||||
name: "TestPublicGroup"
|
name: "TestPublicGroup"
|
||||||
type: "guild"
|
type: "guild"
|
||||||
privacy: "public"
|
privacy: "public"
|
||||||
).end (res) ->
|
).end (res) ->
|
||||||
expectCode res, 200
|
|
||||||
guild = res.body
|
guild = res.body
|
||||||
expect(guild.members.length).to.equal 1
|
expect(guild.members.length).to.equal 1
|
||||||
expect(guild.leader).to.equal user._id
|
expect(guild.leader).to.equal user._id
|
||||||
#Add members to guild
|
#Add members to guild
|
||||||
async.waterfall [
|
cb()
|
||||||
|
|
||||||
(cb) ->
|
(cb) ->
|
||||||
registerManyUsers 15, cb
|
registerManyUsers 15, cb
|
||||||
|
|
||||||
@@ -253,13 +283,14 @@ describe "Guilds", ->
|
|||||||
callback(null, null)
|
callback(null, null)
|
||||||
|
|
||||||
async.map members, joinGuild, (err, results) -> cb()
|
async.map members, joinGuild, (err, results) -> cb()
|
||||||
|
|
||||||
], done
|
], done
|
||||||
|
|
||||||
context "is a member", ->
|
context "is a member", ->
|
||||||
before (done) ->
|
before (done) ->
|
||||||
registerNewUser ->
|
registerNewUser ->
|
||||||
request.post(baseURL + "/groups/" + guild._id + "/join")
|
request.post(baseURL + "/groups/" + guild._id + "/join")
|
||||||
.end ->
|
.end (res)->
|
||||||
done()
|
done()
|
||||||
, true
|
, true
|
||||||
|
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ describe 'User', ->
|
|||||||
it 'handles perfect days', ->
|
it 'handles perfect days', ->
|
||||||
user = newUser()
|
user = newUser()
|
||||||
user.dailys = []
|
user.dailys = []
|
||||||
_.times 3, ->user.dailys.push shared.taskDefaults({type:'daily'})
|
_.times 3, ->user.dailys.push shared.taskDefaults({type:'daily', startDate: moment().subtract(7, 'days')})
|
||||||
cron = -> user.lastCron = moment().subtract(1,'days');user.fns.cron()
|
cron = -> user.lastCron = moment().subtract(1,'days');user.fns.cron()
|
||||||
|
|
||||||
cron()
|
cron()
|
||||||
@@ -193,7 +193,7 @@ describe 'User', ->
|
|||||||
user.preferences.sleep = true
|
user.preferences.sleep = true
|
||||||
cron = -> user.lastCron = moment().subtract(1, 'days');user.fns.cron()
|
cron = -> user.lastCron = moment().subtract(1, 'days');user.fns.cron()
|
||||||
user.dailys = []
|
user.dailys = []
|
||||||
_.times 2, -> user.dailys.push shared.taskDefaults({type:'daily'})
|
_.times 2, -> user.dailys.push shared.taskDefaults({type:'daily', startDate: moment().subtract(7, 'days')})
|
||||||
|
|
||||||
it 'remains in the inn on cron', ->
|
it 'remains in the inn on cron', ->
|
||||||
cron()
|
cron()
|
||||||
@@ -883,8 +883,9 @@ describe 'Cron', ->
|
|||||||
before.dailys[0].repeat = after.dailys[0].repeat = options.repeat if options.repeat
|
before.dailys[0].repeat = after.dailys[0].repeat = options.repeat if options.repeat
|
||||||
before.dailys[0].streak = after.dailys[0].streak = 10
|
before.dailys[0].streak = after.dailys[0].streak = 10
|
||||||
before.dailys[0].completed = after.dailys[0].completed = true if options.checked
|
before.dailys[0].completed = after.dailys[0].completed = true if options.checked
|
||||||
|
before.dailys[0].startDate = after.dailys[0].startDate = moment().subtract(30, 'days')
|
||||||
if options.shouldDo
|
if options.shouldDo
|
||||||
expect(shared.shouldDo(now, options.repeat, {timezoneOffset, dayStart:options.dayStart, now})).to.be.ok()
|
expect(shared.shouldDo(now.toDate(), after.dailys[0], {timezoneOffset, dayStart:options.dayStart, now})).to.be.ok()
|
||||||
after.fns.cron {now}
|
after.fns.cron {now}
|
||||||
before.stats.mp=after.stats.mp #FIXME
|
before.stats.mp=after.stats.mp #FIXME
|
||||||
switch options.expect
|
switch options.expect
|
||||||
|
|||||||
330
test/common/dailies.coffee
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
_ = require 'lodash'
|
||||||
|
expect = require 'expect.js'
|
||||||
|
sinon = require 'sinon'
|
||||||
|
moment = require 'moment'
|
||||||
|
shared = require '../../common/script/index.coffee'
|
||||||
|
shared.i18n.translations = require('../../website/src/i18n.js').translations
|
||||||
|
|
||||||
|
repeatWithoutLastWeekday = ()->
|
||||||
|
repeat = {su:1,m:1,t:1,w:1,th:1,f:1,s:1}
|
||||||
|
if shared.startOfWeek(moment().zone(0)).isoWeekday() == 1 # Monday
|
||||||
|
repeat.su = false
|
||||||
|
else
|
||||||
|
repeat.s = false
|
||||||
|
{repeat: repeat}
|
||||||
|
|
||||||
|
### Helper Functions ####
|
||||||
|
# @TODO: Refactor into helper file
|
||||||
|
newUser = (addTasks=true)->
|
||||||
|
buffs = {per:0, int:0, con:0, str:0, stealth: 0, streaks: false}
|
||||||
|
user =
|
||||||
|
auth:
|
||||||
|
timestamps: {}
|
||||||
|
stats: {str:1, con:1, per:1, int:1, mp: 32, class: 'warrior', buffs: buffs}
|
||||||
|
items:
|
||||||
|
lastDrop:
|
||||||
|
count: 0
|
||||||
|
hatchingPotions: {}
|
||||||
|
eggs: {}
|
||||||
|
food: {}
|
||||||
|
gear:
|
||||||
|
equipped: {}
|
||||||
|
costume: {}
|
||||||
|
party:
|
||||||
|
quest:
|
||||||
|
progress:
|
||||||
|
down: 0
|
||||||
|
preferences: {}
|
||||||
|
dailys: []
|
||||||
|
todos: []
|
||||||
|
rewards: []
|
||||||
|
flags: {}
|
||||||
|
achievements: {}
|
||||||
|
contributor:
|
||||||
|
level: 2
|
||||||
|
shared.wrap(user)
|
||||||
|
user.ops.reset(null, ->)
|
||||||
|
if addTasks
|
||||||
|
_.each ['habit', 'todo', 'daily'], (task)->
|
||||||
|
user.ops.addTask {body: {type: task, id: shared.uuid()}}
|
||||||
|
user
|
||||||
|
|
||||||
|
cron = (usr) ->
|
||||||
|
usr.lastCron = moment().subtract(1,'days')
|
||||||
|
usr.fns.cron()
|
||||||
|
|
||||||
|
describe 'daily/weekly that repeats everyday (default)', ->
|
||||||
|
user = null
|
||||||
|
daily = null
|
||||||
|
weekly = null
|
||||||
|
|
||||||
|
describe 'when startDate is in the future', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
user = newUser()
|
||||||
|
user.dailys = [
|
||||||
|
shared.taskDefaults({type:'daily', startDate: moment().add(7, 'days'), frequency: 'daily'})
|
||||||
|
shared.taskDefaults({type:'daily', startDate: moment().add(7, 'days'), frequency: 'weekly', repeat: {su:1,m:1,t:1,w:1,th:1,f:1,s:1}})
|
||||||
|
]
|
||||||
|
daily = user.dailys[0]
|
||||||
|
weekly = user.dailys[1]
|
||||||
|
|
||||||
|
it 'does not damage user for not completing it', ->
|
||||||
|
cron(user)
|
||||||
|
expect(user.stats.hp).to.be 50
|
||||||
|
|
||||||
|
it 'does not change value on cron if daily is incomplete', ->
|
||||||
|
cron(user)
|
||||||
|
expect(daily.value).to.be 0
|
||||||
|
expect(weekly.value).to.be 0
|
||||||
|
|
||||||
|
it 'does not reset checklists if daily is not marked as complete', ->
|
||||||
|
checklist = [
|
||||||
|
{
|
||||||
|
'text' : '1',
|
||||||
|
'id' : 'checklist-one',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '2',
|
||||||
|
'id' : 'checklist-two',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '3',
|
||||||
|
'id' : 'checklist-three',
|
||||||
|
'completed' : false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
daily.checklist = checklist
|
||||||
|
weekly.checklist = checklist
|
||||||
|
cron(user)
|
||||||
|
|
||||||
|
expect(daily.checklist[0].completed).to.be true
|
||||||
|
expect(daily.checklist[1].completed).to.be true
|
||||||
|
expect(daily.checklist[2].completed).to.be false
|
||||||
|
|
||||||
|
expect(weekly.checklist[0].completed).to.be true
|
||||||
|
expect(weekly.checklist[1].completed).to.be true
|
||||||
|
expect(weekly.checklist[2].completed).to.be false
|
||||||
|
|
||||||
|
it 'resets checklists if daily is marked as complete', ->
|
||||||
|
checklist = [
|
||||||
|
{
|
||||||
|
'text' : '1',
|
||||||
|
'id' : 'checklist-one',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '2',
|
||||||
|
'id' : 'checklist-two',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '3',
|
||||||
|
'id' : 'checklist-three',
|
||||||
|
'completed' : false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
daily.checklist = checklist
|
||||||
|
weekly.checklist = checklist
|
||||||
|
daily.completed = true
|
||||||
|
weekly.completed = true
|
||||||
|
cron(user)
|
||||||
|
|
||||||
|
_.each daily.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
_.each weekly.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
it 'is due on startDate', ->
|
||||||
|
daily_due_today = shared.shouldDo moment(), daily
|
||||||
|
daily_due_on_start_date = shared.shouldDo moment().add(7, 'days'), daily
|
||||||
|
|
||||||
|
expect(daily_due_today).to.be false
|
||||||
|
expect(daily_due_on_start_date).to.be true
|
||||||
|
|
||||||
|
weekly_due_today = shared.shouldDo moment(), weekly
|
||||||
|
weekly_due_on_start_date = shared.shouldDo moment().add(7, 'days'), weekly
|
||||||
|
|
||||||
|
expect(weekly_due_today).to.be false
|
||||||
|
expect(weekly_due_on_start_date).to.be true
|
||||||
|
|
||||||
|
describe 'when startDate is in the past', ->
|
||||||
|
completeDaily = null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
user = newUser()
|
||||||
|
user.dailys = [
|
||||||
|
shared.taskDefaults({type:'daily', startDate: moment().subtract(7, 'days'), frequency: 'daily'})
|
||||||
|
shared.taskDefaults({type:'daily', startDate: moment().subtract(7, 'days'), frequency: 'weekly'})
|
||||||
|
]
|
||||||
|
daily = user.dailys[0]
|
||||||
|
weekly = user.dailys[1]
|
||||||
|
|
||||||
|
it 'does damage user for not completing it', ->
|
||||||
|
cron(user)
|
||||||
|
expect(user.stats.hp).to.be.lessThan 50
|
||||||
|
|
||||||
|
it 'decreases value on cron if daily is incomplete', ->
|
||||||
|
cron(user)
|
||||||
|
expect(daily.value).to.be.lessThan 0
|
||||||
|
expect(weekly.value).to.be.lessThan 0
|
||||||
|
|
||||||
|
it 'resets checklists if daily is not marked as complete', ->
|
||||||
|
checklist = [
|
||||||
|
{
|
||||||
|
'text' : '1',
|
||||||
|
'id' : 'checklist-one',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '2',
|
||||||
|
'id' : 'checklist-two',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '3',
|
||||||
|
'id' : 'checklist-three',
|
||||||
|
'completed' : false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
daily.checklist = checklist
|
||||||
|
weekly.checklist = checklist
|
||||||
|
cron(user)
|
||||||
|
|
||||||
|
_.each daily.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
_.each weekly.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
it 'resets checklists if daily is marked as complete', ->
|
||||||
|
checklist = [
|
||||||
|
{
|
||||||
|
'text' : '1',
|
||||||
|
'id' : 'checklist-one',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '2',
|
||||||
|
'id' : 'checklist-two',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '3',
|
||||||
|
'id' : 'checklist-three',
|
||||||
|
'completed' : false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
daily.checklist = checklist
|
||||||
|
daily.completed = true
|
||||||
|
weekly.checklist = checklist
|
||||||
|
weekly.completed = true
|
||||||
|
cron(user)
|
||||||
|
|
||||||
|
_.each daily.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
_.each weekly.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
describe 'when startDate is today', ->
|
||||||
|
completeDaily = null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
user = newUser()
|
||||||
|
user.dailys = [
|
||||||
|
# Must set start date to yesterday, because cron mock sets last cron to yesterday
|
||||||
|
shared.taskDefaults({type:'daily', startDate: moment().subtract(1, 'days'), frequency: 'daily'})
|
||||||
|
shared.taskDefaults({type:'daily', startDate: moment().subtract(1, 'days'), frequency: 'weekly'})
|
||||||
|
]
|
||||||
|
daily = user.dailys[0]
|
||||||
|
weekly = user.dailys[1]
|
||||||
|
|
||||||
|
it 'does damage user for not completing it', ->
|
||||||
|
cron(user)
|
||||||
|
expect(user.stats.hp).to.be.lessThan 50
|
||||||
|
|
||||||
|
it 'decreases value on cron if daily is incomplete', ->
|
||||||
|
cron(user)
|
||||||
|
expect(daily.value).to.be.lessThan 0
|
||||||
|
expect(weekly.value).to.be.lessThan 0
|
||||||
|
|
||||||
|
it 'resets checklists if daily is not marked as complete', ->
|
||||||
|
checklist = [
|
||||||
|
{
|
||||||
|
'text' : '1',
|
||||||
|
'id' : 'checklist-one',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '2',
|
||||||
|
'id' : 'checklist-two',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '3',
|
||||||
|
'id' : 'checklist-three',
|
||||||
|
'completed' : false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
daily.checklist = checklist
|
||||||
|
weekly.checklist = checklist
|
||||||
|
cron(user)
|
||||||
|
|
||||||
|
_.each daily.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
_.each weekly.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
it 'resets checklists if daily is marked as complete', ->
|
||||||
|
checklist = [
|
||||||
|
{
|
||||||
|
'text' : '1',
|
||||||
|
'id' : 'checklist-one',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '2',
|
||||||
|
'id' : 'checklist-two',
|
||||||
|
'completed' : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'text' : '3',
|
||||||
|
'id' : 'checklist-three',
|
||||||
|
'completed' : false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
daily.checklist = checklist
|
||||||
|
daily.completed = true
|
||||||
|
weekly.checklist = checklist
|
||||||
|
weekly.completed = true
|
||||||
|
cron(user)
|
||||||
|
|
||||||
|
_.each daily.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
_.each weekly.checklist, (box)->
|
||||||
|
expect(box.completed).to.be false
|
||||||
|
|
||||||
|
describe 'daily that repeats every x days', ->
|
||||||
|
user = null
|
||||||
|
daily = null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
user = newUser()
|
||||||
|
user.dailys = [ shared.taskDefaults({type:'daily', startDate: moment(), frequency: 'daily'}) ]
|
||||||
|
daily = user.dailys[0]
|
||||||
|
|
||||||
|
_.times 11, (due) ->
|
||||||
|
|
||||||
|
it 'where x equals ' + due, ->
|
||||||
|
daily.everyX = due
|
||||||
|
|
||||||
|
_.times 30, (day) ->
|
||||||
|
isDue = shared.shouldDo moment().add(day, 'days'), daily
|
||||||
|
expect(isDue).to.be true if day % due == 0
|
||||||
|
expect(isDue).to.be false if day % due != 0
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
padding: 1em;
|
padding: 1em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
.formatting-help
|
.slight-vertical-padding
|
||||||
clear: both
|
clear: both
|
||||||
padding-top: 0.618em
|
padding-top: 0.618em
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ for $stage in $stages
|
|||||||
.color-{$stage[0]}:not(.completed)
|
.color-{$stage[0]}:not(.completed)
|
||||||
background-color: $stage[1]
|
background-color: $stage[1]
|
||||||
border: 1px solid shade($stage[1],10%)
|
border: 1px solid shade($stage[1],10%)
|
||||||
.priority-multiplier, .task-attributes, .repeat-days
|
.priority-multiplier, .task-attributes, .repeat-days, .repeat-frequency
|
||||||
li
|
li
|
||||||
hrpg-button-color-mixin($stage[1])
|
hrpg-button-color-mixin($stage[1])
|
||||||
button
|
button
|
||||||
@@ -63,7 +63,7 @@ for $stage in $stages
|
|||||||
color: darken($completed,30%)
|
color: darken($completed,30%)
|
||||||
background-color: $completed
|
background-color: $completed
|
||||||
border: 1px solid shade($completed,10%)
|
border: 1px solid shade($completed,10%)
|
||||||
.priority-multiplier, .task-attributes, .repeat-days
|
.priority-multiplier, .task-attributes, .repeat-days, .repeat-frequency
|
||||||
li
|
li
|
||||||
hrpg-button-color-mixin($completed)
|
hrpg-button-color-mixin($completed)
|
||||||
button
|
button
|
||||||
@@ -410,6 +410,10 @@ form
|
|||||||
padding: 0 0 1em
|
padding: 0 0 1em
|
||||||
margin-bottom: 1em
|
margin-bottom: 1em
|
||||||
|
|
||||||
|
button.advanced-options-toggle
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
background: none;
|
||||||
.option-title
|
.option-title
|
||||||
font-size: 1em
|
font-size: 1em
|
||||||
margin: 0 0 0.5em
|
margin: 0 0 0.5em
|
||||||
@@ -507,7 +511,7 @@ form
|
|||||||
|
|
||||||
form
|
form
|
||||||
padding-bottom: 1em
|
padding-bottom: 1em
|
||||||
.priority-multiplier, .task-attributes, .repeat-days
|
.priority-multiplier, .task-attributes, .repeat-days, .repeat-frequency
|
||||||
text-align: center
|
text-align: center
|
||||||
li
|
li
|
||||||
@extend $hrpg-button
|
@extend $hrpg-button
|
||||||
@@ -517,6 +521,7 @@ form
|
|||||||
&:last-of-type
|
&:last-of-type
|
||||||
margin-right: 0
|
margin-right: 0
|
||||||
.repeat-days
|
.repeat-days
|
||||||
|
padding-bottom: 1em
|
||||||
li
|
li
|
||||||
button
|
button
|
||||||
min-width: 2.5em
|
min-width: 2.5em
|
||||||
@@ -524,6 +529,11 @@ form
|
|||||||
text-align: center
|
text-align: center
|
||||||
@extend $hrpg-button
|
@extend $hrpg-button
|
||||||
|
|
||||||
|
// Dailies
|
||||||
|
.dailies
|
||||||
|
.repeat-weekly
|
||||||
|
padding-bottom: 1em
|
||||||
|
|
||||||
// Habits – task button styles (+ -)
|
// Habits – task button styles (+ -)
|
||||||
.habits
|
.habits
|
||||||
.task-actions
|
.task-actions
|
||||||
|
|||||||
BIN
website/public/emails/images/PROMO-Enchanted-Armoire-v1.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
@@ -4,6 +4,7 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
|
|||||||
function($scope, $rootScope, $location, User, Notification, $http, ApiUrl, $timeout, Shared, Guide) {
|
function($scope, $rootScope, $location, User, Notification, $http, ApiUrl, $timeout, Shared, Guide) {
|
||||||
$scope.obj = User.user; // used for task-lists
|
$scope.obj = User.user; // used for task-lists
|
||||||
$scope.user = User.user;
|
$scope.user = User.user;
|
||||||
|
|
||||||
$scope.armoireCount = function(gear) {
|
$scope.armoireCount = function(gear) {
|
||||||
return Shared.countArmoire(gear);
|
return Shared.countArmoire(gear);
|
||||||
};
|
};
|
||||||
@@ -131,6 +132,19 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
|
|||||||
*/
|
*/
|
||||||
$scope._today = moment().add({days: 1});
|
$scope._today = moment().add({days: 1});
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------
|
||||||
|
Dailies
|
||||||
|
------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
$scope.openDatePicker = function($event, task) {
|
||||||
|
$event.preventDefault();
|
||||||
|
$event.stopPropagation();
|
||||||
|
|
||||||
|
task._isDatePickerOpen = !task._isDatePickerOpen;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------
|
------------------------
|
||||||
Checklists
|
Checklists
|
||||||
@@ -216,7 +230,7 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N
|
|||||||
$scope.shouldShow = function(task, list, prefs){
|
$scope.shouldShow = function(task, list, prefs){
|
||||||
if (task._editing) // never hide a task while being edited
|
if (task._editing) // never hide a task while being edited
|
||||||
return true;
|
return true;
|
||||||
var shouldDo = task.type == 'daily' ? habitrpgShared.shouldDo(new Date, task.repeat, prefs) : true;
|
var shouldDo = task.type == 'daily' ? habitrpgShared.shouldDo(new Date, task, prefs) : true;
|
||||||
switch (list.view) {
|
switch (list.view) {
|
||||||
case "yellowred": // Habits
|
case "yellowred": // Habits
|
||||||
return task.value < 1;
|
return task.value < 1;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ var populateQuery = function(type, q, additionalFields){
|
|||||||
q.populate('members', partyFields + (additionalFields ? (' ' + additionalFields) : ''));
|
q.populate('members', partyFields + (additionalFields ? (' ' + additionalFields) : ''));
|
||||||
else
|
else
|
||||||
q.populate(guildPopulate);
|
q.populate(guildPopulate);
|
||||||
|
q.populate('leader', nameFields);
|
||||||
q.populate('invites', nameFields);
|
q.populate('invites', nameFields);
|
||||||
q.populate({
|
q.populate({
|
||||||
path: 'challenges',
|
path: 'challenges',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ var mongoose = require("mongoose");
|
|||||||
var Schema = mongoose.Schema;
|
var Schema = mongoose.Schema;
|
||||||
var shared = require('../../../common');
|
var shared = require('../../../common');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var moment = require('moment');
|
||||||
|
|
||||||
// Task Schema
|
// Task Schema
|
||||||
// -----------
|
// -----------
|
||||||
@@ -51,9 +52,12 @@ var checklist = [{
|
|||||||
var DailySchema = new Schema(
|
var DailySchema = new Schema(
|
||||||
_.defaults({
|
_.defaults({
|
||||||
type: {type: String, 'default': 'daily'},
|
type: {type: String, 'default': 'daily'},
|
||||||
|
frequency: {type: String, 'default': 'weekly', enum: ['daily', 'weekly']},
|
||||||
|
everyX: {type: Number, 'default': 1}, // e.g. once every X weeks
|
||||||
|
startDate: {type: Date, 'default': moment().startOf('day').toDate()},
|
||||||
history: Array,
|
history: Array,
|
||||||
completed: {type: Boolean, 'default': false},
|
completed: {type: Boolean, 'default': false},
|
||||||
repeat: {
|
repeat: { // used only for 'weekly' frequency,
|
||||||
m: {type: Boolean, 'default': true},
|
m: {type: Boolean, 'default': true},
|
||||||
t: {type: Boolean, 'default': true},
|
t: {type: Boolean, 'default': true},
|
||||||
w: {type: Boolean, 'default': true},
|
w: {type: Boolean, 'default': true},
|
||||||
|
|||||||
@@ -459,7 +459,9 @@ UserSchema.pre('save', function(next) {
|
|||||||
newTask.name = newTask.name(self.preferences.language);
|
newTask.name = newTask.name(self.preferences.language);
|
||||||
}else{
|
}else{
|
||||||
newTask.text = newTask.text(self.preferences.language);
|
newTask.text = newTask.text(self.preferences.language);
|
||||||
|
if(newTask.notes) {
|
||||||
newTask.notes = newTask.notes(self.preferences.language);
|
newTask.notes = newTask.notes(self.preferences.language);
|
||||||
|
}
|
||||||
|
|
||||||
if(newTask.checklist){
|
if(newTask.checklist){
|
||||||
newTask.checklist = _.map(newTask.checklist, function(checklistItem){
|
newTask.checklist = _.map(newTask.checklist, function(checklistItem){
|
||||||
|
|||||||
@@ -179,8 +179,11 @@ module.exports.setupConfig = function(){
|
|||||||
baseUrl = nconf.get('BASE_URL');
|
baseUrl = nconf.get('BASE_URL');
|
||||||
|
|
||||||
module.exports.ga = require('universal-analytics')(nconf.get('GA_ID'));
|
module.exports.ga = require('universal-analytics')(nconf.get('GA_ID'));
|
||||||
var mixpanel = require('mixpanel')
|
|
||||||
module.exports.mixpanel = mixpanel.init(nconf.get('MP_ID'));
|
var mixpanel = isProd && require('mixpanel');
|
||||||
|
module.exports.mixpanel = mixpanel
|
||||||
|
? mixpanel.init(nconf.get('MP_ID'))
|
||||||
|
: { track: function() {} };
|
||||||
};
|
};
|
||||||
|
|
||||||
var algorithm = 'aes-256-ctr';
|
var algorithm = 'aes-256-ctr';
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ html(ng-app="habitrpg", ng-controller="RootCtrl", ng-class='{"applying-action":a
|
|||||||
include ./shared/header/menu
|
include ./shared/header/menu
|
||||||
include ./shared/modals/index
|
include ./shared/modals/index
|
||||||
include ./shared/header/header
|
include ./shared/header/header
|
||||||
include ./shared/tasks/lists
|
include ./shared/tasks/index
|
||||||
include ./main/index
|
include ./main/index
|
||||||
include ./options/index
|
include ./options/index
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
span.glyphicon.glyphicon-ban-circle
|
span.glyphicon.glyphicon-ban-circle
|
||||||
=env.t('leave')
|
=env.t('leave')
|
||||||
a.btn.btn-success.pull-right(ng-if=':: !isMemberOfGroup(User.user._id, group)', ng-click='join(group)')=env.t('join')
|
a.btn.btn-success.pull-right(ng-if=':: !isMemberOfGroup(User.user._id, group)', ng-click='join(group)')=env.t('join')
|
||||||
span(ng-if='group.leader == user.id')
|
span(ng-if='group.leader._id == user.id')
|
||||||
button.btn.btn-sm.btn-primary.pull-right(ng-click='save(group)', ng-show='group._editing')=env.t('save')
|
button.btn.btn-sm.btn-primary.pull-right(ng-click='save(group)', ng-show='group._editing')=env.t('save')
|
||||||
button.btn.btn-sm.btn-default.pull-right(ng-click='group._editing = true', ng-hide='group._editing')=env.t('editGroup')
|
button.btn.btn-sm.btn-default.pull-right(ng-click='group._editing = true', ng-hide='group._editing')=env.t('editGroup')
|
||||||
|
|
||||||
@@ -51,7 +51,13 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
img.pull-right(ng-show='group.logo', ng-src='{{group.logo}}')
|
img.pull-right(ng-show='group.logo', ng-src='{{group.logo}}')
|
||||||
markdown(text='group.description')
|
markdown(text='group.description')
|
||||||
hr
|
hr
|
||||||
small.muted Group ID: {{group._id}}
|
p=env.t('groupLeader')
|
||||||
|
|:
|
||||||
|
a(class='badge badge-info', ng-click='clickMember(group.leader._id, true)')
|
||||||
|
| {{group.leader.profile.name}}
|
||||||
|
.slight-vertical-padding
|
||||||
|
small.muted=env.t('groupID')
|
||||||
|
|: {{group._id}}
|
||||||
|
|
||||||
include ./challenge-box
|
include ./challenge-box
|
||||||
|
|
||||||
@@ -78,14 +84,14 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
ng-change='set({"party.orderAscending": user.party.orderAscending})'
|
ng-change='set({"party.orderAscending": user.party.orderAscending})'
|
||||||
)
|
)
|
||||||
table.table.table-striped(bindonce='group')
|
table.table.table-striped(bindonce='group')
|
||||||
tr(ng-repeat='member in group.members track by member._id')
|
tr(ng-repeat='member in group.members track by member._id' ng-if='member._id != group.leader._id')
|
||||||
td.media
|
td.media
|
||||||
// allow leaders to ban members
|
// allow leaders to ban members
|
||||||
div.pull-left(ng-show='group.leader == user.id && user.id!=member._id')
|
div.pull-left(ng-show='group.leader._id == user.id')
|
||||||
a.media-object(ng-click='removeMember(group, member, true)')
|
a.media-object(ng-click='removeMember(group, member, true)')
|
||||||
span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip'))
|
span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip'))
|
||||||
a.media-body
|
a.media-body
|
||||||
span(ng-class='{"badge badge-info": group.leader==member._id}', ng-click='clickMember(member._id, true)')
|
span(ng-click='clickMember(member._id, true)')
|
||||||
| {{member.profile.name}}
|
| {{member.profile.name}}
|
||||||
tr(ng-if='group.memberCount > group.members.length')
|
tr(ng-if='group.memberCount > group.members.length')
|
||||||
td
|
td
|
||||||
@@ -98,7 +104,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
tr(ng-repeat='invite in group.invites')
|
tr(ng-repeat='invite in group.invites')
|
||||||
td.media
|
td.media
|
||||||
// allow leaders to ban members
|
// allow leaders to ban members
|
||||||
div.pull-left(ng-show='group.leader == user.id')
|
div.pull-left(ng-show='group.leader._id == user.id')
|
||||||
a.media-object(ng-click='removeMember(group, invite, false)')
|
a.media-object(ng-click='removeMember(group, invite, false)')
|
||||||
span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip'))
|
span.glyphicon.glyphicon-ban-circle(tooltip=env.t('banTip'))
|
||||||
a.media-body
|
a.media-body
|
||||||
@@ -117,7 +123,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
td
|
td
|
||||||
.popover.static-popover.fade.right.in.wide-popover
|
.popover.static-popover.fade.right.in.wide-popover
|
||||||
.arrow
|
.arrow
|
||||||
h3.popover-title {{Members.members[group.leader].profile.name}}
|
h3.popover-title {{group.leader.profile.name}}
|
||||||
.popover-content
|
.popover-content
|
||||||
markdown(text='group.leaderMessage')
|
markdown(text='group.leaderMessage')
|
||||||
div(ng-controller='ChatCtrl')
|
div(ng-controller='ChatCtrl')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
small.btn-link(ng-init='showHelp = false', ng-click='showHelp = !showHelp')
|
small.btn-link(ng-init='showHelp = false', ng-click='showHelp = !showHelp')
|
||||||
| {{showHelp ? env.t('hideFormattingHelp') : env.t('showFormattingHelp')}}
|
| {{showHelp ? env.t('hideFormattingHelp') : env.t('showFormattingHelp')}}
|
||||||
|
|
||||||
.formatting-help(ng-if='showHelp')
|
.slight-vertical-padding(ng-if='showHelp')
|
||||||
table.table.table-striped
|
table.table.table-striped
|
||||||
tr.info
|
tr.info
|
||||||
td.col-xs-6 #[b=env.t('youType')]
|
td.col-xs-6 #[b=env.t('youType')]
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ script(type='text/ng-template', id='modals/chooseClass.html')
|
|||||||
.well(ng-show='selectedClass=="healer"')=env.t('healerText')
|
.well(ng-show='selectedClass=="healer"')=env.t('healerText')
|
||||||
|
|
||||||
.modal-footer
|
.modal-footer
|
||||||
button.btn.btn-danger(ng-click='user.ops.disableClasses({}); $close()', popover-placement='top', popover-trigger='mouseenter', popover=env.t('optOutText'))=env.t('optOut')
|
span(popover-placement='left', popover-trigger='mouseenter', popover=env.t('optOutText'))
|
||||||
|
button.btn.btn-danger(ng-click='user.ops.disableClasses({}); $close()')=env.t('optOut')
|
||||||
button.btn.btn-primary(ng-disabled='!selectedClass' ng-click='changeClass(selectedClass); $close()')=env.t('select')
|
button.btn.btn-primary(ng-disabled='!selectedClass' ng-click='changeClass(selectedClass); $close()')=env.t('select')
|
||||||
.pull-left!=env.t('chooseClassLearn')
|
.pull-left!=env.t('chooseClassLearn')
|
||||||
|
|||||||
@@ -1,5 +1,43 @@
|
|||||||
h5 6/1/2015 - NEW EQUIPMENT: THE ENCHANTED ARMOIRE, JUNE BACKGROUNDS, AND NEW MOUNT POSITIONING!
|
h5 6/11/2015 - REPEATING TASKS, START DATE, AND MOBILE APP UPDATES!
|
||||||
|
p
|
||||||
|
br
|
||||||
|
p.small.muted by Blade and fallenpanda
|
||||||
hr
|
hr
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
h5 New Repeat Option for Dailies
|
||||||
|
p Dailies now have a new Advanced Option: Repeat Every X Days. You've wanted this feature for a long time, and it's finally here!
|
||||||
|
br
|
||||||
|
p First, please note that this new option is OPT-IN only. We won't make any changes to your preexisting Dailies without you knowing it. We wouldn't do that!
|
||||||
|
br
|
||||||
|
p That being said, here are the new features:
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
h5 Repeating Tasks
|
||||||
|
p Use the "Every X Days" function under Dailies Advanced Options to create tasks that repeat after a certain number of days have passed, whether every 2 days, every 15 days, every 30 days... You choose the number that works for you!
|
||||||
|
br
|
||||||
|
p These Dailies are only due on those given dates. Need to pay your rent every 30 days? Take medicine every other day? Water your plants every 4 days? No longer a problem.
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
h5 Start Date
|
||||||
|
p Dailies now have a Start Date. They will not be due before this date. This means that if you want to add a new Daily while you're thinking about it, but not have it be due until later, you can achieve that by setting a future Start Date!
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
h5 Mobile App Updates
|
||||||
|
p New <a href='https://play.google.com/store/apps/details?id=com.ocdevel.habitrpg' target='_blank'>Android</a> and <a href='https://itunes.apple.com/us/app/habitrpg/id689569235?mt=8' target='_blank'>iOS</a> updates are available to support this feature. Please, update your apps before using it, or the new repeating Dailies will not display normally on the mobile apps!
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
h5 Other Notes
|
||||||
|
p For a short period of time, the <a href='http://data.habitrpg.com' target='_blank'>Data Display Tool</a> will not be able to calculate damage correctly for Repeat Every X Dailies. We'll get that updated very soon so that it will be accurate again!
|
||||||
|
br
|
||||||
|
p If you still have questions about Repeat Every X Dailies, don't hesitate to ask in <a href='/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>the Newbies Guild</a>!
|
||||||
|
|
||||||
|
hr
|
||||||
|
a(href='/static/old-news', target='_blank') Read older news
|
||||||
|
|
||||||
|
mixin oldNews
|
||||||
|
|
||||||
|
h5 6/1/2015 - NEW EQUIPMENT: THE ENCHANTED ARMOIRE, JUNE BACKGROUNDS, AND NEW MOUNT POSITIONING!
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
.promo_enchanted_armoire.pull-right
|
.promo_enchanted_armoire.pull-right
|
||||||
@@ -22,12 +60,6 @@ h5 6/1/2015 - NEW EQUIPMENT: THE ENCHANTED ARMOIRE, JUNE BACKGROUNDS, AND NEW MO
|
|||||||
h5 New Mount Positioning!
|
h5 New Mount Positioning!
|
||||||
p The mount positioning has been fixed for all the base mounts where it looked like the avatar was riding extreme sidesaddle. Now avatars sit properly, no longer clinging to the sides of their mounts for dear life.
|
p The mount positioning has been fixed for all the base mounts where it looked like the avatar was riding extreme sidesaddle. Now avatars sit properly, no longer clinging to the sides of their mounts for dear life.
|
||||||
p.small.muted by Kiwibot, Lemoness, and SabreCat
|
p.small.muted by Kiwibot, Lemoness, and SabreCat
|
||||||
|
|
||||||
hr
|
|
||||||
a(href='/static/old-news', target='_blank') Read older news
|
|
||||||
|
|
||||||
mixin oldNews
|
|
||||||
|
|
||||||
h5 6/1/2015 - JUNE MYSTERY ITEM!
|
h5 6/1/2015 - JUNE MYSTERY ITEM!
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
|
|||||||
70
website/views/shared/tasks/edit/advanced_options.jade
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
div(ng-if='::task.type!="reward"')
|
||||||
|
button.advanced-options-toggle.option-title.mega(type='button',
|
||||||
|
ng-click='task._advanced = !task._advanced', tooltip=env.t('expandCollapse'))
|
||||||
|
=env.t('advancedOptions')
|
||||||
|
|
||||||
|
div(ng-show='task._advanced')
|
||||||
|
div(ng-if='::task.type == "daily"')
|
||||||
|
.form-group
|
||||||
|
legend.option-title
|
||||||
|
span.hint(popover-title=env.t('startDateHelpTitle'), popover=env.t("startDateHelp"), popover-trigger='mouseenter')
|
||||||
|
=env.t('startDate')
|
||||||
|
|
||||||
|
input.form-control(type='text', ng-model='task.startDate',
|
||||||
|
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
||||||
|
ng-click='datepickerOpened = true')
|
||||||
|
|
||||||
|
hr
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
legend.option-title=env.t('repeat')
|
||||||
|
select.form-control(ng-model='task.frequency')
|
||||||
|
option(value='weekly')=env.t('repeatWeek')
|
||||||
|
option(value='daily')=env.t('repeatDays')
|
||||||
|
|
||||||
|
include ./dailies/repeat_options
|
||||||
|
|
||||||
|
hr
|
||||||
|
|
||||||
|
fieldset.option-group.advanced-option(ng-show="task._advanced")
|
||||||
|
|
||||||
|
legend.option-title
|
||||||
|
a.hint.priority-multiplier-help(href='http://habitrpg.wikia.com/wiki/Difficulty', target='_blank', popover-title=env.t('difficultyHelpTitle'), popover-trigger='mouseenter', popover=env.t('difficultyHelpContent'))=env.t('difficulty')
|
||||||
|
ul.priority-multiplier
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.priority==1 || !task.priority}',
|
||||||
|
ng-click='task.challenge.id || (task.priority=1)')
|
||||||
|
=env.t('easy')
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.priority==1.5}',
|
||||||
|
ng-click='task.challenge.id || (task.priority=1.5)')
|
||||||
|
=env.t('medium')
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.priority==2}',
|
||||||
|
ng-click='task.challenge.id || (task.priority=2)')
|
||||||
|
=env.t('hard')
|
||||||
|
|
||||||
|
span(ng-if='task.type=="daily"')
|
||||||
|
legend.option-title.pull-left=env.t('restoreStreak')
|
||||||
|
input.option-content(type='number', ng-model='task.streak')
|
||||||
|
|
||||||
|
div(ng-if='::(user.preferences.allocationMode == "taskbased" && user.preferences.automaticAllocation) || $state.is("options.social.challenges")')
|
||||||
|
legend.option-title.pull-left=env.t('attributes')
|
||||||
|
ul.task-attributes
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.attribute=="str"}',
|
||||||
|
ng-click='task.attribute="str"')
|
||||||
|
=env.t('physical')
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.attribute=="int"}',
|
||||||
|
ng-click='task.attribute="int"')
|
||||||
|
=env.t('mental')
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.attribute=="con"}',
|
||||||
|
ng-click='task.attribute="con"')
|
||||||
|
=env.t('social')
|
||||||
|
li
|
||||||
|
button(type='button', ng-class='{active: task.attribute=="per"}',
|
||||||
|
ng-click='task.attribute="per"',
|
||||||
|
popover=env.t('otherExamples'), popover-trigger='mouseenter', popover-placement='top')
|
||||||
|
=env.t('other')
|
||||||
22
website/views/shared/tasks/edit/checklist.jade
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
.task-checklist-edit(ng-if='!$state.includes("options.social.challenges")')
|
||||||
|
ul
|
||||||
|
li
|
||||||
|
button(type='button', ng-if='!task.checklist[0] && (task.type=="daily" || task.type=="todo")',
|
||||||
|
ng-click='addChecklist(task)')
|
||||||
|
span.glyphicon.glyphicon-tasks
|
||||||
|
span=env.t('addChecklist')
|
||||||
|
|
||||||
|
form.checklist-form(ng-if='task.checklist')
|
||||||
|
fieldset.option-group(ng-if='!$state.includes("options.social.challenges")')
|
||||||
|
legend.option-title
|
||||||
|
span.hint(popover=env.t('checklistText'), popover-trigger='mouseenter', popover-placement='bottom')
|
||||||
|
=env.t('checklist')
|
||||||
|
ul(hrpg-sort-checklist)
|
||||||
|
li(ng-repeat='item in task.checklist')
|
||||||
|
//input(type='checkbox',ng-model='item.completed',ng-change='saveTask(task,true)')
|
||||||
|
//-,ng-blur='saveTask(task,true)')
|
||||||
|
span.checklist-icon.glyphicon.glyphicon-resize-vertical
|
||||||
|
input(type='text', ng-model='item.text',
|
||||||
|
ui-keyup="{'13':'addChecklistItem(task,$event,$index)','38 40':'navigateChecklist(task,$index,$event)'}")
|
||||||
|
a(ng-click='removeChecklistItem(task,$event,$index,true)')
|
||||||
|
span.glyphicon.glyphicon-trash(tooltip=env.t('delete'))
|
||||||
3
website/views/shared/tasks/edit/dailies/calendar.jade
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fieldset.option-group.calendar(ng-if='::task.type=="daily"', class="option-group")
|
||||||
|
.dailies
|
||||||
|
include ./repeat_options
|
||||||
26
website/views/shared/tasks/edit/dailies/repeat_options.jade
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
legend.option-title=env.t('repeatEvery')
|
||||||
|
|
||||||
|
// If frequency is daily
|
||||||
|
ng-form.form-group(name='everyX' ng-if='task.frequency=="daily"')
|
||||||
|
.input-group
|
||||||
|
input.form-control(type='number', ng-model='task.everyX', min='0', required)
|
||||||
|
span.input-group-addon {{task.everyX == 1 ? env.t('day') : env.t('days')}}
|
||||||
|
|
||||||
|
// If frequency is weekly
|
||||||
|
.form-group(ng-if='task.frequency=="weekly"')
|
||||||
|
ul.repeat-days
|
||||||
|
// note, does not use data-toggle="buttons-checkbox" - it would interfere with our own click binding
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.su}', type='button', ng-click='task.challenge.id || (task.repeat.su = !task.repeat.su)') {{::moment.weekdaysMin(0)}}
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.m}', type='button', ng-click='task.challenge.id || (task.repeat.m = !task.repeat.m)') {{::moment.weekdaysMin(1)}}
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.t}', type='button', ng-click='task.challenge.id || (task.repeat.t = !task.repeat.t)') {{::moment.weekdaysMin(2)}}
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.w}', type='button', ng-click='task.challenge.id || (task.repeat.w = !task.repeat.w)') {{::moment.weekdaysMin(3)}}
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.th}', type='button', ng-click='task.challenge.id || (task.repeat.th = !task.repeat.th)') {{::moment.weekdaysMin(4)}}
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.f}', type='button', ng-click='task.challenge.id || (task.repeat.f= !task.repeat.f)') {{::moment.weekdaysMin(5)}}
|
||||||
|
li
|
||||||
|
button(ng-class='{active: task.repeat.s}', type='button', ng-click='task.challenge.id || (task.repeat.s = !task.repeat.s)') {{::moment.weekdaysMin(6)}}
|
||||||
8
website/views/shared/tasks/edit/habits/plus_minus.jade
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fieldset.option-group.plusminus(ng-if='task.type=="habit" && !task.challenge.id')
|
||||||
|
legend.option-title=env.t('direction/Actions')
|
||||||
|
span.task-checker
|
||||||
|
input.visuallyhidden.focusable(id='{{obj._id}}_{{task.id}}-option-plus', type='checkbox', ng-model='task.up')
|
||||||
|
label(for='{{obj._id}}_{{task.id}}-option-plus')
|
||||||
|
span.task-checker
|
||||||
|
input.visuallyhidden.focusable(id='{{obj._id}}_{{task.id}}-option-minus', type='checkbox', ng-model='task.down')
|
||||||
|
label(for='{{obj._id}}_{{task.id}}-option-minus')
|
||||||
52
website/views/shared/tasks/edit/index.jade
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
div(ng-if='task._editing')
|
||||||
|
.task-options
|
||||||
|
|
||||||
|
// Broken Challenge
|
||||||
|
.well(ng-if='task.challenge.broken')
|
||||||
|
div(ng-if='task.challenge.broken=="TASK_DELETED"')
|
||||||
|
p=env.t('brokenTask')
|
||||||
|
p
|
||||||
|
a(ng-click='unlink(task, "keep")')=env.t('keepIt')
|
||||||
|
|
|
||||||
|
a(ng-click="removeTask(task, obj[list.type+'s'])")=env.t('removeIt')
|
||||||
|
div(ng-if='task.challenge.broken=="CHALLENGE_DELETED"')
|
||||||
|
p
|
||||||
|
|
|
||||||
|
=env.t('brokenChallenge')
|
||||||
|
p
|
||||||
|
a(ng-click='unlink(task, "keep-all")')=env.t('keepThem')
|
||||||
|
| |
|
||||||
|
a(ng-click='unlink(task, "remove-all")')=env.t('removeThem')
|
||||||
|
div(ng-if='task.challenge.broken=="CHALLENGE_CLOSED"')
|
||||||
|
p
|
||||||
|
!=env.t('challengeCompleted', {user: "{{task.challenge.winner}}"})
|
||||||
|
p
|
||||||
|
a(ng-click='unlink(task, "keep-all")')=env.t('keepThem')
|
||||||
|
| |
|
||||||
|
a(ng-click='unlink(task, "remove-all")')=env.t('removeThem')
|
||||||
|
//div(ng-if='task.challenge.broken=="UNSUBSCRIBED"')
|
||||||
|
p=env.t('unsubChallenge')
|
||||||
|
p
|
||||||
|
a(ng-click="unlink(task, 'keep-all')")=env.t('keepThem')
|
||||||
|
| |
|
||||||
|
a(ng-click="unlink(task, 'remove-all')")=env.t('removeThem')
|
||||||
|
|
||||||
|
include ./checklist
|
||||||
|
|
||||||
|
form(ng-submit='saveTask(task,false,true)')
|
||||||
|
include ./text_notes
|
||||||
|
|
||||||
|
include ./habits/plus_minus
|
||||||
|
|
||||||
|
include ./dailies/calendar
|
||||||
|
|
||||||
|
include ./rewards/pricing
|
||||||
|
|
||||||
|
include ./todos/due_date
|
||||||
|
|
||||||
|
include ./tags
|
||||||
|
|
||||||
|
include ./advanced_options
|
||||||
|
|
||||||
|
.save-close
|
||||||
|
button(type='submit')=env.t('saveAndClose')
|
||||||
5
website/views/shared/tasks/edit/rewards/pricing.jade
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
fieldset.option-group.option-short(ng-if='task.type=="reward" && !task.challenge.id')
|
||||||
|
legend.option-title=env.t('price')
|
||||||
|
input.option-content(type='number', size='16', min='0', step='any', ng-model='task.value', required)
|
||||||
|
.money.input-suffix
|
||||||
|
span.shop_gold
|
||||||
5
website/views/shared/tasks/edit/tags.jade
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
fieldset.option-group(ng-if='!$state.includes("options.social.challenges")')
|
||||||
|
p.option-title.mega(ng-click='task._tags = !task._tags', tooltip=env.t('expandCollapse'))=env.t('tags')
|
||||||
|
label.checkbox(ng-repeat='tag in user.tags', ng-class="{visuallyhidden: task._tags}")
|
||||||
|
input(type='checkbox', ng-model='task.tags[tag.id]')
|
||||||
|
markdown(text='tag.name')
|
||||||
6
website/views/shared/tasks/edit/text_notes.jade
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
fieldset.option-group
|
||||||
|
label.option-title=env.t('text')
|
||||||
|
input.option-content(type='text', ng-model='task.text', required, ng-disabled='task.challenge.id')
|
||||||
|
|
||||||
|
label.option-title=env.t('extraNotes')
|
||||||
|
textarea.option-content(rows='3', ng-model='task.notes', ng-model-options="{debounce: 1000}")
|
||||||
6
website/views/shared/tasks/edit/todos/due_date.jade
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
fieldset.option-group(ng-if='task.type=="todo" && !task.challenge.id')
|
||||||
|
legend.option-title=env.t('dueDate')
|
||||||
|
input.option-content.datepicker(type='text', ng-model='task.date',
|
||||||
|
datepicker-popup='{{::user.preferences.dateFormat}}', is-open='datepickerOpened',
|
||||||
|
ng-click='datepickerOpened = true')
|
||||||
|
|
||||||
39
website/views/shared/tasks/index.jade
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Note here, we need this part of Habit to be a directive since we're going to be passing it variables from various
|
||||||
|
// parts of the app. The alternative would be to create new scopes for different containing sections, but that
|
||||||
|
// started to get unwieldy
|
||||||
|
|
||||||
|
include ./task_view/mixins
|
||||||
|
script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
||||||
|
.tasks-lists.container-fluid
|
||||||
|
.row
|
||||||
|
.col-md-3.col-sm-6(ng-repeat='list in lists', ng-class='::{"rewards-module": list.type==="reward"}')
|
||||||
|
.task-column(class='{{::list.type}}s')
|
||||||
|
|
||||||
|
include ./task_view/graph
|
||||||
|
|
||||||
|
h2.task-column_title {{::list.header}}
|
||||||
|
|
||||||
|
include ./task_view/help
|
||||||
|
|
||||||
|
.todos-chart(ng-if='::list.type == "todo"', ng-show='charts.todos')
|
||||||
|
|
||||||
|
include ./task_view/add_new
|
||||||
|
|
||||||
|
alert.alert-warning.dailiesRestingInInn(ng-if='::list.type == "daily" && user.preferences.sleep')
|
||||||
|
i.glyphicon.glyphicon-warning-sign
|
||||||
|
=env.t('dailiesRestingInInn')
|
||||||
|
|
||||||
|
+taskColumnTabs('top')
|
||||||
|
|
||||||
|
// Actual List
|
||||||
|
ul(class='{{::list.type}}s main-list', ng-show='obj[list.type + "s"].length > 0', hrpg-sort-tasks, ng-if='!$state.includes("options.social.challenges")')
|
||||||
|
include ./task
|
||||||
|
//Loads the non-sortable lists for challenges
|
||||||
|
ul(class='{{::list.type}}s main-list', ng-show='obj[list.type + "s"].length > 0', ng-if='$state.includes("options.social.challenges")')
|
||||||
|
include ./task
|
||||||
|
|
||||||
|
include ./task_view/static_rewards
|
||||||
|
|
||||||
|
include ./task_view/spells
|
||||||
|
|
||||||
|
+taskColumnTabs('bottom')
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
// Note here, we need this part of Habit to be a directive since we're going to be passing it variables from various
|
|
||||||
// parts of the app. The alternative would be to create new scopes for different containing sections, but that
|
|
||||||
// started to get unwieldy
|
|
||||||
script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
|
||||||
.tasks-lists.container-fluid
|
|
||||||
.row
|
|
||||||
.col-md-3.col-sm-6(bindonce='lists', ng-repeat='list in lists', ng-class='::{"rewards-module": list.type==="reward"}')
|
|
||||||
.task-column(class='{{list.type}}s')
|
|
||||||
|
|
||||||
// Todos export/graph options
|
|
||||||
span.option-box.pull-right(ng-if='::main')
|
|
||||||
a.option-action(ng-if='list.type=="todo"', ng-show='obj.history.todos', ng-click='toggleChart("todos")', tooltip=env.t('progress'), style='margin-right:5px;')
|
|
||||||
span.glyphicon.glyphicon-signal
|
|
||||||
//a.option-action(ng-href='/v1/users/{{user.id}}/calendar.ics?apiToken={{user.apiToken}}', tooltip='iCal')
|
|
||||||
//-a.option-action(ng-if='list.type=="todo"', ng-click='notPorted()', tooltip='iCal', ng-show='false')
|
|
||||||
span.glyphicon.glyphicon-calendar
|
|
||||||
// <a href="https://www.google.com/calendar/render?cid={{encodeiCalLink(_user.id, _user.apiToken)}}" rel=tooltip title="Google Calendar"><i class=icon-calendar></i></a>
|
|
||||||
a.option-action(ng-click='list.help=!list.help', tooltip='Click for help')
|
|
||||||
span.glyphicon.glyphicon-question-sign(style={'zoom':1.5,'vertical-align':'-webkit-baseline-middle'})
|
|
||||||
|
|
||||||
// Header
|
|
||||||
h2.task-column_title
|
|
||||||
| {{list.header}}
|
|
||||||
|
|
||||||
div(ng-if='list.help', ng-switch='::list.type')
|
|
||||||
div(ng-switch-when='habit')
|
|
||||||
ul
|
|
||||||
li!=env.t('habitHelp1', {plusIcon:"<span class='glyphicon glyphicon-plus'></span>"})
|
|
||||||
li!=env.t('habitHelp2', {minusIcon:"<span class='glyphicon glyphicon-minus'></span>"})
|
|
||||||
li!=env.t('habitHelp3')
|
|
||||||
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
|
||||||
div(ng-switch-when='daily')
|
|
||||||
ul
|
|
||||||
li!=env.t('dailyHelp1', {emphasisStart:"<strong>", emphasisEnd:"</strong>", pencilIcon:"<span class='glyphicon glyphicon-pencil'></span>"})
|
|
||||||
li!=env.t('dailyHelp2')
|
|
||||||
li!=env.t('dailyHelp3', {emphasisStart:"<strong>", emphasisEnd:"</strong>"})
|
|
||||||
li!=env.t('dailyHelp4', {linkStart:"<a href='/#/options/settings/settings' target='_blank'>", linkEnd:"</a>"})
|
|
||||||
li!=env.t('dailyHelp5')
|
|
||||||
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
|
||||||
div(ng-switch-when='todo')
|
|
||||||
ul
|
|
||||||
li!=env.t('toDoHelp1')
|
|
||||||
li!=env.t('toDoHelp2')
|
|
||||||
li!=env.t('toDoHelp3')
|
|
||||||
li!=env.t('toDoHelp4')
|
|
||||||
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
|
||||||
div(ng-switch-when='reward')
|
|
||||||
ul
|
|
||||||
li!=env.t('rewardHelp1', {linkStart:"<a href='/#/options/inventory/equipment' target='_blank'>", linkEnd: "</a>"})
|
|
||||||
li!=env.t('rewardHelp2', {linkStart:"<a href='/#/options/profile/stats' target='_blank'>", linkEnd: "</a>"})
|
|
||||||
li!=env.t('rewardHelp3')
|
|
||||||
li!=env.t('rewardHelp4')
|
|
||||||
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
|
||||||
|
|
||||||
// Todo Chart
|
|
||||||
.todos-chart(ng-if='::list.type == "todo"', ng-show='charts.todos')
|
|
||||||
|
|
||||||
// Add New
|
|
||||||
form.task-add(name='new{{list.type}}form', ng-hide='obj._locked', ng-submit='addTask(obj[list.type+"s"],list)' novalidate)
|
|
||||||
textarea(rows='6', task-focus='list.bulk && list.focus', ng-model='list.newTask', placeholder='{{list.placeHolderBulk}}', ng-if='list.bulk', ui-keydown='{"meta-enter ctrl-enter":"addTask(obj[list.type+\'s\'],list)"}', required)
|
|
||||||
input(type='text', task-focus='!list.bulk && list.focus', ng-model='list.newTask', placeholder='{{list.placeHolder}}', ng-if='!list.bulk', required)
|
|
||||||
button(type='submit', ng-disabled='new{{list.type}}form.$invalid')
|
|
||||||
div.empty-task-notification( ng-show='new{{list.type}}form.$invalid', tooltip=env.t("emptyTask") )
|
|
||||||
span.glyphicon.glyphicon-plus
|
|
||||||
span.glyphicon.glyphicon-plus(ng-show='!new{{list.type}}form.$invalid')
|
|
||||||
small.help-block.btn-link.pull-right(ng-click='toggleBulk(list)')
|
|
||||||
span(ng-if='!list.bulk')=env.t('addmultiple')
|
|
||||||
span(ng-if='list.bulk')=env.t('addsingle')
|
|
||||||
|
|
||||||
alert.alert-warning.dailiesRestingInInn(ng-if='::list.type == "daily" && user.preferences.sleep')
|
|
||||||
i.glyphicon.glyphicon-warning-sign
|
|
||||||
=env.t('dailiesRestingInInn')
|
|
||||||
|
|
||||||
mixin taskColumnTabs(position)
|
|
||||||
// Habits Tabs
|
|
||||||
div(ng-if='::main && list.type=="habit"', class='tabbable tabs-below')
|
|
||||||
ul.task-filter
|
|
||||||
li(ng-class='{active: list.view == "all"}')
|
|
||||||
a(ng-click='list.view = "all"')=env.t('all')
|
|
||||||
li(ng-class='{active: list.view == "yellowred"}')
|
|
||||||
a(ng-click='list.view = "yellowred"')=env.t('yellowred')
|
|
||||||
li(ng-class='{active: list.view == "greenblue"}')
|
|
||||||
a(ng-click='list.view = "greenblue"')=env.t('greenblue')
|
|
||||||
// Daily Tabs
|
|
||||||
div(ng-if='::main && list.type=="daily"', class='tabbable tabs-below')
|
|
||||||
// remaining/completed tabs
|
|
||||||
ul.task-filter
|
|
||||||
li(ng-class='{active: list.view == "all"}')
|
|
||||||
a(ng-click='list.view = "all"')=env.t('all')
|
|
||||||
li(ng-class='{active: list.view == "remaining"}')
|
|
||||||
a(ng-click='list.view = "remaining"')=env.t('due')
|
|
||||||
li(ng-class='{active: list.view == "complete"}')
|
|
||||||
a(ng-click='list.view = "complete"')=env.t('grey')
|
|
||||||
// Todo Tabs
|
|
||||||
div(ng-if='::main && list.type=="todo"', ng-class='::{"tabbable tabs-below": list.type=="todo"}')
|
|
||||||
if position=="bottom"
|
|
||||||
div(ng-show='list.view == "complete"')
|
|
||||||
.alert
|
|
||||||
=env.t('lotOfToDos')
|
|
||||||
button.task-action-btn.tile.spacious.bright(ng-click='user.ops.clearCompleted({})',popover=env.t('deleteToDosExplanation'),popover-trigger='mouseenter')=env.t('clearCompleted')
|
|
||||||
p!=env.t('beeminderDeleteWarning')
|
|
||||||
// remaining/completed tabs
|
|
||||||
ul.task-filter
|
|
||||||
li(ng-class='{active: list.view == "remaining"}')
|
|
||||||
a(ng-click='list.view = "remaining"')=env.t('remaining')
|
|
||||||
li(ng-class='{active: list.view == "dated"}')
|
|
||||||
a(ng-click='list.view = "dated"')=env.t('dated')
|
|
||||||
li(ng-class='{active: list.view == "complete"}')
|
|
||||||
a(ng-click='list.view = "complete"')=env.t('complete')
|
|
||||||
// Rewards Tabs
|
|
||||||
div(ng-if='::main && list.type=="reward"', class='tabbable tabs-below')
|
|
||||||
ul.task-filter
|
|
||||||
li(ng-class='{active: list.view == "all"}')
|
|
||||||
a(ng-click='list.view = "all"')=env.t('all')
|
|
||||||
li(ng-class='{active: list.view == "ingamerewards"}')
|
|
||||||
a(ng-click='list.view = "ingamerewards"')=env.t('ingamerewards')
|
|
||||||
|
|
||||||
+taskColumnTabs('top')
|
|
||||||
|
|
||||||
// Actual List
|
|
||||||
ul(class='{{list.type}}s main-list', ng-show='obj[list.type + "s"].length > 0', hrpg-sort-tasks, ng-if='!$state.includes("options.social.challenges")')
|
|
||||||
include ./task
|
|
||||||
//Loads the non-sortable lists for challenges
|
|
||||||
ul(class='{{list.type}}s main-list', ng-show='obj[list.type + "s"].length > 0', ng-if='$state.includes("options.social.challenges")')
|
|
||||||
include ./task
|
|
||||||
|
|
||||||
// Static Rewards
|
|
||||||
ul.items.rewards(ng-if='main && list.type=="reward"')
|
|
||||||
li.task.reward-item(ng-repeat='item in itemStore',popover-trigger='mouseenter', popover-placement='top', popover='{{item.key == "armoire" && !user.flags.armoireEmpty ? env.t("armoireNotesFull") + armoireCount(user.items.gear.owned) : item.notes()}}')
|
|
||||||
// right-hand side control buttons
|
|
||||||
.task-meta-controls
|
|
||||||
span.task-notes
|
|
||||||
span.glyphicon.glyphicon-comment
|
|
||||||
//left-hand size commands
|
|
||||||
.task-controls.task-primary
|
|
||||||
a.money.btn-buy.item-btn(ng-class='{highValue: item.value >= 1000}', ng-click='buy(item)')
|
|
||||||
span.shop_gold
|
|
||||||
span.reward-cost {{item.value}}
|
|
||||||
// main content
|
|
||||||
span(ng-class='::{"shop_{{item.key}} shop-sprite item-img": true}').reward-img
|
|
||||||
p.task-text {{item.text()}}
|
|
||||||
|
|
||||||
// Events
|
|
||||||
ul.items.rewards(ng-if='main && list.type=="reward" && (user.items.special.snowball>0 || user.stats.buffs.snowball || user.items.special.spookDust>0 || user.stats.buffs.spookDust || user.items.special.shinySeed>0 || user.stats.buffs.shinySeed)')
|
|
||||||
|
|
||||||
mixin specialSpell(k,canceler)
|
|
||||||
li.task.reward-item(ng-if='#{canceler ? "user.stats.buffs."+canceler : "user.items.special."+k+">0"}',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.#{k}.notes()}}')
|
|
||||||
.task-meta-controls
|
|
||||||
span.task-notes
|
|
||||||
span.glyphicon.glyphicon-comment
|
|
||||||
//left-hand size commands
|
|
||||||
.task-controls.task-primary
|
|
||||||
a.money.btn-buy.item-btn(ng-click='castStart(Content.spells.special.#{k})', ng-class='{active: Content.spells.special.#{k}.key == spell.key}')
|
|
||||||
if canceler
|
|
||||||
span.shop_gold
|
|
||||||
span.reward-cost {{Content.spells.special.#{k}.value}}
|
|
||||||
else
|
|
||||||
span.shop_spell(class='shop_#{k}')
|
|
||||||
span.reward-cost {{user.items.special.#{k}}}
|
|
||||||
// main content
|
|
||||||
p.task-text {{Content.spells.special.#{k}.text()}}
|
|
||||||
|
|
||||||
+specialSpell('snowball')
|
|
||||||
+specialSpell('spookDust')
|
|
||||||
+specialSpell('shinySeed')
|
|
||||||
+specialSpell('salt','snowball')
|
|
||||||
+specialSpell('opaquePotion','spookDust')
|
|
||||||
+specialSpell('petalFreePotion','shinySeed')
|
|
||||||
|
|
||||||
// Spells
|
|
||||||
ul.items(ng-if='main && list.type=="reward" && user.stats.class && !user.preferences.disableClasses')
|
|
||||||
li.task.reward-item(ng-repeat='(k,skill) in Content.spells[user.stats.class]', ng-if='user.stats.lvl >= skill.lvl',popover-trigger='mouseenter', popover-placement='top', popover='{{skill.notes()}}')
|
|
||||||
.task-meta-controls
|
|
||||||
span.task-notes
|
|
||||||
span.glyphicon.glyphicon-comment
|
|
||||||
//left-hand size commands
|
|
||||||
.task-controls.task-primary
|
|
||||||
a.money.btn-buy.item-btn(ng-click='castStart(skill)', ng-class='{active: skill.key == spell.key}')
|
|
||||||
span.reward-cost
|
|
||||||
strong {{skill.mana}}
|
|
||||||
=env.t('mp')
|
|
||||||
// main content
|
|
||||||
span(ng-class='{"shop_{{skill.key}} shop-sprite item-img": true}')
|
|
||||||
p.task-text {{skill.text()}}
|
|
||||||
|
|
||||||
br
|
|
||||||
|
|
||||||
+taskColumnTabs('bottom')
|
|
||||||
56
website/views/shared/tasks/meta_controls.jade
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
.task-meta-controls
|
||||||
|
|
||||||
|
// Due Date
|
||||||
|
span(ng-if='task.type=="todo" && task.date')
|
||||||
|
span(ng-class='{"label label-danger":(moment(task.date).isBefore(_today, "days") && !task.completed)}') {{task.date | date:(user.preferences.dateFormat.indexOf('yyyy') == 0 ? user.preferences.dateFormat.substr(5) : user.preferences.dateFormat.substr(0,5))}}
|
||||||
|
|
||||||
|
// Streak
|
||||||
|
|
|
||||||
|
span(ng-show='task.streak') {{task.streak}}
|
||||||
|
span(tooltip=env.t('streakCounter'))
|
||||||
|
span.glyphicon.glyphicon-forward
|
||||||
|
|
|
||||||
|
|
||||||
|
// Icons only available if you own the tasks (aka, hidden from challenge stats)
|
||||||
|
span(ng-if='!obj._locked')
|
||||||
|
a(ng-click='pushTask(task,$index,"top")', tooltip=env.t('pushTaskToTop'))
|
||||||
|
span.glyphicon.glyphicon-open
|
||||||
|
// a(ng-click='pushTask(task,$index,"bottom")', tooltip=env.t('pushTaskToBottom'))
|
||||||
|
// span.glyphicon.glyphicon-import
|
||||||
|
// // glyphicon-import or glyphicon-save or glyphicon-sort-by-attributes
|
||||||
|
a.badge(ng-if='task.checklist[0]', ng-class='{"badge-success":checklistCompletion(task.checklist) == task.checklist.length}', ng-click='collapseChecklist(task)', tooltip=env.t('expandCollapse'))
|
||||||
|
|{{checklistCompletion(task.checklist)}}/{{task.checklist.length}}
|
||||||
|
span.glyphicon.glyphicon-tags(tooltip='{{Shared.appliedTags(user.tags, task.tags)}}', ng-hide='Shared.noTags(task.tags)')
|
||||||
|
// edit
|
||||||
|
a(ng-hide='task._editing', ng-click='editTask(task)', tooltip=env.t('edit'))
|
||||||
|
|
|
||||||
|
span.glyphicon.glyphicon-pencil(ng-hide='task._editing')
|
||||||
|
|
|
||||||
|
a(ng-hide='!task._editing', ng-click='editTask(task)', tooltip=env.t('cancel'))
|
||||||
|
span.glyphicon.glyphicon-remove(ng-hide='!task._editing')
|
||||||
|
|
|
||||||
|
// save
|
||||||
|
a(ng-hide='!task._editing', ng-click='editTask(task);saveTask(task)', tooltip=env.t('save'))
|
||||||
|
span.glyphicon.glyphicon-ok(ng-hide='!task._editing')
|
||||||
|
|
|
||||||
|
//challenges
|
||||||
|
span(ng-if='task.challenge.id')
|
||||||
|
span(ng-if='task.challenge.broken')
|
||||||
|
span.glyphicon.glyphicon-bullhorn(style='background-color:red;', ng-click='task._editing = true', tooltip=env.t('brokenChaLink') tooltip-placement='right')
|
||||||
|
|
|
||||||
|
span(ng-if='!task.challenge.broken')
|
||||||
|
span.glyphicon.glyphicon-bullhorn(tooltip=env.t('challenge'))
|
||||||
|
|
|
||||||
|
// delete
|
||||||
|
a(ng-if='!task.challenge.id', ng-click='removeTask(task, obj[list.type+"s"])', tooltip=env.t('delete'))
|
||||||
|
span.glyphicon.glyphicon-trash
|
||||||
|
|
|
||||||
|
|
||||||
|
// chart
|
||||||
|
a(ng-show='task.history', ng-click='toggleChart(obj._id+task.id, task)', tooltip=env.t('progress'))
|
||||||
|
span.glyphicon.glyphicon-signal
|
||||||
|
|
|
||||||
|
// notes
|
||||||
|
span.task-notes(ng-show='task.notes && !task._editing', ng-click='task.popoverOpen = !task.popoverOpen', popover-trigger='click', data-popover-html="{{task.notes | markdown}}", popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}')
|
||||||
|
span.glyphicon.glyphicon-comment
|
||||||
|
|
|
||||||
@@ -1,238 +1,17 @@
|
|||||||
li(bindonce='list', id='task-{{::task.id}}', ng-repeat='task in obj[list.type+"s"] | filterByTextAndNotes: obj.filterQuery | conditionalOrderBy: list.view=="dated":"date"', class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && (list.type != "reward") && castEnd(task, "task", $event)', ng-class='{"cast-target":spell && (list.type != "reward"), "locked-task":obj._locked === true}', popover-trigger='mouseenter', data-popover-html="{{task.popoverOpen ? '' : task.notes | markdown}}", popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}', ng-show='shouldShow(task, list, user.preferences)')
|
li(id='task-{{::task.id}}',
|
||||||
// right-hand side control buttons
|
ng-repeat='task in obj[list.type+"s"] | filterByTextAndNotes: obj.filterQuery | conditionalOrderBy: list.view=="dated":"date"',
|
||||||
.task-meta-controls
|
class='task {{Shared.taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}',
|
||||||
|
ng-class='{"cast-target":spell && (list.type != "reward"), "locked-task":obj._locked === true}',
|
||||||
|
ng-click='spell && (list.type != "reward") && castEnd(task, "task", $event)',
|
||||||
|
ng-show='shouldShow(task, list, user.preferences)',
|
||||||
|
popover-trigger='mouseenter', popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}',
|
||||||
|
data-popover-html="{{task.popoverOpen ? '' : task.notes | markdown}}")
|
||||||
|
|
||||||
// Due Date
|
ng-form(name='taskForm')
|
||||||
span(ng-if='task.type=="todo" && task.date')
|
include ./meta_controls
|
||||||
span(ng-class='{"label label-danger":(moment(task.date).isBefore(_today, "days") && !task.completed)}') {{task.date | date:(user.preferences.dateFormat.indexOf('yyyy') == 0 ? user.preferences.dateFormat.substr(5) : user.preferences.dateFormat.substr(0,5))}}
|
|
||||||
|
|
||||||
// Streak
|
include ./task_view/index
|
||||||
|
|
|
||||||
span(ng-show='task.streak') {{task.streak}}
|
|
||||||
span(tooltip=env.t('streakCounter'))
|
|
||||||
span.glyphicon.glyphicon-forward
|
|
||||||
|
|
|
||||||
|
|
||||||
// Icons only available if you own the tasks (aka, hidden from challenge stats)
|
include ./edit/index
|
||||||
span(ng-if='!obj._locked')
|
|
||||||
a(ng-click='pushTask(task,$index,"top")', tooltip=env.t('pushTaskToTop'))
|
|
||||||
span.glyphicon.glyphicon-open
|
|
||||||
// a(ng-click='pushTask(task,$index,"bottom")', tooltip=env.t('pushTaskToBottom'))
|
|
||||||
// span.glyphicon.glyphicon-import
|
|
||||||
// // glyphicon-import or glyphicon-save or glyphicon-sort-by-attributes
|
|
||||||
a.badge(ng-if='task.checklist[0]', ng-class='{"badge-success":checklistCompletion(task.checklist) == task.checklist.length}', ng-click='collapseChecklist(task)', tooltip=env.t('expandCollapse'))
|
|
||||||
|{{checklistCompletion(task.checklist)}}/{{task.checklist.length}}
|
|
||||||
span.glyphicon.glyphicon-tags(tooltip='{{Shared.appliedTags(user.tags, task.tags)}}', ng-hide='Shared.noTags(task.tags)')
|
|
||||||
// edit
|
|
||||||
a(ng-hide='task._editing', ng-click='editTask(task)', tooltip=env.t('edit'))
|
|
||||||
|
|
|
||||||
span.glyphicon.glyphicon-pencil(ng-hide='task._editing')
|
|
||||||
|
|
|
||||||
a(ng-hide='!task._editing', ng-click='editTask(task)', tooltip=env.t('cancel'))
|
|
||||||
span.glyphicon.glyphicon-remove(ng-hide='!task._editing')
|
|
||||||
|
|
|
||||||
// save
|
|
||||||
a(ng-hide='!task._editing', ng-click='editTask(task);saveTask(task)', tooltip=env.t('save'))
|
|
||||||
span.glyphicon.glyphicon-ok(ng-hide='!task._editing')
|
|
||||||
|
|
|
||||||
//challenges
|
|
||||||
span(ng-if='task.challenge.id')
|
|
||||||
span(ng-if='task.challenge.broken')
|
|
||||||
span.glyphicon.glyphicon-bullhorn(style='background-color:red;', ng-click='task._editing = true', tooltip=env.t('brokenChaLink') tooltip-placement='right')
|
|
||||||
|
|
|
||||||
span(ng-if='!task.challenge.broken')
|
|
||||||
span.glyphicon.glyphicon-bullhorn(tooltip=env.t('challenge'))
|
|
||||||
|
|
|
||||||
// delete
|
|
||||||
a(ng-if='!task.challenge.id', ng-click='removeTask(task, obj[list.type+"s"])', tooltip=env.t('delete'))
|
|
||||||
span.glyphicon.glyphicon-trash
|
|
||||||
|
|
|
||||||
|
|
||||||
// chart
|
|
||||||
a(ng-show='task.history', ng-click='toggleChart(obj._id+task.id, task)', tooltip=env.t('progress'))
|
|
||||||
span.glyphicon.glyphicon-signal
|
|
||||||
|
|
|
||||||
// notes
|
|
||||||
span.task-notes(ng-show='task.notes && !task._editing', ng-click='task.popoverOpen = !task.popoverOpen', popover-trigger='click', data-popover-html="{{task.notes | markdown}}", popover-placement="top", popover-append-to-body='{{::modal ? "false":"true"}}')
|
|
||||||
span.glyphicon.glyphicon-comment
|
|
||||||
|
|
|
||||||
|
|
||||||
// left-hand side checkbox
|
|
||||||
.task-controls.task-primary(ng-if='!task._editing')
|
|
||||||
|
|
||||||
// Habits
|
|
||||||
.task-actions(ng-if='::task.type=="habit"')
|
|
||||||
// score() is overridden in challengesCtrl to do nothing
|
|
||||||
a(ng-if='task.up', ng-click='applyingAction || score(task,"up")')
|
|
||||||
span.glyphicon.glyphicon-plus
|
|
||||||
a(ng-if='task.down', ng-click='applyingAction || score(task,"down")')
|
|
||||||
span.glyphicon.glyphicon-minus
|
|
||||||
|
|
||||||
// Rewards
|
|
||||||
span(ng-show='task.type=="reward"')
|
|
||||||
a.money.btn-buy(ng-class='{highValue: task.value >= 1000}', ng-click='score(task, "down")')
|
|
||||||
span.shop_gold
|
|
||||||
span.reward-cost {{task.value}}
|
|
||||||
// Daily & Todos
|
|
||||||
span.task-checker.action-yesno(ng-if='::task.type=="daily" || task.type=="todo"')
|
|
||||||
input.visuallyhidden.focusable(ng-if='$state.includes("tasks")', id='box-{{obj._id}}_{{task.id}}', type='checkbox', ng-model='task.completed', ng-change='task.type=="todo" && pushTask(task,$index,"bottom"); changeCheck(task)')
|
|
||||||
input.visuallyhidden.focusable(ng-if='!$state.includes("tasks")', id='box-{{obj._id}}_{{task.id}}', type='checkbox')
|
|
||||||
label(for='box-{{obj._id}}_{{task.id}}')
|
|
||||||
|
|
||||||
// main content
|
|
||||||
div.task-text(ng-dblclick='task._editing ? saveTask(task) : editTask(task)')
|
|
||||||
markdown(text='task.text',target='_blank')
|
|
||||||
//-| {{task.text}}
|
|
||||||
|
|
||||||
div(ng-if='task.checklist && !$state.includes("options.social.challenges") && !task.collapseChecklist && !task._editing')
|
|
||||||
fieldset.option-group.task-checklist
|
|
||||||
label.checkbox(ng-repeat='item in task.checklist')
|
|
||||||
input(type='checkbox',ng-model='item.completed',ng-change='saveTask(task,true)')
|
|
||||||
markdown(text='item.text',target='_blank')
|
|
||||||
|
|
||||||
// edit/options dialog
|
|
||||||
div(ng-if='task._editing')
|
|
||||||
.task-options
|
|
||||||
|
|
||||||
// Broken Challenge
|
|
||||||
.well(ng-if='task.challenge.broken')
|
|
||||||
div(ng-if='task.challenge.broken=="TASK_DELETED"')
|
|
||||||
p=env.t('brokenTask')
|
|
||||||
p
|
|
||||||
a(ng-click='unlink(task, "keep")')=env.t('keepIt')
|
|
||||||
|
|
|
||||||
a(ng-click="removeTask(task, obj[list.type+'s'])")=env.t('removeIt')
|
|
||||||
div(ng-if='task.challenge.broken=="CHALLENGE_DELETED"')
|
|
||||||
p
|
|
||||||
|
|
|
||||||
=env.t('brokenChallenge')
|
|
||||||
p
|
|
||||||
a(ng-click='unlink(task, "keep-all")')=env.t('keepThem')
|
|
||||||
| |
|
|
||||||
a(ng-click='unlink(task, "remove-all")')=env.t('removeThem')
|
|
||||||
div(ng-if='task.challenge.broken=="CHALLENGE_CLOSED"')
|
|
||||||
p
|
|
||||||
!=env.t('challengeCompleted', {user: "{{task.challenge.winner}}"})
|
|
||||||
p
|
|
||||||
a(ng-click='unlink(task, "keep-all")')=env.t('keepThem')
|
|
||||||
| |
|
|
||||||
a(ng-click='unlink(task, "remove-all")')=env.t('removeThem')
|
|
||||||
//div(ng-if='task.challenge.broken=="UNSUBSCRIBED"')
|
|
||||||
p=env.t('unsubChallenge')
|
|
||||||
p
|
|
||||||
a(ng-click="unlink(task, 'keep-all')")=env.t('keepThem')
|
|
||||||
| |
|
|
||||||
a(ng-click="unlink(task, 'remove-all')")=env.t('removeThem')
|
|
||||||
|
|
||||||
// Checklists
|
|
||||||
.task-checklist-edit(ng-if='!$state.includes("options.social.challenges")')
|
|
||||||
ul
|
|
||||||
li
|
|
||||||
button(type='button', ng-if='!task.checklist[0] && (task.type=="daily" || task.type=="todo")',ng-click='addChecklist(task)')
|
|
||||||
span.glyphicon.glyphicon-tasks
|
|
||||||
span=env.t('addChecklist')
|
|
||||||
form.checklist-form(ng-if='task.checklist')
|
|
||||||
fieldset.option-group(ng-if='!$state.includes("options.social.challenges")')
|
|
||||||
legend.option-title
|
|
||||||
span.hint(popover=env.t('checklistText'),popover-trigger='mouseenter',popover-placement='bottom')=env.t('checklist')
|
|
||||||
ul(hrpg-sort-checklist)
|
|
||||||
li(ng-repeat='item in task.checklist')
|
|
||||||
//input(type='checkbox',ng-model='item.completed',ng-change='saveTask(task,true)')
|
|
||||||
//-,ng-blur='saveTask(task,true)')
|
|
||||||
span.checklist-icon.glyphicon.glyphicon-resize-vertical()
|
|
||||||
input(type='text',ng-model='item.text', ui-keyup="{'13':'addChecklistItem(task,$event,$index)','38 40':'navigateChecklist(task,$index,$event)'}")
|
|
||||||
a(ng-click='removeChecklistItem(task,$event,$index,true)')
|
|
||||||
span.glyphicon.glyphicon-trash(tooltip=env.t('delete'))
|
|
||||||
|
|
||||||
form(ng-submit='saveTask(task,false,true)')
|
|
||||||
// text & notes
|
|
||||||
fieldset.option-group
|
|
||||||
label.option-title=env.t('text')
|
|
||||||
input.option-content(type='text', ng-model='task.text', required, ng-disabled='task.challenge.id')
|
|
||||||
|
|
||||||
label.option-title=env.t('extraNotes')
|
|
||||||
textarea.option-content(rows='3', ng-model='task.notes', ng-model-options="{debounce: 1000}")
|
|
||||||
|
|
||||||
// if Habit, plus/minus command options
|
|
||||||
fieldset.option-group.plusminus(ng-if='task.type=="habit" && !task.challenge.id')
|
|
||||||
legend.option-title=env.t('direction/Actions')
|
|
||||||
span.task-checker
|
|
||||||
input.visuallyhidden.focusable(id='{{obj._id}}_{{task.id}}-option-plus', type='checkbox', ng-model='task.up')
|
|
||||||
label(for='{{obj._id}}_{{task.id}}-option-plus')
|
|
||||||
span.task-checker
|
|
||||||
input.visuallyhidden.focusable(id='{{obj._id}}_{{task.id}}-option-minus', type='checkbox', ng-model='task.down')
|
|
||||||
label(for='{{obj._id}}_{{task.id}}-option-minus')
|
|
||||||
|
|
||||||
// if Daily, calendar
|
|
||||||
fieldset(ng-if='::task.type=="daily"', class="option-group")
|
|
||||||
legend.option-title=env.t('repeat')
|
|
||||||
ul.repeat-days(bindonce)
|
|
||||||
// note, does not use data-toggle="buttons-checkbox" - it would interfere with our own click binding
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.su}', type='button', ng-click='task.challenge.id || (task.repeat.su = !task.repeat.su)') {{::moment.weekdaysMin(0)}}
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.m}', type='button', ng-click='task.challenge.id || (task.repeat.m = !task.repeat.m)') {{::moment.weekdaysMin(1)}}
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.t}', type='button', ng-click='task.challenge.id || (task.repeat.t = !task.repeat.t)') {{::moment.weekdaysMin(2)}}
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.w}', type='button', ng-click='task.challenge.id || (task.repeat.w = !task.repeat.w)') {{::moment.weekdaysMin(3)}}
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.th}', type='button', ng-click='task.challenge.id || (task.repeat.th = !task.repeat.th)') {{::moment.weekdaysMin(4)}}
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.f}', type='button', ng-click='task.challenge.id || (task.repeat.f= !task.repeat.f)') {{::moment.weekdaysMin(5)}}
|
|
||||||
li
|
|
||||||
button(ng-class='{active: task.repeat.s}', type='button', ng-click='task.challenge.id || (task.repeat.s = !task.repeat.s)') {{::moment.weekdaysMin(6)}}
|
|
||||||
|
|
||||||
// if Reward, pricing
|
|
||||||
fieldset.option-group.option-short(ng-if='task.type=="reward" && !task.challenge.id')
|
|
||||||
legend.option-title=env.t('price')
|
|
||||||
input.option-content(type='number', size='16', min='0', step="any", ng-model='task.value')
|
|
||||||
.money.input-suffix
|
|
||||||
span.shop_gold
|
|
||||||
|
|
||||||
// if Todos, the due date
|
|
||||||
fieldset.option-group(ng-if='task.type=="todo" && !task.challenge.id')
|
|
||||||
legend.option-title=env.t('dueDate')
|
|
||||||
input.option-content.datepicker(type='text', datepicker-popup='{{user.preferences.dateFormat}}', ng-model='task.date', is-open='datepickerOpened', ng-click='datepickerOpened = true')
|
|
||||||
|
|
||||||
// Tags
|
|
||||||
fieldset.option-group(ng-if='!$state.includes("options.social.challenges")')
|
|
||||||
p.option-title.mega(ng-click='task._tags = !task._tags', tooltip=env.t('expandCollapse'))=env.t('tags')
|
|
||||||
label.checkbox(ng-repeat='tag in user.tags', ng-class="{visuallyhidden: task._tags}")
|
|
||||||
input(type='checkbox', ng-model='task.tags[tag.id]')
|
|
||||||
markdown(text='tag.name')
|
|
||||||
|
|
||||||
// Advanced Options
|
|
||||||
span(ng-if='::task.type!="reward"')
|
|
||||||
p.option-title.mega(ng-click='task._advanced = !task._advanced', tooltip=env.t('expandCollapse'))=env.t('advancedOptions')
|
|
||||||
fieldset.option-group.advanced-option(ng-class="{visuallyhidden: task._advanced}")
|
|
||||||
legend.option-title
|
|
||||||
a.hint.priority-multiplier-help(href='http://habitrpg.wikia.com/wiki/Difficulty', target='_blank', popover-title=env.t('difficultyHelpTitle'), popover-trigger='mouseenter', popover=env.t('difficultyHelpContent'))=env.t('difficulty')
|
|
||||||
ul.priority-multiplier
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.priority==1 || !task.priority}', ng-click='task.challenge.id || (task.priority=1)')=env.t('easy')
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.priority==1.5}', ng-click='task.challenge.id || (task.priority=1.5)')=env.t('medium')
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.priority==2}', ng-click='task.challenge.id || (task.priority=2)')=env.t('hard')
|
|
||||||
//span(ng-if='task.type=="daily" && !task.challenge.id')
|
|
||||||
span(ng-if='task.type=="daily"')
|
|
||||||
legend.option-title.pull-left=env.t('restoreStreak')
|
|
||||||
input.option-content(type='number', ng-model='task.streak')
|
|
||||||
|
|
||||||
div(ng-if='(user.preferences.allocationMode == "taskbased" && user.preferences.automaticAllocation) || $state.is("options.social.challenges")')
|
|
||||||
legend.option-title.pull-left=env.t('attributes')
|
|
||||||
ul.task-attributes
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.attribute=="str"}', ng-click='task.attribute="str"')=env.t('physical')
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.attribute=="int"}', ng-click='task.attribute="int"')=env.t('mental')
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.attribute=="con"}', ng-click='task.attribute="con"')=env.t('social')
|
|
||||||
li
|
|
||||||
button(type='button', ng-class='{active: task.attribute=="per"}', ng-click='task.attribute="per"', popover=env.t('otherExamples'), popover-trigger='mouseenter', popover-placement='top')=env.t('other')
|
|
||||||
|
|
||||||
.save-close
|
|
||||||
button(type='submit')=env.t('saveAndClose')
|
|
||||||
|
|
||||||
div(class='{{obj._id}}{{task.id}}-chart', ng-show='charts[obj._id+task.id]')
|
div(class='{{obj._id}}{{task.id}}-chart', ng-show='charts[obj._id+task.id]')
|
||||||
|
|||||||
10
website/views/shared/tasks/task_view/add_new.jade
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
form.task-add(name='new{{list.type}}form', ng-hide='obj._locked', ng-submit='addTask(obj[list.type+"s"],list)', novalidate)
|
||||||
|
textarea(rows='6', task-focus='list.bulk && list.focus', ng-model='list.newTask', placeholder='{{list.placeHolderBulk}}', ng-if='list.bulk', ui-keydown='{"meta-enter ctrl-enter":"addTask(obj[list.type+\'s\'],list)"}', required)
|
||||||
|
input(type='text', task-focus='!list.bulk && list.focus', ng-model='list.newTask', placeholder='{{list.placeHolder}}', ng-if='!list.bulk', required)
|
||||||
|
button(type='submit', ng-disabled='new{{list.type}}form.$invalid')
|
||||||
|
div.empty-task-notification( ng-show='new{{list.type}}form.$invalid', tooltip=env.t("emptyTask") )
|
||||||
|
span.glyphicon.glyphicon-plus
|
||||||
|
span.glyphicon.glyphicon-plus(ng-show='!new{{list.type}}form.$invalid')
|
||||||
|
small.help-block.btn-link.pull-right(ng-click='toggleBulk(list)')
|
||||||
|
span(ng-if='!list.bulk')=env.t('addmultiple')
|
||||||
|
span(ng-if='list.bulk')=env.t('addsingle')
|
||||||
9
website/views/shared/tasks/task_view/graph.jade
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
span.option-box.pull-right(ng-if='::main')
|
||||||
|
a.option-action(ng-if='list.type=="todo"', ng-show='obj.history.todos', ng-click='toggleChart("todos")', tooltip=env.t('progress'), style='margin-right:5px;')
|
||||||
|
span.glyphicon.glyphicon-signal
|
||||||
|
//a.option-action(ng-href='/v1/users/{{user.id}}/calendar.ics?apiToken={{user.apiToken}}', tooltip='iCal')
|
||||||
|
//-a.option-action(ng-if='list.type=="todo"', ng-click='notPorted()', tooltip='iCal', ng-show='false')
|
||||||
|
span.glyphicon.glyphicon-calendar
|
||||||
|
// <a href="https://www.google.com/calendar/render?cid={{encodeiCalLink(_user.id, _user.apiToken)}}" rel=tooltip title="Google Calendar"><i class=icon-calendar></i></a>
|
||||||
|
a.option-action(ng-click='list.help=!list.help', tooltip='Click for help')
|
||||||
|
span.glyphicon.glyphicon-question-sign(style={'zoom':1.5,'vertical-align':'-webkit-baseline-middle'})
|
||||||
25
website/views/shared/tasks/task_view/help.jade
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
div(ng-if='list.help', ng-switch='::list.type')
|
||||||
|
ul(ng-switch-when='habit')
|
||||||
|
li!=env.t('habitHelp1', {plusIcon:"<span class='glyphicon glyphicon-plus'></span>"})
|
||||||
|
li!=env.t('habitHelp2', {minusIcon:"<span class='glyphicon glyphicon-minus'></span>"})
|
||||||
|
li!=env.t('habitHelp3')
|
||||||
|
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
||||||
|
ul(ng-switch-when='daily')
|
||||||
|
li!=env.t('dailyHelp1', {emphasisStart:"<strong>", emphasisEnd:"</strong>", pencilIcon:"<span class='glyphicon glyphicon-pencil'></span>"})
|
||||||
|
li=env.t('dailyHelp2')
|
||||||
|
li!=env.t('dailyHelp3', {emphasisStart:"<strong>", emphasisEnd:"</strong>"})
|
||||||
|
li!=env.t('dailyHelp4', {linkStart:"<a href='/#/options/settings/settings' target='_blank'>", linkEnd:"</a>"})
|
||||||
|
li!=env.t('dailyHelp5')
|
||||||
|
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
||||||
|
ul(ng-switch-when='todo')
|
||||||
|
li=env.t('toDoHelp1')
|
||||||
|
li=env.t('toDoHelp2')
|
||||||
|
li=env.t('toDoHelp3')
|
||||||
|
li!=env.t('toDoHelp4')
|
||||||
|
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
||||||
|
ul(ng-switch-when='reward')
|
||||||
|
li!=env.t('rewardHelp1', {linkStart:"<a href='/#/options/inventory/equipment' target='_blank'>", linkEnd: "</a>"})
|
||||||
|
li!=env.t('rewardHelp2', {linkStart:"<a href='/#/options/profile/stats' target='_blank'>", linkEnd: "</a>"})
|
||||||
|
li=env.t('rewardHelp3')
|
||||||
|
li!=env.t('rewardHelp4')
|
||||||
|
li!=env.t('newbieGuild', {linkStart:"<a href='https://habitrpg.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a' target='_blank'>", linkEnd: "</a>"})
|
||||||
35
website/views/shared/tasks/task_view/index.jade
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// left-hand side checkbox
|
||||||
|
.task-controls.task-primary(ng-if='!task._editing')
|
||||||
|
|
||||||
|
// Habits
|
||||||
|
.task-actions(ng-if='::task.type=="habit"')
|
||||||
|
// score() is overridden in challengesCtrl to do nothing
|
||||||
|
a(ng-if='task.up', ng-click='applyingAction || score(task,"up")')
|
||||||
|
span.glyphicon.glyphicon-plus
|
||||||
|
a(ng-if='task.down', ng-click='applyingAction || score(task,"down")')
|
||||||
|
span.glyphicon.glyphicon-minus
|
||||||
|
|
||||||
|
// Rewards
|
||||||
|
span(ng-if='::task.type=="reward"')
|
||||||
|
a.money.btn-buy(ng-class='{highValue: task.value >= 1000}', ng-click='score(task, "down")')
|
||||||
|
span.shop_gold
|
||||||
|
span.reward-cost {{task.value}}
|
||||||
|
|
||||||
|
// Daily & Todos
|
||||||
|
span.task-checker.action-yesno(ng-if='::task.type=="daily" || task.type=="todo"')
|
||||||
|
input.visuallyhidden.focusable(id='box-{{::obj._id}}_{{::task.id}}', type='checkbox',
|
||||||
|
ng-model='task.completed', ng-if='$state.includes("tasks")',
|
||||||
|
ng-change='task.type=="todo" && pushTask(task,$index,"bottom"); changeCheck(task)')
|
||||||
|
input.visuallyhidden.focusable(id='box-{{::obj._id}}_{{::task.id}}', type='checkbox',
|
||||||
|
ng-if='!$state.includes("tasks")')
|
||||||
|
label(for='box-{{::obj._id}}_{{::task.id}}')
|
||||||
|
|
||||||
|
// main content
|
||||||
|
.task-text(ng-dblclick='task._editing ? saveTask(task) : editTask(task)')
|
||||||
|
markdown(text='task.text',target='_blank')
|
||||||
|
|
||||||
|
div(ng-if='task.checklist && !$state.includes("options.social.challenges") && !task.collapseChecklist && !task._editing')
|
||||||
|
fieldset.option-group.task-checklist
|
||||||
|
label.checkbox(ng-repeat='item in task.checklist')
|
||||||
|
input(type='checkbox', ng-model='item.completed', ng-change='saveTask(task,true)')
|
||||||
|
markdown(text='item.text', target='_blank')
|
||||||
60
website/views/shared/tasks/task_view/mixins.jade
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
mixin taskColumnTabs(position)
|
||||||
|
// Habits Tabs
|
||||||
|
div(ng-if='::main && list.type=="habit"', class='tabbable tabs-below')
|
||||||
|
ul.task-filter
|
||||||
|
li(ng-class='{active: list.view == "all"}')
|
||||||
|
a(ng-click='list.view = "all"')=env.t('all')
|
||||||
|
li(ng-class='{active: list.view == "yellowred"}')
|
||||||
|
a(ng-click='list.view = "yellowred"')=env.t('yellowred')
|
||||||
|
li(ng-class='{active: list.view == "greenblue"}')
|
||||||
|
a(ng-click='list.view = "greenblue"')=env.t('greenblue')
|
||||||
|
// Daily Tabs
|
||||||
|
div(ng-if='::main && list.type=="daily"', class='tabbable tabs-below')
|
||||||
|
// remaining/completed tabs
|
||||||
|
ul.task-filter
|
||||||
|
li(ng-class='{active: list.view == "all"}')
|
||||||
|
a(ng-click='list.view = "all"')=env.t('all')
|
||||||
|
li(ng-class='{active: list.view == "remaining"}')
|
||||||
|
a(ng-click='list.view = "remaining"')=env.t('due')
|
||||||
|
li(ng-class='{active: list.view == "complete"}')
|
||||||
|
a(ng-click='list.view = "complete"')=env.t('grey')
|
||||||
|
// Todo Tabs
|
||||||
|
div(ng-if='::main && list.type=="todo"', ng-class='::{"tabbable tabs-below": list.type=="todo"}')
|
||||||
|
if position=="bottom"
|
||||||
|
div(ng-show='list.view == "complete"')
|
||||||
|
.alert
|
||||||
|
=env.t('lotOfToDos')
|
||||||
|
button.task-action-btn.tile.spacious.bright(ng-click='user.ops.clearCompleted({})',popover=env.t('deleteToDosExplanation'),popover-trigger='mouseenter')=env.t('clearCompleted')
|
||||||
|
p!=env.t('beeminderDeleteWarning')
|
||||||
|
// remaining/completed tabs
|
||||||
|
ul.task-filter
|
||||||
|
li(ng-class='{active: list.view == "remaining"}')
|
||||||
|
a(ng-click='list.view = "remaining"')=env.t('remaining')
|
||||||
|
li(ng-class='{active: list.view == "dated"}')
|
||||||
|
a(ng-click='list.view = "dated"')=env.t('dated')
|
||||||
|
li(ng-class='{active: list.view == "complete"}')
|
||||||
|
a(ng-click='list.view = "complete"')=env.t('complete')
|
||||||
|
// Rewards Tabs
|
||||||
|
div(ng-if='::main && list.type=="reward"', class='tabbable tabs-below')
|
||||||
|
ul.task-filter
|
||||||
|
li(ng-class='{active: list.view == "all"}')
|
||||||
|
a(ng-click='list.view = "all"')=env.t('all')
|
||||||
|
li(ng-class='{active: list.view == "ingamerewards"}')
|
||||||
|
a(ng-click='list.view = "ingamerewards"')=env.t('ingamerewards')
|
||||||
|
|
||||||
|
mixin specialSpell(k,canceler)
|
||||||
|
li.task.reward-item(ng-if='#{canceler ? "user.stats.buffs."+canceler : "user.items.special."+k+">0"}',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.#{k}.notes()}}')
|
||||||
|
.task-meta-controls
|
||||||
|
span.task-notes
|
||||||
|
span.glyphicon.glyphicon-comment
|
||||||
|
//left-hand size commands
|
||||||
|
.task-controls.task-primary
|
||||||
|
a.money.btn-buy.item-btn(ng-click='castStart(Content.spells.special.#{k})', ng-class='{active: Content.spells.special.#{k}.key == spell.key}')
|
||||||
|
if canceler
|
||||||
|
span.shop_gold
|
||||||
|
span.reward-cost {{Content.spells.special.#{k}.value}}
|
||||||
|
else
|
||||||
|
span.shop_spell(class='shop_#{k}')
|
||||||
|
span.reward-cost {{user.items.special.#{k}}}
|
||||||
|
// main content
|
||||||
|
p.task-text {{Content.spells.special.#{k}.text()}}
|
||||||
25
website/views/shared/tasks/task_view/spells.jade
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Events
|
||||||
|
ul.items.rewards(ng-if='main && list.type=="reward" && (user.items.special.snowball>0 || user.stats.buffs.snowball || user.items.special.spookDust>0 || user.stats.buffs.spookDust || user.items.special.shinySeed>0 || user.stats.buffs.shinySeed)')
|
||||||
|
|
||||||
|
+specialSpell('snowball')
|
||||||
|
+specialSpell('spookDust')
|
||||||
|
+specialSpell('shinySeed')
|
||||||
|
+specialSpell('salt','snowball')
|
||||||
|
+specialSpell('opaquePotion','spookDust')
|
||||||
|
+specialSpell('petalFreePotion','shinySeed')
|
||||||
|
|
||||||
|
// Spells
|
||||||
|
ul.items(ng-if='main && list.type=="reward" && user.stats.class && !user.preferences.disableClasses')
|
||||||
|
li.task.reward-item(ng-repeat='(k,skill) in Content.spells[user.stats.class]', ng-if='user.stats.lvl >= skill.lvl',popover-trigger='mouseenter', popover-placement='top', popover='{{skill.notes()}}')
|
||||||
|
.task-meta-controls
|
||||||
|
span.task-notes
|
||||||
|
span.glyphicon.glyphicon-comment
|
||||||
|
//left-hand size commands
|
||||||
|
.task-controls.task-primary
|
||||||
|
a.money.btn-buy.item-btn(ng-click='castStart(skill)', ng-class='{active: skill.key == spell.key}')
|
||||||
|
span.reward-cost
|
||||||
|
strong {{skill.mana}}
|
||||||
|
=env.t('mp')
|
||||||
|
// main content
|
||||||
|
span(ng-class='{"shop_{{skill.key}} shop-sprite item-img": true}')
|
||||||
|
p.task-text {{skill.text()}}
|
||||||
14
website/views/shared/tasks/task_view/static_rewards.jade
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
ul.items.rewards(ng-if='main && list.type=="reward"')
|
||||||
|
li.task.reward-item(ng-repeat='item in itemStore',popover-trigger='mouseenter', popover-placement='top', popover='{{item.key == "armoire" && !user.flags.armoireEmpty ? env.t("armoireNotesFull") + armoireCount(user.items.gear.owned) : item.notes()}}')
|
||||||
|
// right-hand side control buttons
|
||||||
|
.task-meta-controls
|
||||||
|
span.task-notes
|
||||||
|
span.glyphicon.glyphicon-comment
|
||||||
|
//left-hand size commands
|
||||||
|
.task-controls.task-primary
|
||||||
|
a.money.btn-buy.item-btn(ng-class='{highValue: item.value >= 1000}', ng-click='buy(item)')
|
||||||
|
span.shop_gold
|
||||||
|
span.reward-cost {{item.value}}
|
||||||
|
// main content
|
||||||
|
span(ng-class='::{"shop_{{item.key}} shop-sprite item-img": true}').reward-img
|
||||||
|
p.task-text {{item.text()}}
|
||||||