mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-07-31 23:11:15 +00:00
Merge branch 'develop' of github.com:lefnire/habitrpg into develop
This commit is contained in:
commit
78d6111fbc
8 changed files with 127 additions and 54 deletions
|
|
@ -195,8 +195,8 @@ setupGrowlNotifications = (model) ->
|
|||
statsNotification '<i class="icon-chevron-up"></i> Level Up!', 'lvl'
|
||||
|
||||
module.exports.resetDom = (model) ->
|
||||
DERBY.app.dom.clear()
|
||||
DERBY.app.view.render(model, DERBY.app.view._lastRender.ns, DERBY.app.view._lastRender.context);
|
||||
window.DERBY.app.dom.clear()
|
||||
window.DERBY.app.view.render(model, window.DERBY.app.view._lastRender.ns, window.DERBY.app.view._lastRender.context);
|
||||
|
||||
# Note, Google Analyatics giving beef if in this file. Moved back to index.html. It's ok, it's async - really the
|
||||
# syncronous requires up top are what benefit the most from this file.
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ module.exports.app = (appExports, model) ->
|
|||
model.set '_newTag', ''
|
||||
|
||||
appExports.toggleEditingTags = ->
|
||||
before = model.get('_editingTags')
|
||||
model.set '_editingTags', !before, ->
|
||||
location.reload() if before is true #when they're done, refresh the page
|
||||
model.set '_editingTags', !model.get('_editingTags')
|
||||
|
||||
appExports.clearFilters = ->
|
||||
user.set 'filters', {}
|
||||
|
|
|
|||
|
|
@ -22,42 +22,6 @@ misc.viewHelpers view
|
|||
|
||||
_ = require('lodash')
|
||||
algos = require 'habitrpg-shared/script/algos'
|
||||
helpers = require 'habitrpg-shared/script/helpers'
|
||||
|
||||
###
|
||||
Cleanup task-corruption (null tasks, rogue/invisible tasks, etc)
|
||||
Obviously none of this should be happening, but we'll stop-gap until we can find & fix
|
||||
Gotta love refLists! see https://github.com/lefnire/habitrpg/issues/803 & https://github.com/lefnire/habitrpg/issues/6343
|
||||
###
|
||||
cleanupCorruptTasks = (model) ->
|
||||
user = model.at('_user')
|
||||
tasks = user.get('tasks')
|
||||
|
||||
## Remove corrupted tasks
|
||||
_.each tasks, (task, key) ->
|
||||
unless task?.id? and task?.type?
|
||||
user.del("tasks.#{key}")
|
||||
delete tasks[key]
|
||||
true
|
||||
|
||||
misc.batchTxn model, (uObj, paths, batch) ->
|
||||
## Task List Cleanup
|
||||
['habit','daily','todo','reward'].forEach (type) ->
|
||||
|
||||
# 1. remove duplicates
|
||||
# 2. restore missing zombie tasks back into list
|
||||
idList = uObj["#{type}Ids"]
|
||||
taskIds = _.pluck( _.where(tasks, {type:type}), 'id')
|
||||
union = _.union idList, taskIds
|
||||
|
||||
# 2. remove empty (grey) tasks
|
||||
preened = _.filter union, (id) -> id and _.contains(taskIds, id)
|
||||
|
||||
# There were indeed issues found, set the new list
|
||||
if !_.isEqual(idList, preened)
|
||||
batch.set("#{type}Ids", preened)
|
||||
console.error uObj.id + "'s #{type}s were corrupt."
|
||||
true
|
||||
|
||||
|
||||
###
|
||||
|
|
@ -103,7 +67,6 @@ get '/', (page, model, params, next) ->
|
|||
|
||||
# removed force-ssl (handled in nginx), see git for code
|
||||
setupSubscriptions page, model, params, next, ->
|
||||
cleanupCorruptTasks(model) # https://github.com/lefnire/habitrpg/issues/634
|
||||
require('./items').server(model)
|
||||
#refLists
|
||||
_.each ['habit', 'daily', 'todo', 'reward'], (type) ->
|
||||
|
|
@ -115,9 +78,12 @@ get '/', (page, model, params, next) ->
|
|||
# ========== CONTROLLER FUNCTIONS ==========
|
||||
|
||||
ready (model) ->
|
||||
user = model.at('_user')
|
||||
browser = require './browser'
|
||||
exports.removeAt = (e) -> e.at().remove() # used for things like remove website, chat, etc
|
||||
|
||||
user = model.at('_user')
|
||||
misc.fixCorruptUser(model) # https://github.com/lefnire/habitrpg/issues/634
|
||||
|
||||
browser = require './browser'
|
||||
require('./tasks').app(exports, model)
|
||||
require('./items').app(exports, model)
|
||||
require('./party').app(exports, model, app)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module.exports.batchTxn = batchTxn = (model, cb, options) ->
|
|||
get: (k) -> helpers.dotGet(k,uObj)
|
||||
paths = {}
|
||||
model._dontPersist = true
|
||||
cb uObj, paths, batch
|
||||
ret = cb uObj, paths, batch
|
||||
_.each paths, (v,k) -> user.pass({cron:options?.cron}).set(k,helpers.dotGet(k, uObj));true
|
||||
model._dontPersist = false
|
||||
# some hackery in our own branched racer-db-mongo, see findAndModify of lefnire/racer-db-mongo#habitrpg index.js
|
||||
|
|
@ -19,6 +19,8 @@ module.exports.batchTxn = batchTxn = (model, cb, options) ->
|
|||
unless _.isEmpty paths
|
||||
setOps = _.reduce paths, ((m,v,k)-> m[k] = helpers.dotGet(k,uObj);m), {}
|
||||
user.set "update__", setOps
|
||||
ret
|
||||
|
||||
|
||||
###
|
||||
algos.score wrapper for habitrpg-helpers to work in Derby. We need to do model.set() instead of simply setting the
|
||||
|
|
@ -58,6 +60,51 @@ module.exports.hydrate = hydrate = (spec) ->
|
|||
hydrated
|
||||
else spec
|
||||
|
||||
|
||||
###
|
||||
Cleanup task-corruption (null tasks, rogue/invisible tasks, etc)
|
||||
Obviously none of this should be happening, but we'll stop-gap until we can find & fix
|
||||
Gotta love refLists! see https://github.com/lefnire/habitrpg/issues/803 & https://github.com/lefnire/habitrpg/issues/6343
|
||||
###
|
||||
module.exports.fixCorruptUser = (model) ->
|
||||
user = model.at('_user')
|
||||
tasks = user.get('tasks')
|
||||
|
||||
## Remove corrupted tasks
|
||||
_.each tasks, (task, key) ->
|
||||
unless task?.id? and task?.type?
|
||||
user.del("tasks.#{key}")
|
||||
delete tasks[key]
|
||||
true
|
||||
|
||||
resetDom = false
|
||||
batchTxn model, (uObj, paths, batch) ->
|
||||
|
||||
## fix https://github.com/lefnire/habitrpg/issues/1086
|
||||
uniqPets = _.uniq(uObj.items.pets)
|
||||
batch.set('items.pets', uniqPets) if !_.isEqual(uniqPets, uObj.items.pets)
|
||||
console.log {uniqPets, count:_.size(uniqPets)}
|
||||
|
||||
## Task List Cleanup
|
||||
['habit','daily','todo','reward'].forEach (type) ->
|
||||
|
||||
# 1. remove duplicates
|
||||
# 2. restore missing zombie tasks back into list
|
||||
idList = uObj["#{type}Ids"]
|
||||
taskIds = _.pluck( _.where(tasks, {type:type}), 'id')
|
||||
union = _.union idList, taskIds
|
||||
|
||||
# 2. remove empty (grey) tasks
|
||||
preened = _.filter union, (id) -> id and _.contains(taskIds, id)
|
||||
|
||||
# There were indeed issues found, set the new list
|
||||
if !_.isEqual(idList, preened)
|
||||
batch.set("#{type}Ids", preened)
|
||||
console.error uObj.id + "'s #{type}s were corrupt."
|
||||
true
|
||||
resetDom = !_.isEmpty(paths)
|
||||
require('./browser').resetDom(model) if resetDom
|
||||
|
||||
module.exports.viewHelpers = (view) ->
|
||||
|
||||
#misc
|
||||
|
|
|
|||
61
src/server/apiv2.coffee
Normal file
61
src/server/apiv2.coffee
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
express = require 'express'
|
||||
router = new express.Router()
|
||||
util = require('util')
|
||||
|
||||
_ = require 'lodash'
|
||||
algos = require 'habitrpg-shared/script/algos'
|
||||
helpers = require 'habitrpg-shared/script/helpers'
|
||||
validator = require 'derby-auth/node_modules/validator'
|
||||
check = validator.check
|
||||
sanitize = validator.sanitize
|
||||
misc = require '../app/misc'
|
||||
|
||||
NO_TOKEN_OR_UID = err: "You must include a token and uid (user id) in your request"
|
||||
NO_USER_FOUND = err: "No user found."
|
||||
|
||||
# ---------- /api/v1 API ------------
|
||||
# Every url added beneath router is prefaced by /api/v2
|
||||
|
||||
###
|
||||
API Status
|
||||
###
|
||||
router.get '/status', (req, res) ->
|
||||
res.json status: 'up'
|
||||
|
||||
###
|
||||
beforeEach auth interceptor
|
||||
###
|
||||
auth = (req, res, next) ->
|
||||
uid = req.headers['x-api-user']
|
||||
token = req.headers['x-api-key']
|
||||
return res.json 401, NO_TOKEN_OR_UID unless uid || token
|
||||
|
||||
model = req.getModel()
|
||||
query = model.query('users').withIdAndToken(uid, token)
|
||||
|
||||
query.fetch (err, user) ->
|
||||
return res.json err: err if err
|
||||
req.user = user
|
||||
req.userObj = user.get()
|
||||
return res.json 401, NO_USER_FOUND if !req.userObj || _.isEmpty(req.userObj)
|
||||
req._isServer = true
|
||||
next()
|
||||
|
||||
###
|
||||
POST new actions
|
||||
###
|
||||
router.post '/', auth, (req, res) ->
|
||||
actions = req.body
|
||||
if _.isArray actions
|
||||
actions.forEach (action)->
|
||||
switch action.op
|
||||
when score
|
||||
{}
|
||||
when newTask
|
||||
req.user.set "tasks.#{req.task.id}", action.task
|
||||
|
||||
console.log util.inspect req.body
|
||||
|
||||
res.json 200, req.userObj
|
||||
|
||||
module.exports = router
|
||||
|
|
@ -80,6 +80,7 @@ mongo_store = new MongoStore {url: process.env.NODE_DB_URI}, ->
|
|||
.use(middleware.translate)
|
||||
# API should be hit before all other routes
|
||||
.use('/api/v1', require('./api').middleware)
|
||||
.use('/api/v2', require('./apiv2').middleware)
|
||||
.use(require('./deprecated').middleware)
|
||||
# Show splash page for newcomers
|
||||
.use(middleware.splash)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
<li>
|
||||
<a rel=tooltip title='Edit Tags' x-bind="click:toggleEditingTags"><i class='{#if _editingTags}icon-ok{else}icon-pencil{/}'></i></a>
|
||||
</li>
|
||||
{#each _user.tags as :tag}
|
||||
<li class="{#if _user.filters[:tag.id]}active{/}" style='position:relative;'>
|
||||
{#each users[_userId].tags as :tag}
|
||||
<li class="{#if users[_userId].filters[:tag.id]}active{/}" style='position:relative;'>
|
||||
{#if _editingTags}
|
||||
<div class="input-append option-group tag-editing" >
|
||||
<input class="input input-small option-content tag-editing-pill" type="text" value='{:tag.name}' />
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
</form>
|
||||
{/}
|
||||
</li>
|
||||
<!--<li class="{#unless activeFilters(_user.filters)}hidden{/}">-->
|
||||
<!--<li class="{#unless activeFilters(users[_userId].filters)}hidden{/}">-->
|
||||
<li>
|
||||
<a rel=tooltip title='Clear Filters' x-bind="click:clearFilters"><i class='icon-remove-sign'></i></a>
|
||||
</li>
|
||||
|
|
@ -37,15 +37,15 @@
|
|||
</div>
|
||||
|
||||
<applied-filters:>
|
||||
<i rel=tooltip title="{appliedTags(_user.tags, :task.tags)}" class='{#if noTags(:task.tags)}hidden{/} icon-tags'></i>
|
||||
<i rel=tooltip title="{appliedTags(users[_userId].tags, :task.tags)}" class='{#if noTags(:task.tags)}hidden{/} icon-tags'></i>
|
||||
|
||||
<!-- At first we showed all applied tags, but it gets really cluttered: http://gyazo.com/fce50f91fd0f1d64cab9774f755e95c1 -->
|
||||
<!-- There's a very strange bug where live-bound #each here loses model.at reference on _{type}List alter -->
|
||||
<!--
|
||||
{{#each _user.tags as :tag}}
|
||||
{{#each users[_userId].tags as :tag}}
|
||||
<small>
|
||||
{#if :task.tags[:tag.id]}
|
||||
<small data-tag-id="{{:tag.id}}" x-bind="click:toggleFilterByTag" class="label tag-label {#if _user.filters[:tag.id]}label-info{/}">{:tag.name}</small>
|
||||
<small data-tag-id="{{:tag.id}}" x-bind="click:toggleFilterByTag" class="label tag-label {#if users[_userId].filters[:tag.id]}label-info{/}">{:tag.name}</small>
|
||||
{/}
|
||||
</small>
|
||||
{{/}}-->
|
||||
|
|
@ -53,9 +53,9 @@
|
|||
<filter-fieldgroup:>
|
||||
<fieldset class='option-group'>
|
||||
<legend class="option-title">Tags</legend>
|
||||
{{#each _user.tags as :tag}}
|
||||
{#each users[_userId].tags as :tag}
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" checked="{:task.tags[:tag.id]}"> {:tag.name}
|
||||
</label>
|
||||
{{/}}
|
||||
{/}
|
||||
</fieldset>
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
|
||||
<!-- all the parts of a single task -->
|
||||
<task:>
|
||||
<li data-id={{:task.id}} class="task {taskClasses(:task, _user.filters, _user.preferences.dayStart, _user.lastCron, _showCompleted)}">
|
||||
<li data-id={{:task.id}} class="task {taskClasses(:task, users[_userId].filters, _user.preferences.dayStart, _user.lastCron, _showCompleted)}">
|
||||
|
||||
<!-- right-hand side control buttons -->
|
||||
<div class="task-meta-controls">
|
||||
|
|
|
|||
Loading…
Reference in a new issue