rewrite: notifications!! also, surpressing _.extend user for now. need to fix ASAP!

This commit is contained in:
Tyler Renelle 2013-08-28 16:48:27 -04:00
parent 42f4e6f69c
commit 13a4aadfb4
5 changed files with 120 additions and 119 deletions

View file

@ -14,7 +14,6 @@ loadJavaScripts = (model) ->
###
Internal Scripts
###
require "../vendor/jquery-ui-1.10.2/jquery-1.9.1.js"
require "../vendor/jquery.cookie.min.js"
require "../vendor/bootstrap/js/bootstrap.min.js"
require "../vendor/jquery.bootstrap-growl.min.js"
@ -22,47 +21,14 @@ loadJavaScripts = (model) ->
require "../vendor/bootstrap-tour/bootstrap-tour"
unless (model.get('_mobileDevice') is true)
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.core.js"
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.widget.js"
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.mouse.js"
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.sortable.js"
require "../vendor/sticky"
# note: external script loading is handled in app.on('render') near the bottom of this file (see https://groups.google.com/forum/?fromgroups=#!topic/derbyjs/x8FwdTLEuXo)
###
Setup jQuery UI Sortable
###
setupSortable = (model) ->
unless (model.get('_mobileDevice') is true) #don't do sortable on mobile
['habit', 'daily', 'todo', 'reward'].forEach (type) ->
$("ul.#{type}s").sortable
dropOnEmpty: false
cursor: "move"
items: "li"
scroll: true
axis: 'y'
update: (e, ui) ->
item = ui.item[0]
domId = item.id
id = item.getAttribute 'data-id'
to = $("ul.#{type}s").children().index(item)
# Use the Derby ignore option to suppress the normal move event
# binding, since jQuery UI will move the element in the DOM.
# Also, note that refList index arguments can either be an index
# or the item's id property
model.at("_#{type}List").pass(ignore: domId).move {id}, to
setupTooltips = module.exports.setupTooltips = ->
$('[rel=tooltip]').tooltip()
$('[rel=popover]').popover()
$('.popover-auto-show').popover('show')
$('.priority-multiplier-help').popover
title: "How difficult is this task?"
trigger: "hover"
content: "This multiplies its point value. Use sparingly, rely instead on our organic value-adjustment algorithms. But some tasks are grossly more valuable (Write Thesis vs Floss Teeth). Click for more info."
setupTour = (model) ->
tourSteps = [
{
@ -118,87 +84,9 @@ setupTour = (model) ->
initStickyHeader = (model) ->
$('.header-wrap').sticky({topSpacing:0})
growlNotification = module.exports.growlNotification = (html, type) ->
$.bootstrapGrowl html,
ele: '#notification-area',
type: type # (null, 'info', 'error', 'success', 'gp', 'xp', 'hp', 'lvl','death')
top_offset: 20
align: 'right' # ('left', 'right', or 'center')
width: 250 # (integer, or 'auto')
delay: 3000
allow_dismiss: true
stackup_spacing: 10 # spacing between consecutive stacecked growls.
###
Sets up "+1 Exp", "Level Up", etc notifications
###
setupGrowlNotifications = (model) ->
return unless jQuery? # Only run this in the browser
user = model.at '_user'
statsNotification = (html, type) ->
return if user.get('stats.lvl') == 0 #don't show notifications if user dead
growlNotification(html, type)
# Setup listeners which trigger notifications
user.on 'set', 'stats.hp', (captures, args) ->
num = captures - args
rounded = Math.abs(num.toFixed(1))
if num < 0
statsNotification "<i class='icon-heart'></i> - #{rounded} HP", 'hp' # lost hp from purchase
else if num > 0
statsNotification "<i class='icon-heart'></i> + #{rounded} HP", 'hp' # gained hp from potion/level?
user.on 'set', 'stats.exp', (captures, args, isLocal, silent=false) ->
# unless silent
num = captures - args
rounded = Math.abs(num.toFixed(1))
if num < 0 and num > -50 # TODO fix hackey negative notification supress
statsNotification "<i class='icon-star'></i> - #{rounded} XP", 'xp'
else if num > 0
statsNotification "<i class='icon-star'></i> + #{rounded} XP", 'xp'
###
Show "+ 5 {gold_coin} 3 {silver_coin}"
###
showCoins = (money) ->
absolute = Math.abs(money)
gold = Math.floor(absolute)
silver = Math.floor((absolute-gold)*100)
if gold and silver > 0
return "#{gold} <i class='icon-gold'></i> #{silver} <i class='icon-silver'></i>"
else if gold > 0
return "#{gold} <i class='icon-gold'></i>"
else if silver > 0
return "#{silver} <i class='icon-silver'></i>"
user.on 'set', 'stats.gp', (captures, args) ->
money = captures - args
return unless !!money # why is this happening? gotta find where stats.gp is being set from (-)habit
sign = if money < 0 then '-' else '+'
statsNotification "#{sign} #{showCoins(money)}", 'gp'
# Append Bonus
bonus = model.get('_streakBonus')
if (money > 0) and !!bonus
bonus = 0.01 if bonus < 0.01
statsNotification "+ #{showCoins(bonus)} Streak Bonus!"
model.del('_streakBonus')
user.on 'set', 'items.*', (item, after, before) ->
if item in ['armor','weapon','shield','head'] and parseInt(after) < parseInt(before)
item = 'helm' if item is 'head' # don't want to day "lost a head"
statsNotification "<i class='icon-death'></i> Respawn!", "death"
user.on 'set', 'stats.lvl', (captures, args) ->
if captures > args
statsNotification '<i class="icon-chevron-up"></i> Level Up!', 'lvl'
module.exports.app = (appExports, model, app) ->
loadJavaScripts(model)
setupGrowlNotifications(model) unless model.get('_mobileDevice')
app.on 'render', (ctx) ->
#restoreRefs(model)

View file

@ -1,9 +1,118 @@
'use strict';
habitrpg.controller('NotificationCtrl',
['$scope', 'Notification',
function ($scope, Notification) {
$scope.data = Notification.get();
['$scope', '$rootScope', 'User', function ($scope, $rootScope, User) {
function growlNotification(html, type) {
$.bootstrapGrowl(html, {
ele: '#notification-area',
type: type, //(null, 'info', 'error', 'success', 'gp', 'xp', 'hp', 'lvl','death')
top_offset: 20,
align: 'right', //('left', 'right', or 'center')
width: 250, //(integer, or 'auto')
delay: 3000,
allow_dismiss: true,
stackup_spacing: 10 // spacing between consecutive stacecked growls.
});
};
/*
Sets up "+1 Exp", "Level Up", etc notifications
*/
function setupGrowlNotifications() {
function statsNotification(html, type) {
// don't show notifications if user dead
if (User.user.stats.lvl == 0) return;
growlNotification(html, type);
};
/**
Show "+ 5 {gold_coin} 3 {silver_coin}"
*/
function showCoins(money) {
var absolute, gold, silver;
absolute = Math.abs(money);
gold = Math.floor(absolute);
silver = Math.floor((absolute - gold) * 100);
if (gold && silver > 0) {
return "" + gold + " <i class='icon-gold'></i> " + silver + " <i class='icon-silver'></i>";
} else if (gold > 0) {
return "" + gold + " <i class='icon-gold'></i>";
} else if (silver > 0) {
return "" + silver + " <i class='icon-silver'></i>";
}
};
$rootScope.$watch('user.stats.hp', function(after, before) {
if (after == before) return;
var num = after - before;
var rounded = Math.abs(num.toFixed(1));
if (num < 0) {
//lost hp from purchase
statsNotification("<i class='icon-heart'></i> - " + rounded + " HP", 'hp');
} else if (num > 0) {
// gained hp from potion/level?
statsNotification("<i class='icon-heart'></i> + " + rounded + " HP", 'hp');
}
});
$rootScope.$watch('user.stats.exp', function(after, before) {
if (after == before) return;
var num = after - before;
var rounded = Math.abs(num.toFixed(1));
// TODO fix hackey negative notification supress
if (num < 0 && num > -50) {
statsNotification("<i class='icon-star'></i> - " + rounded + " XP", 'xp');
} else if (num > 0) {
statsNotification("<i class='icon-star'></i> + " + rounded + " XP", 'xp');
}
});
$rootScope.$watch('user.stats.gp', function(after, before) {
if (after == before) return;
var bonus, money, sign;
money = after - before;
//why is this happening? gotta find where stats.gp is being set from (-)habit
//if (!money) {
// return;
//}
sign = money < 0 ? '-' : '+';
statsNotification("" + sign + " " + (showCoins(money)), 'gp');
//Append Bonus TODO
//bonus = model.get('_streakBonus');
if ((money > 0) && !!bonus) {
if (bonus < 0.01) {
bonus = 0.01;
}
statsNotification("+ " + (showCoins(bonus)) + " Streak Bonus!");
//model.del('_streakBonus');
}
});
// FIXME
// user.on('set', 'items.*', function(item, after, before) {
// if ((item === 'armor' || item === 'weapon' || item === 'shield' || item === 'head') && parseInt(after) < parseInt(before)) {
// //don't want to day "lost a head"
// if (item === 'head') {
// item = 'helm';
// }
// return statsNotification("<i class='icon-death'></i> Respawn!", "death");
// }
// });
$rootScope.$watch('user.stats.lvl', function(after, before) {
if (after == before) return;
if (after > before) {
statsNotification('<i class="icon-chevron-up"></i> Level Up!', 'lvl');
}
});
};
setupGrowlNotifications();
}
]);

View file

@ -59,14 +59,17 @@ angular.module('userServices', []).
sent.push(queue.shift());
});
$http.post(API_URL + '/api/v1/user/batch-update' + '?date=' + new Date().getTime(), sent)
.success(function (data, status, heacreatingders, config) {
data.tasks = _.toArray(data.tasks);
//make sure there are no pending actions to sync. If there are any it is not safe to apply model from server as we may overwrite user data.
if (!queue.length) {
//we can't do user=data as it will not update user references in all other angular controllers.
_.extend(user, data);
// FIXME - this is the one of the biggest issues in Habit rewrite right now, this function
// kills CPU and makes it things un-responsive. We need to only update the user when it's been
// modified, not every time. Commenting this out makes it out-of-sync with the API though
//_.extend(user, data);
// FIXME handle this somewhere else, we don't need to check every single time
var offset = moment().zone(); // eg, 240 - this will be converted on server as -(offset/60)

View file

@ -24,6 +24,7 @@ html
script(type='text/javascript', src='/bower_components/jquery/jquery.min.js')
script(type='text/javascript', src='/bower_components/lodash/lodash.js')
script(type='text/javascript', src='/bower_components/moment/moment.js')
script(type='text/javascript', src='/bower_components/bootstrap-growl/jquery.bootstrap-growl.min.js')
script(type='text/javascript', src='/bower_components/angular/angular.js')
script(type='text/javascript', src='/bower_components/angular-route/angular-route.js')
script(type='text/javascript', src='/bower_components/angular-resource/angular-resource.js')
@ -75,7 +76,7 @@ html
app:filters:filters(ng-hide='_gamePane')
br
#notification-area
#notification-area(ng-controller='NotificationCtrl')
#wrap
// Errors

View file

@ -128,7 +128,7 @@ li(ng-repeat='task in user[list.type + "s"]', class='task {{taskClasses(task,use
p.option-title.mega(ng-click='task._advanced = !task._advanced') Advanced Options
fieldset.option-group.advanced-option(ng-class="{visuallyhidden: !task._advanced}")
legend.option-title
a.priority-multiplier-help(href='https://trello.com/card/priority-multiplier/50e5d3684fe3a7266b0036d6/17', target='_blank')
a.priority-multiplier-help(href='https://trello.com/card/priority-multiplier/50e5d3684fe3a7266b0036d6/17', target='_blank', popover-title='How difficult is this task?', popover-trigger='mouseenter', popover="This multiplies its point value. Use sparingly, rely instead on our organic value-adjustment algorithms. But some tasks are grossly more valuable (Write Thesis vs Floss Teeth). Click for more info.")
i.icon-question-sign
| Difficulty
// {{#if taskInChallenge(task)}}