mirror of
https://github.com/sudoxnym/habitica-self-host.git
synced 2026-07-21 21:34:15 +00:00
Merge branch 'develop' of https://github.com/HabitRPG/habitrpg into develop
This commit is contained in:
commit
facdca48b0
35 changed files with 342 additions and 309 deletions
|
|
@ -30,7 +30,7 @@
|
|||
"bootstrap": "~3.1.0",
|
||||
"bootstrap-growl": "git://github.com/ifightcrime/bootstrap-growl.git#master",
|
||||
"bootstrap-tour": "~0.8.1",
|
||||
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git#develop",
|
||||
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared.git",
|
||||
"BrowserQuest": "git://github.com/mozilla/BrowserQuest.git",
|
||||
"github-buttons": "git://github.com/mdo/github-buttons.git",
|
||||
"marked": "~0.2.9",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"version": "0.0.0-152",
|
||||
"main": "./src/server.js",
|
||||
"dependencies": {
|
||||
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#develop",
|
||||
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared",
|
||||
"connect-mongo": "*",
|
||||
"express": "3.5.x",
|
||||
"gzippo": "*",
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||
"public": Groups.publicGuilds()
|
||||
}
|
||||
$scope.type = 'guild';
|
||||
$scope.text = 'Guild';
|
||||
$scope.text = window.env.t('guild');
|
||||
var newGroup = function(){
|
||||
return new Groups.Group({type:'guild', privacy:'private'});
|
||||
}
|
||||
|
|
@ -316,7 +316,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||
.controller("PartyCtrl", ['$rootScope','$scope', 'Groups', 'User', 'Challenges', '$state', '$compile',
|
||||
function($rootScope,$scope, Groups, User, Challenges, $state, $compile) {
|
||||
$scope.type = 'party';
|
||||
$scope.text = 'Party';
|
||||
$scope.text = window.env.t('party');
|
||||
$scope.group = $rootScope.party = Groups.party();
|
||||
$scope.newGroup = new Groups.Group({type:'party'});
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User',
|
|||
var food = $scope.selectedFood
|
||||
if (food.key == 'Saddle') {
|
||||
if (!$window.confirm(window.env.t('useSaddle', {pet: pet}))) return;
|
||||
} else if (!$window.confirm(window.env.t('feedPet', {name: petDisplayName, article: food.article, text: food.text}))) {
|
||||
} else if (!$window.confirm(window.env.t('feedPet', {name: petDisplayName, article: food.article, text: food.text()}))) {
|
||||
return;
|
||||
}
|
||||
User.user.ops.feed({params:{pet: pet, food: food.key}});
|
||||
|
|
@ -124,7 +124,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User',
|
|||
var item = Content.quests[quest];
|
||||
var completedPrevious = !item.previous || (User.user.achievements.quests && User.user.achievements.quests[item.previous]);
|
||||
if (!completedPrevious)
|
||||
return alert(window.env.t('mustComplete', {quest: $rootScope.Content.quests[item.previous].text}));
|
||||
return alert(window.env.t('mustComplete', {quest: $rootScope.Content.quests[item.previous].text()}));
|
||||
if (item.lvl && item.lvl > user.stats.lvl)
|
||||
return alert(window.env.t('mustLevel', {level: item.lvl}));
|
||||
$rootScope.selectedQuest = item;
|
||||
|
|
|
|||
|
|
@ -204,11 +204,11 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
|
|||
|
||||
$http.post('/api/v2/user/class/cast/'+spell.key+'?targetType='+type+'&targetId='+targetId)
|
||||
.success(function(){
|
||||
var msg = window.env.t('youCast', {spell: spell.text});
|
||||
var msg = window.env.t('youCast', {spell: spell.text()});
|
||||
switch (type) {
|
||||
case 'task': msg = window.env.t('youCastTarget', {spell: spell.text, target: target.text});break;
|
||||
case 'user': msg = window.env.t('youCastTarget', {spell: spell.text, target: target.profile.name});break;
|
||||
case 'party': msg = window.env.t('youCastParty', {spell: spell.text});break;
|
||||
case 'task': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.text});break;
|
||||
case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break;
|
||||
case 'party': msg = window.env.t('youCastParty', {spell: spell.text()});break;
|
||||
}
|
||||
Notification.text(msg);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,9 +12,5 @@ if(window.moment && window.env.language && window.env.language.momentLang && win
|
|||
window.moment.lang(window.env.language.momentLangCode);
|
||||
}
|
||||
|
||||
window.env.t = function(stringName, vars){
|
||||
var string = window.env.translations[stringName];
|
||||
if(!string) return window._.template(window.env.translations.stringNotFound, {string: stringName});
|
||||
|
||||
return vars === undefined ? string : window._.template(string, vars);
|
||||
}
|
||||
window.habitrpgShared.i18n.strings = window.env.translations;
|
||||
window.env.t = window.habitrpgShared.i18n.t;
|
||||
|
|
@ -78,6 +78,13 @@ angular.module('guideServices', []).
|
|||
});
|
||||
$('.main-herobox').popover('destroy');
|
||||
var tour = new Tour({
|
||||
template: "<div class='popover'>" +
|
||||
"<div class='arrow'></div><h3 class='popover-title'></h3><div class='popover-content'></div>" +
|
||||
"<div class='popover-navigation'><div class='btn-group'>" +
|
||||
"<button class='btn btn-sm btn-default' data-role='prev'>«</button>" +
|
||||
"<button class='btn btn-sm btn-default' data-role='next'>»</button>" +
|
||||
"<button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button></div>" +
|
||||
"<button class='btn btn-sm btn-default' data-role='end'>" + window.env.t('endTour') + "</button></div></div>",
|
||||
onEnd: function(){
|
||||
User.set({'flags.showTour': false});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ api.registerUser = function(req, res, next) {
|
|||
timestamps: {created: +new Date(), loggedIn: +new Date()}
|
||||
}
|
||||
};
|
||||
newUser.preferences = newUser.preferences || {};
|
||||
newUser.preferences.language = req.language; // User language detected from browser, not saved
|
||||
user = new User(newUser);
|
||||
|
||||
// temporary for conventions
|
||||
|
|
@ -255,7 +257,11 @@ api.setupPassport = function(router) {
|
|||
},
|
||||
function(user, cb){
|
||||
if (user) return cb(null, user);
|
||||
|
||||
user = new User({
|
||||
preferences: {
|
||||
language: req.language // User language detected from browser, not saved
|
||||
},
|
||||
auth: {
|
||||
facebook: req.user,
|
||||
timestamps: {created: +new Date(), loggedIn: +new Date()}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ api.score = function(req, res, next) {
|
|||
if (task.type === 'daily' || task.type === 'todo')
|
||||
task.completed = direction === 'up';
|
||||
}
|
||||
var delta = user.ops.score({params:{id:task.id, direction:direction}});
|
||||
var delta = user.ops.score({params:{id:task.id, direction:direction}, language: req.language});
|
||||
|
||||
user.save(function(err,saved){
|
||||
if (err) return next(err);
|
||||
|
|
@ -336,7 +336,7 @@ api.cast = function(req, res, next) {
|
|||
|
||||
if (group) {
|
||||
series.push(function(cb2){
|
||||
var message = '`'+user.profile.name+' casts '+spell.text + (targetType=='user' ? ' on '+found.profile.name : ' for the party')+'.`';
|
||||
var message = '`'+user.profile.name+' casts '+spell.text() + (targetType=='user' ? ' on '+found.profile.name : ' for the party')+'.`';
|
||||
group.sendChat(message);
|
||||
group.save(cb2);
|
||||
})
|
||||
|
|
@ -397,6 +397,8 @@ api.batchUpdate = function(req, res, next) {
|
|||
res.locals.ops = [];
|
||||
var ops = _.transform(req.body, function(m,_req){
|
||||
if (_.isEmpty(_req)) return;
|
||||
_req.language = req.language;
|
||||
|
||||
m.push(function() {
|
||||
var cb = arguments[arguments.length-1];
|
||||
res.locals.ops.push(_req);
|
||||
|
|
|
|||
97
src/i18n.js
Normal file
97
src/i18n.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
_ = require('lodash'),
|
||||
User = require('./models/user').model,
|
||||
shared = require('habitrpg-shared'),
|
||||
translations = {};
|
||||
|
||||
var loadTranslations = function(locale){
|
||||
var files = fs.readdirSync(path.join(__dirname, "/../node_modules/habitrpg-shared/locales/", locale));
|
||||
translations[locale] = {};
|
||||
_.each(files, function(file){
|
||||
_.merge(translations[locale], require(path.join(__dirname, "/../node_modules/habitrpg-shared/locales/", locale, file)));
|
||||
});
|
||||
};
|
||||
|
||||
// First fetch english so we can merge with missing strings in other languages
|
||||
loadTranslations('en');
|
||||
|
||||
fs.readdirSync(path.join(__dirname, "/../node_modules/habitrpg-shared/locales/")).forEach(function(file) {
|
||||
if(file === 'en' || file === 'README.md') return;
|
||||
loadTranslations(file);
|
||||
// Merge missing strings from english
|
||||
_.defaults(translations[file], translations.en);
|
||||
});
|
||||
|
||||
var langCodes = Object.keys(translations);
|
||||
|
||||
var avalaibleLanguages = _.map(langCodes, function(langCode){
|
||||
return {
|
||||
code: langCode,
|
||||
name: translations[langCode].languageName
|
||||
}
|
||||
});
|
||||
|
||||
// Load MomentJS localization files
|
||||
var momentLangs = {};
|
||||
|
||||
// Handle different language codes from MomentJS and /locales
|
||||
var momentLangsMapping = {
|
||||
'en': 'en-gb',
|
||||
'no': 'nn'
|
||||
};
|
||||
|
||||
var momentLangs = {};
|
||||
|
||||
_.each(langCodes, function(code){
|
||||
var lang = _.find(avalaibleLanguages, {code: code});
|
||||
lang.momentLangCode = (momentLangsMapping[code] || code);
|
||||
try{
|
||||
// MomentJS lang files are JS files that has to be executed in the browser so we load them as plain text files
|
||||
var f = fs.readFileSync(path.join(__dirname, '/../node_modules/moment/lang/' + lang.momentLangCode + '.js'), 'utf8');
|
||||
momentLangs[code] = f;
|
||||
}catch (e){}
|
||||
});
|
||||
|
||||
var getUserLanguage = function(req, res, next){
|
||||
var getFromBrowser = function(){
|
||||
var acceptable = _(req.acceptedLanguages).map(function(lang){
|
||||
return lang.slice(0, 2);
|
||||
}).uniq().value();
|
||||
var matches = _.intersection(acceptable, langCodes);
|
||||
return matches.length > 0 ? matches[0] : 'en';
|
||||
};
|
||||
|
||||
var getFromUser = function(user){
|
||||
var lang;
|
||||
if(user && user.preferences.language && translations[user.preferences.language]){
|
||||
lang = user.preferences.language;
|
||||
}else{
|
||||
var preferred = getFromBrowser();
|
||||
lang = translations[preferred] ? preferred : 'en';
|
||||
}
|
||||
req.language = lang;
|
||||
next();
|
||||
};
|
||||
|
||||
if(req.locals && req.locals.user){
|
||||
getFromUser(req.locals.user);
|
||||
}else if(req.session && req.session.userId){
|
||||
User.findOne({_id: req.session.userId}, function(err, user){
|
||||
if(err) return callback(err);
|
||||
getFromUser(user);
|
||||
});
|
||||
}else{
|
||||
getFromUser(null);
|
||||
}
|
||||
};
|
||||
|
||||
shared.i18n.translations = translations;
|
||||
|
||||
module.exports = {
|
||||
translations: translations,
|
||||
avalaibleLanguages: avalaibleLanguages,
|
||||
langCodes: langCodes,
|
||||
getUserLanguage: getUserLanguage,
|
||||
momentLangs: momentLangs
|
||||
};
|
||||
|
|
@ -7,6 +7,8 @@ var limiter = require('connect-ratelimit');
|
|||
var logging = require('./logging');
|
||||
var domainMiddleware = require('domain-middleware');
|
||||
var cluster = require('cluster');
|
||||
var i18n = require('./i18n.js');
|
||||
var shared = require('habitrpg-shared');
|
||||
|
||||
module.exports.apiThrottle = function(app) {
|
||||
if (nconf.get('NODE_ENV') !== 'production') return;
|
||||
|
|
@ -139,121 +141,34 @@ var getManifestFiles = function(page){
|
|||
return code;
|
||||
}
|
||||
|
||||
// Translations
|
||||
|
||||
var translations = {};
|
||||
|
||||
var loadTranslations = function(locale){
|
||||
var files = fs.readdirSync(path.join(__dirname, "/../node_modules/habitrpg-shared/locales/", locale));
|
||||
translations[locale] = {};
|
||||
_.each(files, function(file){
|
||||
_.merge(translations[locale], require(path.join(__dirname, "/../node_modules/habitrpg-shared/locales/", locale, file)));
|
||||
});
|
||||
};
|
||||
|
||||
// First fetch english so we can merge with missing strings in other languages
|
||||
loadTranslations('en');
|
||||
|
||||
fs.readdirSync(path.join(__dirname, "/../node_modules/habitrpg-shared/locales/")).forEach(function(file) {
|
||||
if(file === 'en') return;
|
||||
loadTranslations(file);
|
||||
// Merge missing strings from english
|
||||
_.defaults(translations[file], translations.en);
|
||||
});
|
||||
|
||||
var langCodes = Object.keys(translations);
|
||||
|
||||
var avalaibleLanguages = _.map(langCodes, function(langCode){
|
||||
return {
|
||||
code: langCode,
|
||||
name: translations[langCode].languageName
|
||||
}
|
||||
});
|
||||
|
||||
// Load MomentJS localization files
|
||||
var momentLangs = {};
|
||||
|
||||
// Handle different language codes from MomentJS and /locales
|
||||
var momentLangsMapping = {
|
||||
'en': 'en-gb',
|
||||
'no': 'nn'
|
||||
};
|
||||
|
||||
var momentLangs = {};
|
||||
|
||||
_.each(langCodes, function(code){
|
||||
var lang = _.find(avalaibleLanguages, {code: code});
|
||||
lang.momentLangCode = (momentLangsMapping[code] || code);
|
||||
try{
|
||||
// MomentJS lang files are JS files that has to be executed in the browser so we load them as plain text files
|
||||
var f = fs.readFileSync(path.join(__dirname, '/../node_modules/moment/lang/' + lang.momentLangCode + '.js'), 'utf8');
|
||||
momentLangs[code] = f;
|
||||
}catch (e){}
|
||||
});
|
||||
|
||||
var getUserLanguage = function(req, callback){
|
||||
var getFromBrowser = function(){
|
||||
var acceptable = _(req.acceptedLanguages).map(function(lang){
|
||||
return lang.slice(0, 2);
|
||||
}).uniq().value();
|
||||
var matches = _.intersection(acceptable, langCodes);
|
||||
return matches.length > 0 ? matches[0] : 'en';
|
||||
};
|
||||
|
||||
if(req.session && req.session.userId){
|
||||
User.findOne({_id: req.session.userId}, function(err, user){
|
||||
if(err) return callback(err);
|
||||
if(user && user.preferences.language && translations[user.preferences.language]){
|
||||
return callback(null, _.find(avalaibleLanguages, {code: user.preferences.language}));
|
||||
}else{
|
||||
var langCode = getFromBrowser();
|
||||
// Because english is usually always avalaible as an acceptable language for the browser,
|
||||
// if the user visit the page when his own language is not avalaible yet
|
||||
// he'll have english set in his preferences, which is not good.
|
||||
//if(user && translations[langCode]){
|
||||
//user.preferences.language = langCode;
|
||||
//user.save(); //callback?
|
||||
//}
|
||||
return callback(null, _.find(avalaibleLanguages, {code: langCode}))
|
||||
}
|
||||
});
|
||||
}else{
|
||||
return callback(null, _.find(avalaibleLanguages, {code: getFromBrowser()}));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.locals = function(req, res, next) {
|
||||
getUserLanguage(req, function(err, language){
|
||||
if(err) return res.json(500, {err: err});
|
||||
var language = _.find(i18n.avalaibleLanguages, {code: req.language});
|
||||
var isStaticPage = req.url.split('/')[1] === 'static'; // If url contains '/static/'
|
||||
|
||||
var isStaticPage = req.url.split('/')[1] === 'static'; // If url contains '/static/'
|
||||
// Load moment.js language file only when not on static pages
|
||||
language.momentLang = ((!isStaticPage && i18n.momentLangs[language.code]) || undefined);
|
||||
|
||||
// Load moment.js language file only when not on static pages
|
||||
language.momentLang = ((!isStaticPage && momentLangs[language.code])|| undefined);
|
||||
res.locals.habitrpg = {
|
||||
NODE_ENV: nconf.get('NODE_ENV'),
|
||||
BASE_URL: nconf.get('BASE_URL'),
|
||||
GA_ID: nconf.get("GA_ID"),
|
||||
IS_MOBILE: /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')),
|
||||
STRIPE_PUB_KEY: nconf.get('STRIPE_PUB_KEY'),
|
||||
getManifestFiles: getManifestFiles,
|
||||
getBuildUrl: getBuildUrl,
|
||||
avalaibleLanguages: i18n.avalaibleLanguages,
|
||||
language: language,
|
||||
isStaticPage: isStaticPage,
|
||||
translations: i18n.translations[language.code],
|
||||
t: function(){ // stringName and vars are the allowed parameters
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
args.push(language.code);
|
||||
return shared.i18n.t.apply(null, args);
|
||||
},
|
||||
siteVersion: siteVersion
|
||||
}
|
||||
|
||||
res.locals.habitrpg = {
|
||||
NODE_ENV: nconf.get('NODE_ENV'),
|
||||
BASE_URL: nconf.get('BASE_URL'),
|
||||
GA_ID: nconf.get("GA_ID"),
|
||||
IS_MOBILE: /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')),
|
||||
STRIPE_PUB_KEY: nconf.get('STRIPE_PUB_KEY'),
|
||||
getManifestFiles: getManifestFiles,
|
||||
getBuildUrl: getBuildUrl,
|
||||
avalaibleLanguages: avalaibleLanguages,
|
||||
language: language,
|
||||
isStaticPage: isStaticPage,
|
||||
translations: translations[language.code],
|
||||
t: function(stringName, vars){
|
||||
var string = translations[language.code][stringName];
|
||||
if(!string) return _.template(translations[language.code].stringNotFound, {string: stringName});
|
||||
|
||||
return vars === undefined ? string : _.template(string, vars);
|
||||
},
|
||||
siteVersion: siteVersion
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
module.exports.enTranslations = function(stringName, vars){
|
||||
|
|
|
|||
|
|
@ -305,14 +305,14 @@ var UserSchema = new Schema({
|
|||
id: { type: String, 'default': shared.uuid },
|
||||
name: String,
|
||||
challenge: String
|
||||
}], 'default': shared.content.userDefaults.tags},
|
||||
}]},
|
||||
|
||||
challenges: [{type: 'String', ref:'Challenge'}],
|
||||
|
||||
habits: {type:[TaskSchemas.HabitSchema], 'default': shared.content.userDefaults.habits},
|
||||
dailys: {type:[TaskSchemas.DailySchema], 'default': shared.content.userDefaults.dailys},
|
||||
todos: {type:[TaskSchemas.TodoSchema], 'default': shared.content.userDefaults.todos},
|
||||
rewards: {type:[TaskSchemas.RewardSchema], 'default': shared.content.userDefaults.rewards},
|
||||
habits: {type:[TaskSchemas.HabitSchema]},
|
||||
dailys: {type:[TaskSchemas.DailySchema]},
|
||||
todos: {type:[TaskSchemas.TodoSchema]},
|
||||
rewards: {type:[TaskSchemas.RewardSchema]},
|
||||
|
||||
extra: Schema.Types.Mixed
|
||||
|
||||
|
|
@ -348,6 +348,31 @@ UserSchema.post('init', function(doc){
|
|||
|
||||
UserSchema.pre('save', function(next) {
|
||||
|
||||
// Populate new users with default content
|
||||
if (this.isNew){
|
||||
//TODO for some reason this doesn't work here: `_.merge(this, shared.content.userDefaults);`
|
||||
var self = this;
|
||||
_.each(['habits', 'dailys', 'todos', 'rewards', 'tags'], function(taskType){
|
||||
self[taskType] = _.map(shared.content.userDefaults[taskType], function(task){
|
||||
var newTask = task;
|
||||
|
||||
// Render task's text and notes in user's language
|
||||
if(taskType === 'tags'){
|
||||
// tasks automatically get id=helpers.uuid() from TaskSchema id.default, but tags are Schema.Types.Mixed - so we need to manually invoke here
|
||||
newTask.id = shared.uuid();
|
||||
newTask.name = task.name(self.preferences.language);
|
||||
}else{
|
||||
newTask.text = task.text(self.preferences.language);
|
||||
newTask.notes = task.notes(self.preferences.language);
|
||||
}
|
||||
|
||||
return newTask;
|
||||
});
|
||||
});
|
||||
|
||||
this.preferences.language = undefined;
|
||||
}
|
||||
|
||||
//this.markModified('tasks');
|
||||
if (_.isNaN(this.preferences.dayStart) || this.preferences.dayStart < 0 || this.preferences.dayStart > 23) {
|
||||
this.preferences.dayStart = 0;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ middleware = require("../middleware")
|
|||
cron = user.cron
|
||||
_ = require('lodash')
|
||||
content = require('habitrpg-shared').content
|
||||
i18n = require('../i18n')
|
||||
|
||||
|
||||
module.exports = (swagger, v2) ->
|
||||
|
|
@ -47,7 +48,7 @@ module.exports = (swagger, v2) ->
|
|||
spec:
|
||||
description: "Export user history"
|
||||
method: 'GET'
|
||||
middleware: auth.auth
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: dataexport.history #[todo] encode data output options in the data controller and use these to build routes
|
||||
|
||||
# ---------------------------------
|
||||
|
|
@ -138,7 +139,7 @@ module.exports = (swagger, v2) ->
|
|||
path("id", "Task ID", "string")
|
||||
query 'keep',"When unlinking a challenge task, how to handle the orphans?",'string',['keep','keep-all','remove','remove-all']
|
||||
]
|
||||
middleware: auth.auth ## removing cron since they may want to remove task first
|
||||
middleware: [auth.auth, i18n.getUserLanguage] ## removing cron since they may want to remove task first
|
||||
action: challenges.unlink
|
||||
|
||||
|
||||
|
|
@ -227,7 +228,7 @@ module.exports = (swagger, v2) ->
|
|||
path: '/user'
|
||||
method: 'DELETE'
|
||||
description: "Delete a user object entirely, USE WITH CAUTION!"
|
||||
middleware: auth.auth
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: user["delete"]
|
||||
|
||||
"/user/revive":
|
||||
|
|
@ -306,7 +307,7 @@ module.exports = (swagger, v2) ->
|
|||
parameters:[
|
||||
body '','The array of batch-operations to perform','object'
|
||||
]
|
||||
middleware: [middleware.forceRefresh, auth.auth, cron]
|
||||
middleware: [middleware.forceRefresh, auth.auth, i18n.getUserLanguage, cron]
|
||||
action: user.batchUpdate
|
||||
|
||||
# Tags
|
||||
|
|
@ -350,7 +351,7 @@ module.exports = (swagger, v2) ->
|
|||
parameters: [
|
||||
query 'type',"Comma-separated types of groups to return, eg 'party,guilds,public,tavern'",'string'
|
||||
]
|
||||
middleware: auth.auth
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: groups.list
|
||||
|
||||
|
||||
|
|
@ -362,7 +363,7 @@ module.exports = (swagger, v2) ->
|
|||
parameters: [
|
||||
body '','Group object (see GroupSchema)','object'
|
||||
]
|
||||
middleware: auth.auth
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: groups.create
|
||||
|
||||
"/groups/{gid}:GET":
|
||||
|
|
@ -370,7 +371,7 @@ module.exports = (swagger, v2) ->
|
|||
path: '/groups/{gid}'
|
||||
description: "Get a group"
|
||||
parameters: [path('gid','Group ID','string')]
|
||||
middleware: auth.auth
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: groups.get
|
||||
|
||||
"/groups/{gid}:POST":
|
||||
|
|
@ -379,7 +380,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: "Edit a group"
|
||||
parameters: [body('','Group object (see GroupSchema)','object')]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.update
|
||||
|
||||
"/groups/{gid}/join":
|
||||
|
|
@ -387,7 +388,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: 'Join a group'
|
||||
parameters: [path('gid','Id of the group to join','string')]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.join
|
||||
|
||||
"/groups/{gid}/leave":
|
||||
|
|
@ -395,7 +396,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: 'Leave a group'
|
||||
parameters: [path('gid','ID of the group to leave','string')]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.leave
|
||||
|
||||
"/groups/{gid}/invite":
|
||||
|
|
@ -406,7 +407,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'gid','Group id','string'
|
||||
query 'uuid','User id to invite','string'
|
||||
]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action:groups.invite
|
||||
|
||||
"/groups/{gid}/removeMember":
|
||||
|
|
@ -417,7 +418,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'gid','Group id','string'
|
||||
query 'uuid','User id to boot','string'
|
||||
]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action:groups.removeMember
|
||||
|
||||
"/groups/{gid}/questAccept":
|
||||
|
|
@ -428,7 +429,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'gid',"Group id",'string'
|
||||
query 'key',"optional. if provided, trigger new invite, if not, accept existing invite",'string'
|
||||
]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action:groups.questAccept
|
||||
|
||||
"/groups/{gid}/questReject":
|
||||
|
|
@ -438,7 +439,7 @@ module.exports = (swagger, v2) ->
|
|||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.questReject
|
||||
|
||||
"/groups/{gid}/questAbort":
|
||||
|
|
@ -446,7 +447,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: 'Abort quest'
|
||||
parameters: [path('gid','Group to abort quest in','string')]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.questAbort
|
||||
|
||||
#TODO PUT /groups/:gid/chat/:messageId
|
||||
|
|
@ -456,7 +457,7 @@ module.exports = (swagger, v2) ->
|
|||
path: "/groups/{gid}/chat"
|
||||
description: "Get all chat messages"
|
||||
parameters: [path('gid','Group to return the chat from ','string')]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.getChat
|
||||
|
||||
|
||||
|
|
@ -469,7 +470,7 @@ module.exports = (swagger, v2) ->
|
|||
query 'message', 'Chat message','string'
|
||||
path 'gid','Group id','string'
|
||||
]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.postChat
|
||||
|
||||
# placing before route below, so that if !=='seen' it goes to next()
|
||||
|
|
@ -480,7 +481,7 @@ module.exports = (swagger, v2) ->
|
|||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
]
|
||||
middleware: []
|
||||
middleware: [i18n.getUserLanguage]
|
||||
action: groups.seenMessage
|
||||
|
||||
"/groups/{gid}/chat/{messageId}":
|
||||
|
|
@ -488,7 +489,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'DELETE'
|
||||
description: 'Delete a group'
|
||||
parameters: [path('gid','ID of group to delete','string')]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.deleteChatMessage
|
||||
|
||||
"/groups/{gid}/chat/{mid}/like":
|
||||
|
|
@ -499,7 +500,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'gid','Group id','string'
|
||||
path 'mid','Message id','string'
|
||||
]
|
||||
middleware: [auth.auth, groups.attachGroup]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.likeChatMessage
|
||||
|
||||
# ---------------------------------
|
||||
|
|
@ -514,19 +515,19 @@ module.exports = (swagger, v2) ->
|
|||
# ---------------------------------
|
||||
"/hall/heroes":
|
||||
spec: {}
|
||||
middleware:[auth.auth]
|
||||
middleware:[auth.auth, i18n.getUserLanguage]
|
||||
action: hall.getHeroes
|
||||
|
||||
"/hall/heroes/{uid}:GET":
|
||||
spec: path: "/hall/heroes/{uid}"
|
||||
middleware:[auth.auth, hall.ensureAdmin]
|
||||
middleware:[auth.auth, i18n.getUserLanguage, hall.ensureAdmin]
|
||||
action: hall.getHero
|
||||
|
||||
"/hall/heroes/{uid}:POST":
|
||||
spec:
|
||||
method: 'POST'
|
||||
path: "/hall/heroes/{uid}"
|
||||
middleware: [auth.auth, hall.ensureAdmin]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, hall.ensureAdmin]
|
||||
action: hall.updateHero
|
||||
|
||||
"/hall/patrons":
|
||||
|
|
@ -534,7 +535,7 @@ module.exports = (swagger, v2) ->
|
|||
parameters: [
|
||||
query 'page','Page number to fetch (this list is long)','string'
|
||||
]
|
||||
middleware:[auth.auth]
|
||||
middleware:[auth.auth, i18n.getUserLanguage]
|
||||
action: hall.getPatrons
|
||||
|
||||
|
||||
|
|
@ -549,7 +550,7 @@ module.exports = (swagger, v2) ->
|
|||
spec:
|
||||
path: '/challenges'
|
||||
description: "Get a list of challenges"
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.list
|
||||
|
||||
|
||||
|
|
@ -559,7 +560,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: "Create a challenge"
|
||||
parameters: [body('','Challenge object (see ChallengeSchema)','object')]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.create
|
||||
|
||||
"/challenges/{cid}:GET":
|
||||
|
|
@ -584,7 +585,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'cid','Challenge id','string'
|
||||
body('','Challenge object (see ChallengeSchema)','object')
|
||||
]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.update
|
||||
|
||||
"/challenges/{cid}:DELETE":
|
||||
|
|
@ -593,7 +594,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'DELETE'
|
||||
description: "Delete a challenge"
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges["delete"]
|
||||
|
||||
"/challenges/{cid}/close":
|
||||
|
|
@ -604,7 +605,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'cid','Challenge id','string'
|
||||
query 'uid','User ID of the winner','string',true
|
||||
]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.selectWinner
|
||||
|
||||
"/challenges/{cid}/join":
|
||||
|
|
@ -612,7 +613,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: "Join a challenge"
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.join
|
||||
|
||||
"/challenges/{cid}/leave":
|
||||
|
|
@ -620,7 +621,7 @@ module.exports = (swagger, v2) ->
|
|||
method: 'POST'
|
||||
description: 'Leave a challenge'
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.leave
|
||||
|
||||
"/challenges/{cid}/member/{uid}":
|
||||
|
|
@ -630,7 +631,7 @@ module.exports = (swagger, v2) ->
|
|||
path 'cid','Challenge id','string'
|
||||
path 'uid','User id','string'
|
||||
]
|
||||
middleware: [auth.auth]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.getMember
|
||||
|
||||
|
||||
|
|
@ -662,7 +663,7 @@ module.exports = (swagger, v2) ->
|
|||
#type: 'Pet'
|
||||
errorResponses: []
|
||||
method: 'GET'
|
||||
route.middleware ?= if path.indexOf('/user') is 0 then [auth.auth, cron] else []
|
||||
route.middleware ?= if path.indexOf('/user') is 0 then [auth.auth, i18n.getUserLanguage, cron] else []
|
||||
swagger["add#{route.spec.method}"](route);true
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
var auth = require('../controllers/auth');
|
||||
var express = require('express');
|
||||
var i18n = require('../i18n');
|
||||
var router = new express.Router();
|
||||
|
||||
/* auth.auth*/
|
||||
auth.setupPassport(router); //FIXME make this consistent with the others
|
||||
router.post('/api/v2/register', auth.registerUser);
|
||||
router.post('/api/v2/user/auth/local', auth.loginLocal);
|
||||
router.post('/api/v2/user/auth/facebook', auth.loginFacebook);
|
||||
router.post('/api/v2/user/reset-password', auth.resetPassword);
|
||||
router.post('/api/v2/user/change-password', auth.auth, auth.changePassword);
|
||||
router.post('/api/v2/register', i18n.getUserLanguage, auth.registerUser);
|
||||
router.post('/api/v2/user/auth/local', i18n.getUserLanguage, auth.loginLocal);
|
||||
router.post('/api/v2/user/auth/facebook', i18n.getUserLanguage, auth.loginFacebook);
|
||||
router.post('/api/v2/user/reset-password', i18n.getUserLanguage, auth.resetPassword);
|
||||
router.post('/api/v2/user/change-password', i18n.getUserLanguage, auth.auth, auth.changePassword);
|
||||
|
||||
router.post('/api/v1/register', auth.registerUser);
|
||||
router.post('/api/v1/user/auth/local', auth.loginLocal);
|
||||
router.post('/api/v1/user/auth/facebook', auth.loginFacebook);
|
||||
router.post('/api/v1/register', i18n.getUserLanguage, auth.registerUser);
|
||||
router.post('/api/v1/user/auth/local', i18n.getUserLanguage, auth.loginLocal);
|
||||
router.post('/api/v1/user/auth/facebook', i18n.getUserLanguage, auth.loginFacebook);
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -3,10 +3,11 @@ var router = new express.Router();
|
|||
var dataexport = require('../controllers/dataexport');
|
||||
var auth = require('../controllers/auth');
|
||||
var nconf = require('nconf');
|
||||
var i18n = require('../i18n')
|
||||
|
||||
/* Data export */
|
||||
router.get('/history.csv',auth.authWithSession,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes
|
||||
router.get('/userdata.xml',auth.authWithSession,dataexport.leanuser,dataexport.userdata.xml);
|
||||
router.get('/userdata.json',auth.authWithSession,dataexport.leanuser,dataexport.userdata.json);
|
||||
router.get('/history.csv',auth.authWithSession,i18n.getUserLanguage,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes
|
||||
router.get('/userdata.xml',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.xml);
|
||||
router.get('/userdata.json',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.json);
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ var _ = require('lodash');
|
|||
var middleware = require('../middleware');
|
||||
var user = require('../controllers/user');
|
||||
var auth = require('../controllers/auth');
|
||||
var i18n = require('../i18n');
|
||||
|
||||
// -------- App --------
|
||||
router.get('/', middleware.locals, function(req, res) {
|
||||
router.get('/', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
if (!req.headers['x-api-user'] && !req.headers['x-api-key'] && !(req.session && req.session.userId))
|
||||
return res.redirect('/static/front')
|
||||
|
||||
|
|
@ -19,35 +20,35 @@ router.get('/', middleware.locals, function(req, res) {
|
|||
|
||||
// -------- Marketing --------
|
||||
|
||||
router.get('/static/front', middleware.locals, function(req, res) {
|
||||
router.get('/static/front', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/front', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/privacy', middleware.locals, function(req, res) {
|
||||
router.get('/static/privacy', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/privacy', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/terms', middleware.locals, function(req, res) {
|
||||
router.get('/static/terms', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/terms', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/api', middleware.locals, function(req, res) {
|
||||
router.get('/static/api', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/api', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/features', middleware.locals, function(req, res) {
|
||||
router.get('/static/features', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/features', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/videos', middleware.locals, function(req, res) {
|
||||
router.get('/static/videos', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/videos', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/contact', middleware.locals, function(req, res) {
|
||||
router.get('/static/contact', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/contact', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
router.get('/static/plans', middleware.locals, function(req, res) {
|
||||
router.get('/static/plans', i18n.getUserLanguage, middleware.locals, function(req, res) {
|
||||
res.render('static/plans', {env: res.locals.habitrpg});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ if (cluster.isMaster && (isDev || isProd)) {
|
|||
var swagger = require("swagger-node-express");
|
||||
var autoinc = require('mongoose-id-autoinc');
|
||||
|
||||
// Setup translations
|
||||
var i18n = require('./i18n');
|
||||
|
||||
var middleware = require('./middleware');
|
||||
|
||||
var TWO_WEEKS = 1000 * 60 * 60 * 24 * 14;
|
||||
|
|
|
|||
|
|
@ -28,30 +28,4 @@ describe('Root Controller', function() {
|
|||
expect(scope.contribText({level: 8, text: 'Blacksmith'}, {npc: 'NPC'})).to.eql('NPC');
|
||||
});
|
||||
|
||||
describe('i18n', function(){
|
||||
var t = env.t;
|
||||
beforeEach(function(){
|
||||
env.translations = {
|
||||
"text1": 'translatedText1',
|
||||
"text2": '<%= number %> eggs',
|
||||
"stringNotFound" : "String '<%= string %>' not found.",
|
||||
};
|
||||
});
|
||||
|
||||
it('translates strings', function(){
|
||||
expect(t('')).to.eql("String '' not found.");
|
||||
expect(t('text1')).to.eql('translatedText1');
|
||||
expect(t(' text1 ')).to.eql("String ' text1 ' not found.");
|
||||
expect(t('text3')).to.eql("String 'text3' not found.");
|
||||
});
|
||||
|
||||
it('interpolates strings', function(){
|
||||
expect(t('text2', {number: 2})).to.eql('2 eggs');
|
||||
expect(t('text2', {number: 'ten'})).to.eql('ten eggs');
|
||||
expect(t('text2', {n: 10, number: 'ten'})).to.eql('ten eggs');
|
||||
expect(t('text2')).to.eql('<%= number %> eggs');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
|
@ -4,9 +4,9 @@ script(type='text/ng-template', id='partials/options.inventory.equipment.html')
|
|||
.col-md-6.border-right
|
||||
h3.equipment-title.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('battleGearText'))=env.t('battleGear')
|
||||
li.customize-menu.inventory-gear
|
||||
menu.pets-menu(label='{{label}}', ng-repeat='(klass,label) in {warrior:"Warrior", wizard:"Mage", rogue:"Rogue", healer:"Healer", special:"Special", mystery:"Mystery"}', ng-show='gear[klass]')
|
||||
menu.pets-menu(label='{{label}}', ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery")}', ng-show='gear[klass]')
|
||||
div(ng-repeat='item in gear[klass]')
|
||||
button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='user.ops.equip({params:{key:item.key}})', class='shop_{{item.key}}', ng-class='{selectableInventory: user.items.gear.equipped[item.type] == item.key}')
|
||||
button.customize-option(popover='{{item.notes()}}', popover-title='{{item.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='user.ops.equip({params:{key:item.key}})', class='shop_{{item.key}}', ng-class='{selectableInventory: user.items.gear.equipped[item.type] == item.key}')
|
||||
.col-md-6
|
||||
h3.equipment-title.hint(popover-trigger='mouseenter', popover-placement='right', popover=env.t('costumeText'))=env.t('costume')
|
||||
.checkbox.equipment-title
|
||||
|
|
@ -15,9 +15,9 @@ script(type='text/ng-template', id='partials/options.inventory.equipment.html')
|
|||
|
|
||||
=env.t('useCostume')
|
||||
li.customize-menu(ng-if='user.preferences.costume')
|
||||
menu.pets-menu(label='{{label}}', ng-repeat='(klass,label) in {warrior:"Warrior", wizard:"Mage", rogue:"Rogue", healer:"Healer", special:"Special", mystery:"Mystery"}', ng-show='gear[klass]')
|
||||
menu.pets-menu(label='{{label}}', ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery")}', ng-show='gear[klass]')
|
||||
div(ng-repeat='item in gear[klass]')
|
||||
button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='user.ops.equip({params:{type:"costume", key:item.key}})', class='shop_{{item.key}}', ng-class='{selectableInventory: user.items.gear.costume[item.type] == item.key}')
|
||||
button.customize-option(popover='{{item.notes()}}', popover-title='{{item.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='user.ops.equip({params:{type:"costume", key:item.key}})', class='shop_{{item.key}}', ng-class='{selectableInventory: user.items.gear.costume[item.type] == item.key}')
|
||||
|
||||
script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
||||
.container-fluid
|
||||
|
|
@ -32,36 +32,36 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
|||
p.muted(ng-show='eggCount < 1')=env.t('noEggs')
|
||||
div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)')
|
||||
//TODO move positioning this styling to css
|
||||
button.customize-option(popover='{{Content.eggs[egg].notes}}', popover-title='{{Content.eggs[egg].text}} Egg', popover-trigger='mouseenter', popover-placement='right', ng-click='chooseEgg(egg)', class='Pet_Egg_{{egg}}', ng-class='{selectableInventory: selectedPotion && !(user.items.pets[egg+"-"+selectedPotion.key]>0)}')
|
||||
button.customize-option(popover='{{Content.eggs[egg].notes()}}', popover-title!=env.t("egg", {eggType: "{{Content.eggs[egg].text()}}"}), popover-trigger='mouseenter', popover-placement='right', ng-click='chooseEgg(egg)', class='Pet_Egg_{{egg}}', ng-class='{selectableInventory: selectedPotion && !(user.items.pets[egg+"-"+selectedPotion.key]>0)}')
|
||||
.badge.badge-info.stack-count {{points}}
|
||||
//-p {{Content.eggs[egg].text}}
|
||||
//-p {{Content.eggs[egg].text()}}
|
||||
|
||||
li.customize-menu
|
||||
menu.hatchingPotion-menu(label=(env.t('hatchingPotions') + ' ({{potCount}})'))
|
||||
p.muted(ng-show='potCount < 1')=env.t('noHatchingPotions')
|
||||
div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)')
|
||||
button.customize-option(popover='{{Content.hatchingPotions[pot].notes}}', popover-title='{{Content.hatchingPotions[pot].text}} Potion', popover-trigger='mouseenter', popover-placement='right', ng-click='choosePotion(pot)', class='Pet_HatchingPotion_{{pot}}', ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0)}')
|
||||
button.customize-option(popover='{{Content.hatchingPotions[pot].notes()}}', popover-title!=env.t("potion", {potionType: "{{Content.hatchingPotions[pot].text()}}"}), popover-trigger='mouseenter', popover-placement='right', ng-click='choosePotion(pot)', class='Pet_HatchingPotion_{{pot}}', ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0)}')
|
||||
.badge.badge-info.stack-count {{points}}
|
||||
|
||||
li.customize-menu
|
||||
menu.pets-menu(label=(env.t('scrolls') + ' ({{questCount}})'))
|
||||
menu.pets-menu(label=(env.t('quests') + ' ({{questCount}})'))
|
||||
p.muted(ng-show='questCount < 1')=env.t('noScrolls')
|
||||
p.muted!=env.t('scrollsText1') + ' <a href="/#/options/groups/party">' + env.t('scrollsText2') + '</a>'
|
||||
div(ng-repeat='(quest_key,points) in ownedItems(user.items.quests)', ng-init='quest = Content.quests[quest_key]')
|
||||
button.customize-option(popover="{{quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : quest.notes | htmlDecode}}", popover-title='{{quest.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='showQuest(quest_key)', class='inventory_quest_scroll', ng-class='{locked: quest.previous && !user.achievements.quests[quest.previous]}')
|
||||
button.customize-option(popover="{{quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : quest.notes() | htmlDecode}}", popover-title='{{quest.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='showQuest(quest_key)', class='inventory_quest_scroll', ng-class='{locked: quest.previous && !user.achievements.quests[quest.previous]}')
|
||||
.badge.badge-info.stack-count {{points}}
|
||||
|
||||
li.customize-menu
|
||||
menu.pets-menu(label=env.t('food') + ' ({{foodCount}})')
|
||||
p(ng-show='foodCount < 1')=env.t('noFood')
|
||||
div(ng-repeat='(food,points) in ownedItems(user.items.food)')
|
||||
button.customize-option(popover='{{Content.food[food].notes}}', popover-title='{{Content.food[food].text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='chooseFood(food)', class='Pet_Food_{{food}}')
|
||||
button.customize-option(popover='{{Content.food[food].notes()}}', popover-title='{{Content.food[food].text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='chooseFood(food)', class='Pet_Food_{{food}}')
|
||||
.badge.badge-info.stack-count {{points}}
|
||||
|
||||
li.customize-menu(ng-if='user.items.special.snowball')
|
||||
menu.pets-menu(label=env.t('special'))
|
||||
div
|
||||
button.customize-option(popover='{{Content.special.snowball.notes}}', popover-title='{{Content.special.snowball.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='castStart(Content.special.snowball)', class='inventory_special_snowball')
|
||||
button.customize-option(popover='{{Content.special.snowball.notes()}}', popover-title='{{Content.special.snowball.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='castStart(Content.special.snowball)', class='inventory_special_snowball')
|
||||
.badge.badge-info.stack-count {{user.items.special.snowball}}
|
||||
|
||||
li.customize-menu(ng-if='user.items.special.valentineReceived[0]')
|
||||
|
|
@ -91,29 +91,29 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
|||
.popover-content
|
||||
p=env.t('welcomeMarket')
|
||||
p
|
||||
button.btn.btn-primary(ng-show='selectedEgg', ng-click='sellInventory()')=env.t('sellForGold', {item: "{{selectedEgg.text}}", gold: "{{selectedEgg.value}}"})
|
||||
button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()')=env.t('sellForGold', {item: "{{selectedPotion.text}}", gold: "{{selectedPotion.value}}"})
|
||||
button.btn.btn-primary(ng-show='selectedFood', ng-click='sellInventory()')=env.t('sellForGold', {item: "{{selectedFood.text}}", gold: "{{selectedFood.value}}"})
|
||||
button.btn.btn-primary(ng-show='selectedEgg', ng-click='sellInventory()')=env.t('sellForGold', {item: "{{selectedEgg.text()}}", gold: "{{selectedEgg.value}}"})
|
||||
button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()')=env.t('sellForGold', {item: "{{selectedPotion.text()}}", gold: "{{selectedPotion.value}}"})
|
||||
button.btn.btn-primary(ng-show='selectedFood', ng-click='sellInventory()')=env.t('sellForGold', {item: "{{selectedFood.text()}}", gold: "{{selectedFood.value}}"})
|
||||
menu.inventory-list(type='list')
|
||||
li.customize-menu
|
||||
menu.pets-menu(label=env.t('eggs'))
|
||||
div(ng-repeat='egg in Content.eggs', ng-if='egg.canBuy')
|
||||
button.customize-option(popover='{{egg.notes}}', popover-title='{{egg.text}} Egg', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", egg)', class='Pet_Egg_{{egg.key}}')
|
||||
button.customize-option(popover='{{egg.notes()}}', popover-title!=env.t("egg", {eggType: "{{egg.text()}}"}), popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", egg)', class='Pet_Egg_{{egg.key}}')
|
||||
p
|
||||
| {{egg.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
div(ng-show='user.achievements.quests.gryphon > 1')
|
||||
button.customize-option(popover='{{Content.eggs.Gryphon.notes}}', popover-title='{{Content.eggs.Gryphon.text}} Egg', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", Content.eggs.Gryphon)', class='Pet_Egg_Gryphon')
|
||||
button.customize-option(popover='{{Content.eggs.Gryphon.notes()}}', popover-title!=env.t("egg", {eggType: "{{Content.eggs.Gryphon.text()}}"}), popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", Content.eggs.Gryphon)', class='Pet_Egg_Gryphon')
|
||||
p
|
||||
| {{Content.eggs.Gryphon.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
div(ng-show='user.achievements.quests.hedgehog > 1')
|
||||
button.customize-option(popover='{{Content.eggs.Hedgehog.notes}}', popover-title='{{Content.eggs.Hedgehog.text}} Egg', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", Content.eggs.Hedgehog)', class='Pet_Egg_Hedgehog')
|
||||
button.customize-option(popover='{{Content.eggs.Hedgehog.notes()}}', popover-title!=env.t("egg", {eggType: "{{Content.eggs.Hedgehog.text()}}"}), popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", Content.eggs.Hedgehog)', class='Pet_Egg_Hedgehog')
|
||||
p
|
||||
| {{Content.eggs.Hedgehog.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
div(ng-show='user.achievements.quests.ghost_stag > 1')
|
||||
button.customize-option(popover='{{Content.eggs.Deer.notes}}', popover-title='{{Content.eggs.Deer.text}} Egg', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", Content.eggs.Deer)', class='Pet_Egg_Deer')
|
||||
button.customize-option(popover='{{Content.eggs.Deer.notes()}}', popover-title!=env.t("egg", {eggType: "{{Content.eggs.Deer.text()}}"}), popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("eggs", Content.eggs.Deer)', class='Pet_Egg_Deer')
|
||||
p
|
||||
| {{Content.eggs.Deer.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
|
|
@ -121,7 +121,7 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
|||
li.customize-menu
|
||||
menu.pets-menu(label=env.t('hatchingPotions'))
|
||||
div(ng-repeat='pot in Content.hatchingPotions')
|
||||
button.customize-option(popover='{{pot.notes}}', popover-title='{{pot.text}} Potion', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("hatchingPotions", pot)', class='Pet_HatchingPotion_{{pot.key}}')
|
||||
button.customize-option(popover='{{pot.notes()}}', popover-title!=env.t("potion", {potionType: "{{pot.text()}}"}), popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("hatchingPotions", pot)', class='Pet_HatchingPotion_{{pot.key}}')
|
||||
p
|
||||
| {{pot.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
|
|
@ -129,7 +129,7 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
|||
li.customize-menu
|
||||
menu.pets-menu(label=env.t('food'))
|
||||
div(ng-repeat='food in Content.food', ng-if='food.canBuy')
|
||||
button.customize-option(popover='{{food.notes}}', popover-title='{{food.text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("food", food)', class='Pet_Food_{{food.key}}')
|
||||
button.customize-option(popover='{{food.notes()}}', popover-title='{{food.text()}}', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("food", food)', class='Pet_Food_{{food.key}}')
|
||||
p
|
||||
| {{food.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
|
|
@ -138,7 +138,7 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
|||
menu.pets-menu(label=env.t('quests'))
|
||||
p.muted!=env.t('scrollsText1') + ' <a href="/#/options/groups/party">' + env.t('scrollsText2') + '</a>'
|
||||
div(ng-repeat='quest in Content.quests', ng-if='quest.canBuy')
|
||||
button.customize-option(popover="{{quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : quest.notes | htmlDecode}}", popover-title='{{quest.text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='buyQuest(quest.key)', class='inventory_quest_scroll', ng-class='{locked: quest.previous && !user.achievements.quests[quest.previous]}')
|
||||
button.customize-option(popover="{{quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : quest.notes() | htmlDecode}}", popover-title='{{quest.text()}}', popover-trigger='mouseenter', popover-placement='left', ng-click='buyQuest(quest.key)', class='inventory_quest_scroll', ng-class='{locked: quest.previous && !user.achievements.quests[quest.previous]}')
|
||||
p
|
||||
| {{quest.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
|
|
@ -151,7 +151,7 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
|
|||
| 4
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
//-div
|
||||
button.customize-option(popover='{{Content.spells.special.snowball.notes}}', popover-title='{{Content.spells.special.snowball.text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("special", Content.spells.special.snowball)', class='inventory_special_snowball')
|
||||
button.customize-option(popover='{{Content.spells.special.snowball.notes()}}', popover-title='{{Content.spells.special.snowball.text()}}', popover-trigger='mouseenter', popover-placement='left', ng-click='purchase("special", Content.spells.special.snowball)', class='inventory_special_snowball')
|
||||
p
|
||||
| {{Content.spells.special.snowball.value}}
|
||||
span.Pet_Currency_Gem1x.inline-gems
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ script(type='text/ng-template', id='partials/options.inventory.mounts.html')
|
|||
menu.pets(type='list')
|
||||
li.customize-menu(ng-repeat='egg in Content.eggs')
|
||||
menu
|
||||
div(ng-repeat='potion in Content.hatchingPotions', popover-trigger='mouseenter', popover='{{potion.text}} {{egg.mountText}}', popover-placement='bottom', ng-init='mount = egg.key+"-"+potion.key')
|
||||
div(ng-repeat='potion in Content.hatchingPotions', popover-trigger='mouseenter', popover=env.t('mountName', {potion: '{{potion.text()}}', mount: '{{egg.mountText()}}'}), popover-placement='bottom', ng-init='mount = egg.key+"-"+potion.key')
|
||||
button(class="pet-button Mount_Head_{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.key, potion.key)')
|
||||
//div(class='Mount_Head_{{mount}}')
|
||||
button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]')
|
||||
|
|
@ -33,7 +33,7 @@ mixin petList(source)
|
|||
menu.pets(type='list')
|
||||
li.customize-menu(ng-repeat='egg in #{source}')
|
||||
menu
|
||||
div(ng-repeat='potion in Content.hatchingPotions', popover-trigger='mouseenter', popover='{{potion.text}} {{egg.text}}', popover-placement='bottom', ng-init='pet = egg.key+"-"+potion.key')
|
||||
div(ng-repeat='potion in Content.hatchingPotions', popover-trigger='mouseenter', popover=env.t('petName', {potion: '{{potion.text()}}', egg: '{{egg.text()}}'}), popover-placement='bottom', ng-init='pet = egg.key+"-"+potion.key')
|
||||
button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet, selectableInventory: selectedFood}', ng-click='choosePet(egg.key, potion.key)')
|
||||
.progress(ng-show='!user.items.mounts[pet] && egg.key!="Egg"')
|
||||
.progress-bar.progress-bar-success(style="width:{{user.items.pets[pet]/.5}}%")
|
||||
|
|
@ -85,7 +85,7 @@ script(type='text/ng-template', id='partials/options.inventory.pets.html')
|
|||
li.customize-menu
|
||||
menu.pets-menu(label=env.t('food'))
|
||||
div(ng-repeat='(food,points) in ownedItems(user.items.food)')
|
||||
button.customize-option(popover-append-to-body='true', popover='{{Content.food[food].notes}}', popover-title='{{Content.food[food].text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='chooseFood(food)', class='Pet_Food_{{food}}')
|
||||
button.customize-option(popover-append-to-body='true', popover='{{Content.food[food].notes()}}', popover-title='{{Content.food[food].text()}}', popover-trigger='mouseenter', popover-placement='left', ng-click='chooseFood(food)', class='Pet_Food_{{food}}')
|
||||
.badge.badge-info.stack-count {{points}}
|
||||
// Remove this once we have images in
|
||||
p {{Content.food[food].text}}
|
||||
p {{Content.food[food].text()}}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ mixin customizeProfile(mobile)
|
|||
|
||||
// Flower
|
||||
li.customize-menu
|
||||
menu(label="Flower")
|
||||
menu(label=env.t('flower'))
|
||||
button(class='head_0 customize-option', type='button', ng-click='set({"preferences.hair.flower":0})')
|
||||
each num in [1,2,3,4,5,6]
|
||||
button(class='hair_flower_#{num} customize-option', type='button', ng-click='set({"preferences.hair.flower":#{num}})')
|
||||
|
|
@ -141,7 +141,7 @@ script(id='partials/options.profile.stats.html', type='text/ng-template')
|
|||
h3=env.t('characterBuild')
|
||||
h4
|
||||
=env.t('class') + ': '
|
||||
span {{ {warrior:'Warrior',wizard:'Mage',healer:'Healer',rogue:'Rogue'}[user.stats.class] }}
|
||||
span {{ {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer")}[user.stats.class] }}
|
||||
a.btn.btn-danger.btn-xs(ng-click='changeClass(null)')=env.t('changeClass')
|
||||
small.cost 3 <span class="Pet_Currency_Gem1x inline-gems"/>
|
||||
table.table.table-striped
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
h3.panel-title=env.t('challenges')
|
||||
|
||||
a.pull-right(target='_blank', href='https://trello.com/card/challenges-individual-party-guild-public/50e5d3684fe3a7266b0036d6/58')
|
||||
small
|
||||
="More info"
|
||||
small=env.t('moreInfo')
|
||||
.panel-body.modal-fixed-height(bindonce='group.challenges')
|
||||
div(ng-if='group.challenges.length > 0')
|
||||
table.table.table-striped
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ script(type='text/ng-template', id='partials/options.social.challenges.html')
|
|||
input.form-control(type='text', minlength="3", maxlength="16", ng-model='newChallenge.shortName', placeholder=env.t('challengeTag'), required)
|
||||
|
||||
a.hint.vertical-20(target='_blank', href='http://habitrpg.wikia.com/wiki/Tags', popover=env.t('challengeTagPop'), popover-trigger='mouseenter', popover-placement='right')
|
||||
="More info"
|
||||
=env.t('moreInfo')
|
||||
|
||||
.form-group
|
||||
textarea.form-control(cols='3', placeholder=env.t('challengeDescr'), ng-model='newChallenge.description')
|
||||
|
|
@ -121,7 +121,7 @@ script(type='text/ng-template', id='partials/options.social.challenges.html')
|
|||
span.input-suffix.Pet_Currency_Gem1x.inline-gems
|
||||
|
||||
span.hint.vertical-20(popover=env.t('prizePop'), popover-trigger='mouseenter', popover-placement='right')
|
||||
="More info"
|
||||
=env.t('moreInfo')
|
||||
span(ng-show='newChallenge.group=="habitrpg"')
|
||||
!=env.t('publicChallenges')
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@
|
|||
.row
|
||||
form.col-md-12.form-horizontal(ng-submit='create(newGroup)')
|
||||
.form-group
|
||||
label.control-label(for='new-group-name')
|
||||
| {{text}}
|
||||
=env.t('name')
|
||||
input.form-control#new-group-name.input-medium.option-content(required, type='text', placeholder=('{{text}} ' + env.t('name')), ng-model='newGroup.name')
|
||||
label.control-label(for='new-group-name')=env.t('newGroupName', {groupType: "{{text}}"})
|
||||
input.form-control#new-group-name.input-medium.option-content(required, type='text', placeholder=env.t('newGroupName', {groupType: "{{text}}"}), ng-model='newGroup.name')
|
||||
.form-group
|
||||
label(for='new-group-description')=env.t('description')
|
||||
textarea.form-control#new-group-description.option-content(cols='3', placeholder=env.t('description'), ng-model='newGroup.description')
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ a.pull-right.gem-wallet(popover-trigger='mouseenter', popover-title=env.t('guild
|
|||
// ------ Bosses -------
|
||||
.panel.panel-default(bindonce='group', ng-if='group.type==="party" && group.quest.key')
|
||||
.panel-heading
|
||||
h3.panel-title(ng-if='group.quest.active==false')=env.t('questInvitation') + ' {{Content.quests[group.quest.key].text}}'
|
||||
h3.panel-title(ng-if='group.quest.active==true') {{Content.quests[group.quest.key].text}}
|
||||
h3.panel-title(ng-if='group.quest.active==false')=env.t('questInvitation') + ' {{Content.quests[group.quest.key].text()}}'
|
||||
h3.panel-title(ng-if='group.quest.active==true') {{Content.quests[group.quest.key].text()}}
|
||||
.panel-body.modal-fixed-height
|
||||
div(ng-if='group.quest.active==false')
|
||||
table.table.table-striped
|
||||
|
|
@ -50,11 +50,11 @@ a.pull-right.gem-wallet(popover-trigger='mouseenter', popover-title=env.t('guild
|
|||
tr(ng-repeat='(k,v) in group.quest.progress.collect', class='quest_collected_{{v >= Content.quests[group.quest.key].collect[k].count}}')
|
||||
td
|
||||
div.pull-left(class='quest_{{group.quest.key}}_{{k}}')
|
||||
| {{Content.quests[group.quest.key].collect[k].text}}
|
||||
| {{Content.quests[group.quest.key].collect[k].text()}}
|
||||
td
|
||||
{{v}} / {{Content.quests[group.quest.key].collect[k].count}}
|
||||
|
||||
div(ng-bind-html='Content.quests[group.quest.key].notes')
|
||||
div(ng-bind-html='Content.quests[group.quest.key].notes()')
|
||||
hr
|
||||
h5=env.t('participants')
|
||||
table.table.table-striped
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ script(type='text/ng-template', id='partials/options.social.party.html')
|
|||
{{user.id}}
|
||||
p
|
||||
=env.t('startLFG')
|
||||
|
|
||||
a(href="http://habitrpg.wikia.com/wiki/Board:The_Archery_-_LFG")=env.t('linkLFG')
|
||||
|
|
||||
=env.t('endLFG')
|
||||
include ./create-group
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
//Why is shown? Because of script here at line 24!!!!!!!!!
|
||||
script(id='modals/buyGems.html', type='text/ng-template')
|
||||
.modal-body
|
||||
.buy-gems
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ script(type='text/ng-template', id='modals/dropsEnabled.html')
|
|||
p
|
||||
figure
|
||||
.item-drop-icon(class='Pet_Egg_Wolf')
|
||||
span!=env.t('firstDrop', {eggText: "{{Content.eggs.Wolf.text}}", eggNotes: "{{Content.eggs.Wolf.notes}}"})
|
||||
span!=env.t('firstDrop', {eggText: "{{Content.eggs.Wolf.text()}}", eggNotes: "{{Content.eggs.Wolf.notes()}}"})
|
||||
br
|
||||
p
|
||||
figure
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
script(type='text/ng-template', id='modals/newStuff.html')
|
||||
.modal-header
|
||||
h4 New Stuff!
|
||||
h4=env.t('newStuff')
|
||||
.modal-body.new-stuff-modal.modal-fixed-height
|
||||
table
|
||||
tr
|
||||
|
|
@ -723,5 +723,5 @@ script(type='text/ng-template', id='modals/newStuff.html')
|
|||
a(href='https://trello.com/card/custom-day-start/50e5d3684fe3a7266b0036d6/15') Add custom day start
|
||||
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='$close()') Cool
|
||||
button.btn.btn-warning(ng-click='dismissAlert(); $close()') Dismiss This Alert
|
||||
button.btn.btn-default(ng-click='$close()')=env.t('cool')
|
||||
button.btn.btn-warning(ng-click='dismissAlert(); $close()')=env.t('dismissAlert')
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ script(id='partials/options.social.party.quest-rewards.html', type='text/ng-temp
|
|||
h5 {{header}}
|
||||
table.table.table-striped
|
||||
tr(ng-repeat='drop in quest.drop.items')
|
||||
td {{drop.text}}
|
||||
td {{drop.text()}}
|
||||
tr
|
||||
td {{quest.drop.exp}}
|
||||
=env.t('experience')
|
||||
|
|
@ -13,20 +13,20 @@ script(id='partials/options.social.party.quest-rewards.html', type='text/ng-temp
|
|||
|
||||
script(type='text/ng-template', id='modals/questCompleted.html')
|
||||
.modal-header
|
||||
h4 "{{Content.quests[user.party.quest.completed].text}}"
|
||||
h4 "{{Content.quests[user.party.quest.completed].text()}}"
|
||||
=env.t('completed')
|
||||
.modal-body
|
||||
p {{Content.quests[user.party.quest.completed].completion}}
|
||||
p {{Content.quests[user.party.quest.completed].completion()}}
|
||||
quest-rewards(key='{{user.party.quest.completed}}', header=env.t('youReceived'))
|
||||
.modal-footer
|
||||
button.btn.btn-primary(ng-click='set({"party.quest.completed":""}); $close()')=env.t('accept')
|
||||
|
||||
script(type='text/ng-template', id='modals/showQuest.html')
|
||||
.modal-header
|
||||
h4 {{selectedQuest.text}}
|
||||
h4 {{selectedQuest.text()}}
|
||||
.modal-body
|
||||
.pull-right(class='quest_{{selectedQuest.key}}')
|
||||
div(ng-bind-html='selectedQuest.notes')
|
||||
div(ng-bind-html='selectedQuest.notes()')
|
||||
quest-rewards(key='{{selectedQuest.key}}')
|
||||
hr
|
||||
.npc_ian.pull-left
|
||||
|
|
@ -38,10 +38,10 @@ script(type='text/ng-template', id='modals/showQuest.html')
|
|||
|
||||
script(type='text/ng-template', id='modals/buyQuest.html')
|
||||
.modal-header
|
||||
h4 {{selectedQuest.text}}
|
||||
h4 {{selectedQuest.text()}}
|
||||
.modal-body
|
||||
.pull-right(class='quest_{{selectedQuest.key}}')
|
||||
div(ng-bind-html='selectedQuest.notes')
|
||||
div(ng-bind-html='selectedQuest.notes()')
|
||||
quest-rewards(key='{{selectedQuest.key}}')
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('neverMind')
|
||||
|
|
@ -50,9 +50,9 @@ script(type='text/ng-template', id='modals/buyQuest.html')
|
|||
script(type='text/ng-template', id='modals/questInvitation.html')
|
||||
.modal-header
|
||||
h4=env.t('questInvitation')
|
||||
| {{Content.quests[party.quest.key].text}}
|
||||
| {{Content.quests[party.quest.key].text()}}
|
||||
.modal-body
|
||||
div(ng-bind-html='Content.quests[party.quest.key].notes')
|
||||
div(ng-bind-html='Content.quests[party.quest.key].notes()')
|
||||
quest-rewards(key='{{party.quest.key}}')
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='questHold = true; $close()')=env.t('askLater')
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ div(ng-if='profile.contributor.level || user._id == profile._id')
|
|||
span.label.label-default(ng-if='!profile.contributor.level')=env.t('contribName')
|
||||
small
|
||||
=env.t('contribText')
|
||||
|
|
||||
a(href='http://habitrpg.wikia.com/wiki/Contributing_to_HabitRPG', target='_blank')=env.t('readMore')
|
||||
| .
|
||||
hr
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ table.table.table-striped(ng-show='user.flags.itemsEnabled')
|
|||
// FIXME this isn't refreshing properly. On first party modal, correct. Second party modal click gives the previous gear. It's always one behind.
|
||||
tr(ng-repeat='(k,v) in profile.items.gear.equipped', ng-init='piece=Content.gear.flat[v]', ng-show='piece')
|
||||
td
|
||||
strong {{piece.text}}:
|
||||
strong {{piece.text()}}:
|
||||
span(ng-repeat='stat in ["str","con","per","int"]', ng-show='piece[stat]') {{piece[stat]}} {{stat.toUpperCase()}}
|
||||
|
||||
h4=env.t('attributes')
|
||||
table.table.table-striped
|
||||
tr(ng-repeat='(k,v) in {str:"Strength (STR)",int:"Intelligence (INT)",con:"Constitution (CON)",per:"Perception (PER)"}')
|
||||
tr(ng-repeat='(k,v) in {str: env.t("strength") + " (STR)",int: env.t("intelligence") + " (INT)",con: env.t("constitution") + " (CON)",per:env.t("perception") + " (PER)"}')
|
||||
td
|
||||
span.hint(ng-if='k=="str"', popover-title=env.t('strength'), popover-placement='right', popover=env.t('strengthText'), popover-trigger='mouseenter', style='margin-right:3px')
|
||||
strong {{v}}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
|||
|
||||
// Static Rewards
|
||||
ul.items.rewards(ng-if='main && list.type=="reward" && user.flags.itemsEnabled')
|
||||
li.task.reward-item(ng-repeat='item in itemStore',popover-trigger='mouseenter', popover-placement='top', popover='{{item.notes}}')
|
||||
li.task.reward-item(ng-repeat='item in itemStore',popover-trigger='mouseenter', popover-placement='top', popover='{{item.notes()}}')
|
||||
// right-hand side control buttons
|
||||
.task-meta-controls
|
||||
span.task-notes
|
||||
|
|
@ -47,12 +47,12 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
|||
span.shop_gold
|
||||
// main content
|
||||
span(bo-class='{"shop_{{item.key}} shop-sprite item-img": true}')
|
||||
p.task-text {{item.text}}
|
||||
p.task-text {{item.text()}}
|
||||
|
||||
// Events
|
||||
ul.items.rewards(ng-if='main && list.type=="reward" && (user.items.special.snowball>0 || user.stats.buffs.snowball)')
|
||||
|
||||
li.task.reward-item(ng-if='user.items.special.snowball>0',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.snowball.notes}}')
|
||||
li.task.reward-item(ng-if='user.items.special.snowball>0',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.snowball.notes()}}')
|
||||
.task-meta-controls
|
||||
span.task-notes
|
||||
span.glyphicon.glyphicon-comment
|
||||
|
|
@ -62,9 +62,9 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
|||
span.reward-cost {{user.items.special.snowball}}
|
||||
span.shop_snowball(style='display:inline-block;vertical-align:top;')
|
||||
// main content
|
||||
p.task-text {{Content.spells.special.snowball.text}}
|
||||
p.task-text {{Content.spells.special.snowball.text()}}
|
||||
|
||||
li.task.reward-item(ng-if='user.stats.buffs.snowball',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.salt.notes}}')
|
||||
li.task.reward-item(ng-if='user.stats.buffs.snowball',popover-trigger='mouseenter', popover-placement='top', popover='{{Content.spells.special.salt.notes()}}')
|
||||
.task-meta-controls
|
||||
span.task-notes
|
||||
span.glyphicon.glyphicon-comment
|
||||
|
|
@ -75,11 +75,11 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
|||
span.shop_gold
|
||||
// main content
|
||||
span.shop_salt.shop-sprite.item-img
|
||||
p.task-text {{Content.spells.special.salt.text}}
|
||||
p.task-text {{Content.spells.special.salt.text()}}
|
||||
|
||||
// Spells
|
||||
ul.items(ng-if='main && list.type=="reward" && user.stats.class && !user.preferences.disableClasses')
|
||||
li.task.reward-item(ng-repeat='(k,spell) in Content.spells[user.stats.class]', ng-if='user.stats.lvl >= spell.lvl',popover-trigger='mouseenter', popover-placement='top', popover='{{spell.notes}}')
|
||||
li.task.reward-item(ng-repeat='(k,spell) in Content.spells[user.stats.class]', ng-if='user.stats.lvl >= spell.lvl',popover-trigger='mouseenter', popover-placement='top', popover='{{spell.notes()}}')
|
||||
.task-meta-controls
|
||||
span.task-notes
|
||||
span.glyphicon.glyphicon-comment
|
||||
|
|
@ -91,7 +91,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template")
|
|||
=env.t('mp')
|
||||
// main content
|
||||
span(ng-class='{"shop_{{spell.key}} shop-sprite item-img": true}')
|
||||
p.task-text {{spell.text}}
|
||||
p.task-text {{spell.text()}}
|
||||
|
||||
br
|
||||
|
||||
|
|
|
|||
|
|
@ -11,76 +11,81 @@ block content
|
|||
.row#about-page(ng-controller='AboutCtrl')
|
||||
.col-md-12#aboutPage
|
||||
.marketing
|
||||
h1 Improve Your Habits By Playing A Game
|
||||
h1=env.t('marketing1Header')
|
||||
.row
|
||||
.col-md-6
|
||||
a.gallery(href='/marketing/screenshot.png', title='Improve Your Habits By Playing A Game')
|
||||
a.gallery(href='/marketing/screenshot.png', title=env.t('marketing1Header'))
|
||||
img(src='/marketing/screenshot.png')
|
||||
p.lead HabitRPG is a video game to help you improve real life habits. It "gamifies" your life by turning all your tasks (habits, dailies, and to-dos) into little monsters you have to conquor. The better you are at this, the more you progress in the game. If you slip up in life, your character starts backsliding in the game.
|
||||
p.lead=env.t('marketing1Lead1')
|
||||
.col-md-6
|
||||
|
||||
a.gallery(href='/marketing/gear.png', title='Get Sweet Gear')
|
||||
a.gallery(href='/marketing/gear.png', title=env.t('marketing1Lead2Title'))
|
||||
img(src='/marketing/gear.png')
|
||||
p.lead <strong>Get Sweet Gear</strong>. Improve your habits to build up your avatar. Show off the sweet gear you've earned
|
||||
p.lead!=env.t('marketing1Lead2')
|
||||
|
||||
a.gallery(href='/marketing/drops.png', title='Find Random Prizes')
|
||||
a.gallery(href='/marketing/drops.png', title=env.t('marketing1Lead3Title'))
|
||||
img(src='/marketing/drops.png',style='max-height:200px')
|
||||
p.lead <strong>Find Random Prizes</strong>. For some, it's the gamble which motivates them, a system called "stochastic rewarding". HabitRPG accommodates all reinforcement styles: positive, negative, predictable, and random.
|
||||
p.lead!=env.t('marketing1Lead3')
|
||||
|
||||
// TODO achievements
|
||||
|
||||
hr.clearfix
|
||||
|
||||
h1 Compete With Friends, Join Interest Groups
|
||||
h1=env.t('marketing2Header')
|
||||
.row
|
||||
.col-md-6
|
||||
a.gallery(href='/marketing/guild.png', title='Compete With Friends, Join Interest Groups')
|
||||
a.gallery(href='/marketing/guild.png', title=env.t('marketing2Header'))
|
||||
img(src='/marketing/guild.png')
|
||||
p.lead While you can solo-play HabitRPG, the lights really turn on when you start collaborating, competing, and holding eachother accountable. The most effective part of any self-improvement program is social accountability, and what better an environment for accountability and competition than a video game?
|
||||
p.lead=env.t('marketing2Lead1')
|
||||
|
||||
a.gallery(href='/bower_components/habitrpg-shared/img/sprites/spritesmith/quests/quest_vice3.png', title='Bosses')
|
||||
a.gallery(href='/bower_components/habitrpg-shared/img/sprites/spritesmith/quests/quest_vice3.png', title=env.t('marketing2Lead2Title'))
|
||||
img(src='/bower_components/habitrpg-shared/img/sprites/spritesmith/quests/quest_vice3.png')
|
||||
p.lead <strong>Fight Bosses</strong>. What's a Role Playing Game without battles? Fight bosses with your party. Bosses are "super accountability mode" - a day you miss the gym is a day the boss hurts <em>everyone</em>.
|
||||
p.lead!=env.t('marketing2Lead2')
|
||||
.col-md-6
|
||||
a.gallery(href='/marketing/challenge.png', title='Challenges')
|
||||
a.gallery(href='/marketing/challenge.png', title=env.t('challenges'))
|
||||
img(src='/marketing/challenge.png')
|
||||
p.lead <strong>Challenges</strong> let you compete with friends and strangers. Whoever does the best at the end of a challenge wins special prizes.
|
||||
p.lead!=env.t('marketing2Lead3')
|
||||
|
||||
hr.clearfix
|
||||
|
||||
h1 Apps
|
||||
h1=env.t('marketing3Header')
|
||||
.row
|
||||
.col-md-6
|
||||
a.gallery(href='/marketing/android_iphone.png', title='iPhone & Android')
|
||||
a.gallery(href='/marketing/android_iphone.png', title=env.t('marketing3LeadTitle'))
|
||||
img(src='/marketing/android_iphone.png',style='box-shadow:none;')
|
||||
p.lead The <strong>iPhone & Android</strong> apps let you take care of business on the go. We realize that logging into the website to click buttons can be a drag.
|
||||
p.lead!=env.t('marketing3Lead1')
|
||||
.col-md-6
|
||||
a.gallery(href='/marketing/integration.png', title='iPhone & Android')
|
||||
a.gallery(href='/marketing/integration.png', title=env.t('marketing3LeadTitle'))
|
||||
img(src='/marketing/integration.png')
|
||||
p.lead Other <strong>3rd Party Tools</strong> tie HabitRPG into various aspects of your life. Our API provides easy integration for things like the <a href='https://chrome.google.com/webstore/detail/habitrpg/pidkmpibnnnhneohdgjclfdjpijggmjj?hl=en-US' target='_blank'>Chrome Extension</a>, for which you lose points when browsing unproductive websites, and gain points when on productive ones. <a href='http://habitrpg.wikia.com/wiki/App_and_Extension_Integrations' target='_blank'>See more here</a>
|
||||
p.lead!=env.t('marketing3Lead2')
|
||||
|
||||
hr.clearfix
|
||||
|
||||
h1 Organizational Use
|
||||
h1=env.t('marketing4Header')
|
||||
.row
|
||||
.col-md-6
|
||||
h3 Gamification In Education
|
||||
h3=env.t('marketing4Lead1Title')
|
||||
img.pull-left(src='/marketing/education.png')
|
||||
p.lead Education is one of the best sectors for gamification. We all know how glued to phones and games students are these days, harness that power! Pit your students against eachother in friendly competition. Reward good behavior with rare prizes. Watch their grades and behavior soar.
|
||||
p.lead=env.t('marketing4Lead1')
|
||||
.col-md-6
|
||||
h3 Gamification In Health and Wellness
|
||||
h3=env.t('marketing4Lead2Title')
|
||||
img.pull-left(src='/marketing/wellness.png')
|
||||
p.lead Health care costs are on the rise, and something's gotta give. Hundreds of programs are built to reduce costs and improve wellness. We believe HabitRPG can pave a substantial path towards healthy lifestyles.
|
||||
p.lead=env.t('marketing4Lead2')
|
||||
.row
|
||||
.col-md-6.col-md-offset-3
|
||||
h3 Gamify Everything
|
||||
h3=env.t('marketing4Lead3Title')
|
||||
img(src='/marketing/lefnire.png')
|
||||
p.lead
|
||||
| Want to gamify your life?
|
||||
a.btn.btn-primary(ng-click='playButtonClick()') Play
|
||||
| Interested in running a group in education, wellness, and more?
|
||||
a.btn.btn-primary(href='/static/plans',target='_blank') Contact Us
|
||||
| Want to learn more?
|
||||
a.btn.btn-primary(href='/static/videos') Watch Videos
|
||||
=env.t('marketing4Lead3-1')
|
||||
|
|
||||
a.btn.btn-primary(ng-click='playButtonClick()')=env.t('playButton')
|
||||
|
|
||||
=env.t('marketing4Lead3-2')
|
||||
|
|
||||
a.btn.btn-primary(href='/static/plans',target='_blank')=env.t('contactUs')
|
||||
|
|
||||
=env.t('marketing4Lead3-3')
|
||||
|
|
||||
a.btn.btn-primary(href='/static/videos')=env.t('watchVideos')
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ script(id='modals/login.html', type='text/ng-template')
|
|||
a(href='/auth/facebook')
|
||||
img(src='/bower_components/habitrpg-shared/img/facebook-login-register.jpeg', alt=env.t('loginFacebookAlt'))
|
||||
//can we add in google auth? I like google auth
|
||||
h3 Or
|
||||
h3=env.t('or')
|
||||
ul.nav.nav-tabs
|
||||
li.active
|
||||
a(data-toggle='tab',data-target='#login-tab')=env.t('login')
|
||||
|
|
|
|||
Loading…
Reference in a new issue