Adding first rudimentary version of tagging and filtering. New users get three tags: morning, afternoon and evening. At the moment, one can not change these tags or add new ones. There are also some problems: tagging a newly added task, also tags one of the existing tasks. Also, when having an active filter and removing the corresponding tag from a task, that task is immediately hidden, although you are still editing it.

This commit is contained in:
Tyler Renelle 2013-02-28 10:59:39 -05:00
parent 39a98446b9
commit 4614e48cdc
11 changed files with 92 additions and 8 deletions

View file

@ -111,6 +111,7 @@ userSchema =
flags:
partyEnabled: false
itemsEnabled: false
tags: []
# ads: 'show' # added on registration
module.exports.newUserObject = ->
@ -130,6 +131,12 @@ module.exports.newUserObject = ->
{type: 'reward', text: 'Cake', notes: 'But only buy if you have enough gold - you lose HP otherwise.', value: 10 }
]
defaultTags = [
{name: 'morning'}
{name: 'afternoon'}
{name: 'evening'}
]
for task in defaultTasks
guid = task.id = derby.uuid()
newUser.tasks[guid] = task
@ -138,6 +145,11 @@ module.exports.newUserObject = ->
when 'daily' then newUser.dailyIds.push guid
when 'todo' then newUser.todoIds.push guid
when 'reward' then newUser.rewardIds.push guid
for tag in defaultTags
tag.id = derby.uuid()
newUser.tags.push tag
return newUser
module.exports.updateUser = (model) ->

7
src/app/filters.coffee Normal file
View file

@ -0,0 +1,7 @@
module.exports.app = (appExports, model) ->
user = model.at('_user')
appExports.toggleFilterByTag = (e, el) ->
tagId = $(el).attr('data-tag-id')
path = '_tagFilters.' + tagId
user.set path, !(user.get path)

View file

@ -13,6 +13,7 @@ browser = require './browser'
party = require './party'
items = require './items'
profile = require './profile'
filters = require './filters'
helpers.viewHelpers view
character.view view
@ -61,4 +62,5 @@ ready (model) ->
require('../server/private').app(exports, model)
require('./debug').app(exports, model) if model.get('_view.nodeEnv') != 'production'
browser.app(exports, model)
filters.app(exports, model)

View file

@ -4,8 +4,14 @@ _ = require 'underscore'
moment = require 'moment'
module.exports.view = (view) ->
view.fn 'taskClasses', (type, completed, value, repeat) ->
view.fn 'taskClasses', (type, completed, value, repeat, tags = {}, filters = {}) ->
#TODO figure out how to just pass in the task model, so i can access all these properties from one object
if type != 'reward'
for filter, enabled of filters
if enabled and not tags[filter]
# All the other classes don't matter
return 'filtered-out'
classes = type
# show as completed if completed (naturally) or not required for today
@ -167,6 +173,13 @@ module.exports.app = (appExports, model) ->
target.removeClass(oldContext)
target.addClass(newContext)
appExports.addTag = (e, el) ->
tagId = $(el).attr('data-tag-id')
taskId = $(el).attr('data-task-id')
console.log taskId
path = "_user.tasks.#{taskId}.tags.#{tagId}"
model.set path, !(model.get path)
appExports.score = (e, el, next) ->
direction = $(el).attr('data-direction')
direction = 'up' if direction == 'true/'

15
styles/app/filters.styl Normal file
View file

@ -0,0 +1,15 @@
/* Filters */
.filters
padding-left: 19px
padding-right: 19px
.filters .nav
margin-bottom: 0
.filter-description
margin-top: 7px
margin-right: 7px
/* Filters applied to tasks */
.task.filtered-out
display: none

View file

@ -7,6 +7,7 @@
@import "./customizer.styl";
@import "./items.styl";
@import "./alerts.styl";
@import "./filters.styl";
@import "../../public/vendor/bootstrap-datepicker/css/datepicker.css";
@ -47,7 +48,7 @@ html,body,p,h1,ul,li,table,tr,th,td
.modal
whitespace:normal
.dropdown-menu
.user-actions .dropdown-menu
right: 0
left: auto

View file

@ -39,7 +39,7 @@ label.checkbox.inline{
.context-enabled
.display-context-dependant,
.task-list li
.task-list > li
display: none
&.context-completed

11
views/app/filters.html Normal file
View file

@ -0,0 +1,11 @@
<filters:>
<div class="well well-small filters">
<div class="pull-left filter-description">
Filter by tag:
</div>
<ul class="nav nav-pills">
{#each _user.tags as :tag}
<li class="{#if _user._tagFilters[:tag.id]}active{/}"><a data-tag-id="{:tag.id}" x-bind=click:toggleFilterByTag>{:tag.name}</a></li>
{/}
</ul>
</div>

View file

@ -7,6 +7,7 @@
<import: src="footer">
<import: src="settings">
<import: src="party">
<import: src="filters">
<Title:>
HabitRPG | Gamify Your Life
@ -28,6 +29,7 @@
<div id="notification-area"></div>
<div id=wrap class="container-fluid">
<app:alerts:alerts />
<app:filters:filters />
<div id=main class="row-fluid">
<app:taskLists />
</div>

View file

@ -28,7 +28,7 @@
<p>This is highly discouraged because you'll lose historical data, which is useful for graphing your progress over time. However, some people find it useful in the beginning after playing with the app for a while.</p>
<@footer>
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<button data-dismiss="modal" x-bind=click:reset class="btn btn-danger btn-large">Reset</button>
<button data-dismiss="modal" x-bind=click:reset class="btn btn-danger">Reset</button>
</@footer>
</app:modals:modal>
@ -103,7 +103,7 @@
{#unless _loggedIn}
<a href="#" class="btn btn-small btn-info" data-target="#login-modal" data-toggle="modal">Login / Register</a>
{else}
<div class="btn-group">
<div class="btn-group user-actions">
<button class="btn btn-small">
{#if _user.party.invitation}<span class="badge badge-success">1</span>{/}
{username(_user.auth)}

View file

@ -128,8 +128,8 @@
<input class="btn" type="submit" value="Add" />
</form>
<task:>
<li data-id={{:task.id}} class="task {taskClasses(:task.type, :task.completed, :task.value, :task.repeat)}">
<task:>
<li data-id={{:task.id}} class="task {taskClasses(:task.type, :task.completed, :task.value, :task.repeat, :task.tags, _user._tagFilters)}">
<pre>
<div class="task-meta-controls">
@ -161,7 +161,14 @@
<input type=checkbox checked="{:task.completed}"/>
{/}
</div>
<div class="task-text">{:task.text}</div>
<div class="task-text">
{:task.text}
{#each _user.tags as :tag}
{#if :task.tags[:tag.id]}
<span class="label {#if _user._tagFilters[:tag.id]}label-info{/}">{:tag.name}</span>
{/}
{/}
</div>
<app:taskMeta />
</pre>
@ -207,6 +214,20 @@
<div><small>Enter as date, eg 02/19/2013 or 02-19-2013</small></div>
</div>
{/}
{#if not(equal(:task.type, 'reward'))}
<div class="control-group">
<div class="btn-group">
<button class="btn dropdown-toggle" data-toggle="dropdown">
Tags <span class="caret"></span>
</button>
<ul class="dropdown-menu">
{#each _user.tags as :tag}
<li class="{#if :task.tags[:tag.id]}active{/}"><a data-task-id="{{:task.id}}" data-tag-id="{:tag.id}" x-bind=click:addTag>{:tag.name}</a></li>
{/}
</ul>
</div>
</div>
{/}
<button type=submit class="btn" x-bind="click:tasksSaveAndClose">Save & Close</button>
</form>
</div>