mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 22:27:26 +01:00
Common reorg (#8025)
* Re-organize common folder * fix: Correct paths in tests * fix: move new content to proper folder * chore: Move audio folder to assets * Move sprites to sprites assets directory * Move css sprites to assets directory * Split out readmes for common code and sprites * Move images to assets directory * Move destinatin of shared browserified file * remove unused file * move compiled js to client-old * Fix karma tests * fix: Correct paths for sprites
This commit is contained in:
committed by
Matteo Pagliazzi
parent
d971e673af
commit
81b7eeeb71
14
website/common/script/libs/appliedTags.js
Normal file
14
website/common/script/libs/appliedTags.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Are there tags applied?
|
||||
*/
|
||||
|
||||
// TODO move to client
|
||||
|
||||
module.exports = function appliedTags (userTags, taskTags = []) {
|
||||
let arr = userTags.filter(tag => {
|
||||
return taskTags.indexOf(tag.id) !== -1;
|
||||
}).map(tag => {
|
||||
return tag.name;
|
||||
});
|
||||
return arr.join(', ');
|
||||
};
|
||||
5
website/common/script/libs/dotGet.js
Normal file
5
website/common/script/libs/dotGet.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
// TODO remove completely, only used in client
|
||||
|
||||
module.exports = _.get;
|
||||
5
website/common/script/libs/dotSet.js
Normal file
5
website/common/script/libs/dotSet.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
// TODO remove completely, only used in client
|
||||
|
||||
module.exports = _.set;
|
||||
42
website/common/script/libs/errors.js
Normal file
42
website/common/script/libs/errors.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import extendableBuiltin from './extendableBuiltin';
|
||||
|
||||
// Base class for custom application errors
|
||||
// It extends Error and capture the stack trace
|
||||
export class CustomError extends extendableBuiltin(Error) {
|
||||
constructor () {
|
||||
super();
|
||||
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We specify an httpCode for all errors so that they can be used in the API too
|
||||
|
||||
export class NotAuthorized extends CustomError {
|
||||
constructor (customMessage) {
|
||||
super();
|
||||
this.name = this.constructor.name;
|
||||
this.httpCode = 401;
|
||||
this.message = customMessage || 'Not authorized.';
|
||||
}
|
||||
}
|
||||
|
||||
export class BadRequest extends CustomError {
|
||||
constructor (customMessage) {
|
||||
super();
|
||||
this.name = this.constructor.name;
|
||||
this.httpCode = 400;
|
||||
this.message = customMessage || 'Bad request.';
|
||||
}
|
||||
}
|
||||
|
||||
export class NotFound extends CustomError {
|
||||
constructor (customMessage) {
|
||||
super();
|
||||
this.name = this.constructor.name;
|
||||
this.httpCode = 404;
|
||||
this.message = customMessage || 'Not found.';
|
||||
}
|
||||
}
|
||||
11
website/common/script/libs/extendableBuiltin.js
Normal file
11
website/common/script/libs/extendableBuiltin.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// Babel 6 doesn't support extending native class (Error, Array, ...)
|
||||
// This function makes it possible to extend native classes with the same results as Babel 5
|
||||
module.exports = function extendableBuiltin (klass) {
|
||||
function ExtendableBuiltin () {
|
||||
klass.apply(this, arguments);
|
||||
}
|
||||
ExtendableBuiltin.prototype = Object.create(klass.prototype);
|
||||
Object.setPrototypeOf(ExtendableBuiltin, klass);
|
||||
|
||||
return ExtendableBuiltin;
|
||||
};
|
||||
9
website/common/script/libs/gold.js
Normal file
9
website/common/script/libs/gold.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// TODO move to client
|
||||
|
||||
module.exports = function gold (num) {
|
||||
if (num) {
|
||||
return Math.floor(num);
|
||||
} else {
|
||||
return '0';
|
||||
}
|
||||
};
|
||||
13
website/common/script/libs/noTags.js
Normal file
13
website/common/script/libs/noTags.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
are any tags active?
|
||||
*/
|
||||
|
||||
// TODO move to client
|
||||
|
||||
module.exports = function noTags (tags) {
|
||||
return _.isEmpty(tags) || _.isEmpty(_.filter(tags, (t) => {
|
||||
return t;
|
||||
}));
|
||||
};
|
||||
19
website/common/script/libs/percent.js
Normal file
19
website/common/script/libs/percent.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// TODO move to client
|
||||
|
||||
module.exports = function percent (x, y, dir) {
|
||||
let roundFn;
|
||||
switch (dir) {
|
||||
case 'up':
|
||||
roundFn = Math.ceil;
|
||||
break;
|
||||
case 'down':
|
||||
roundFn = Math.floor;
|
||||
break;
|
||||
default:
|
||||
roundFn = Math.round;
|
||||
}
|
||||
if (x === 0) {
|
||||
x = 1;
|
||||
}
|
||||
return Math.max(0, roundFn(x / y * 100));
|
||||
};
|
||||
13
website/common/script/libs/pickDeep.js
Normal file
13
website/common/script/libs/pickDeep.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// An utility to pick deep properties from an object.
|
||||
// Works like _.pick but supports nested props (ie pickDeep(obj, ['deep.property']))
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function pickDeep (obj, properties) {
|
||||
if (!_.isArray(properties)) throw new Error('"properties" must be an array');
|
||||
|
||||
let result = {};
|
||||
_.each(properties, (prop) => _.set(result, prop, _.get(obj, prop)));
|
||||
|
||||
return result;
|
||||
};
|
||||
4
website/common/script/libs/planGemLimits.js
Normal file
4
website/common/script/libs/planGemLimits.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
convRate: 20,
|
||||
convCap: 25,
|
||||
};
|
||||
12
website/common/script/libs/preenTodos.js
Normal file
12
website/common/script/libs/preenTodos.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
|
||||
// TODO used only in v2
|
||||
|
||||
module.exports = function preenTodos (tasks) {
|
||||
return _.filter(tasks, (t) => {
|
||||
return !t.completed || t.challenge && t.challenge.id || moment(t.dateCompleted).isAfter(moment().subtract({
|
||||
days: 3,
|
||||
}));
|
||||
});
|
||||
};
|
||||
20
website/common/script/libs/refPush.js
Normal file
20
website/common/script/libs/refPush.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import _ from 'lodash';
|
||||
import uuid from './uuid';
|
||||
|
||||
/*
|
||||
Reflists are arrays, but stored as objects. Mongoose has a helluvatime working with arrays (the main problem for our
|
||||
syncing issues) - so the goal is to move away from arrays to objects, since mongoose can reference elements by ID
|
||||
no problem. To maintain sorting, we use these helper functions:
|
||||
*/
|
||||
|
||||
module.exports = function refPush (reflist, item) {
|
||||
item.sort = _.isEmpty(reflist) ? 0 : _.max(reflist, 'sort').sort + 1;
|
||||
|
||||
if (!(item.id && !reflist[item.id])) {
|
||||
item.id = uuid();
|
||||
}
|
||||
|
||||
reflist[item.id] = item;
|
||||
|
||||
return reflist[item.id];
|
||||
};
|
||||
257
website/common/script/libs/shops.js
Normal file
257
website/common/script/libs/shops.js
Normal file
@@ -0,0 +1,257 @@
|
||||
import _ from 'lodash';
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
let shops = {};
|
||||
|
||||
function lockQuest (quest, user) {
|
||||
if (quest.lvl && user.stats.lvl < quest.lvl) return true;
|
||||
if (user.achievements.quests) return quest.previous && !user.achievements.quests[quest.previous];
|
||||
return quest.previous;
|
||||
}
|
||||
|
||||
shops.getMarketCategories = function getMarket (user, language) {
|
||||
let categories = [];
|
||||
let eggsCategory = {
|
||||
identifier: 'eggs',
|
||||
text: i18n.t('eggs', language),
|
||||
notes: i18n.t('dropsExplanation', language),
|
||||
};
|
||||
|
||||
eggsCategory.items = _(content.questEggs)
|
||||
.values()
|
||||
.filter(egg => egg.canBuy(user))
|
||||
.concat(_.values(content.dropEggs))
|
||||
.map(egg => {
|
||||
return {
|
||||
key: egg.key,
|
||||
text: i18n.t('egg', {eggType: egg.text()}, language),
|
||||
notes: egg.notes(language),
|
||||
value: egg.value,
|
||||
class: `Pet_Egg_${egg.key}`,
|
||||
locked: false,
|
||||
currency: 'gems',
|
||||
purchaseType: 'eggs',
|
||||
};
|
||||
}).sortBy('key').value();
|
||||
categories.push(eggsCategory);
|
||||
|
||||
let hatchingPotionsCategory = {
|
||||
identifier: 'hatchingPotions',
|
||||
text: i18n.t('hatchingPotions', language),
|
||||
notes: i18n.t('dropsExplanation', language),
|
||||
};
|
||||
hatchingPotionsCategory.items = _(content.hatchingPotions)
|
||||
.values()
|
||||
.filter(hp => !hp.limited)
|
||||
.map(hatchingPotion => {
|
||||
return {
|
||||
key: hatchingPotion.key,
|
||||
text: hatchingPotion.text(language),
|
||||
notes: hatchingPotion.notes(language),
|
||||
class: `Pet_HatchingPotion_${hatchingPotion.key}`,
|
||||
value: hatchingPotion.value,
|
||||
locked: false,
|
||||
currency: 'gems',
|
||||
purchaseType: 'hatchingPotions',
|
||||
};
|
||||
}).sortBy('key').value();
|
||||
categories.push(hatchingPotionsCategory);
|
||||
|
||||
let premiumHatchingPotionsCategory = {
|
||||
identifier: 'premiumHatchingPotions',
|
||||
text: i18n.t('magicHatchingPotions', language),
|
||||
notes: i18n.t('premiumPotionNoDropExplanation', language),
|
||||
};
|
||||
premiumHatchingPotionsCategory.items = _(content.hatchingPotions)
|
||||
.values()
|
||||
.filter(hp => hp.limited && hp.canBuy())
|
||||
.map(premiumHatchingPotion => {
|
||||
return {
|
||||
key: premiumHatchingPotion.key,
|
||||
text: premiumHatchingPotion.text(language),
|
||||
notes: `${premiumHatchingPotion.notes(language)} ${premiumHatchingPotion._addlNotes(language)}`,
|
||||
class: `Pet_HatchingPotion_${premiumHatchingPotion.key}`,
|
||||
value: premiumHatchingPotion.value,
|
||||
locked: false,
|
||||
currency: 'gems',
|
||||
purchaseType: 'hatchingPotions',
|
||||
};
|
||||
}).sortBy('key').value();
|
||||
categories.push(premiumHatchingPotionsCategory);
|
||||
|
||||
let foodCategory = {
|
||||
identifier: 'food',
|
||||
text: i18n.t('food', language),
|
||||
notes: i18n.t('dropsExplanation', language),
|
||||
};
|
||||
foodCategory.items = _(content.food)
|
||||
.values()
|
||||
.filter(food => food.canDrop || food.key === 'Saddle')
|
||||
.map(foodItem => {
|
||||
return {
|
||||
key: foodItem.key,
|
||||
text: foodItem.text(language),
|
||||
notes: foodItem.notes(language),
|
||||
class: `Pet_Food_${foodItem.key}`,
|
||||
value: foodItem.value,
|
||||
locked: false,
|
||||
currency: 'gems',
|
||||
purchaseType: 'food',
|
||||
};
|
||||
}).sortBy('key').value();
|
||||
categories.push(foodCategory);
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
shops.getQuestShopCategories = function getQuestShopCategories (user, language) {
|
||||
let categories = [];
|
||||
|
||||
_.each(content.userCanOwnQuestCategories, type => {
|
||||
let category = {
|
||||
identifier: type,
|
||||
text: i18n.t(`${type}Quests`, language),
|
||||
};
|
||||
|
||||
category.items = _(content.questsByLevel)
|
||||
.filter(quest => quest.canBuy(user) && quest.category === type)
|
||||
.map(quest => {
|
||||
let locked = lockQuest(quest, user);
|
||||
return {
|
||||
key: quest.key,
|
||||
text: quest.text(language),
|
||||
notes: quest.notes(language),
|
||||
value: quest.goldValue ? quest.goldValue : quest.value,
|
||||
currency: quest.goldValue ? 'gold' : 'gems',
|
||||
locked,
|
||||
unlockCondition: quest.unlockCondition,
|
||||
drop: quest.drop,
|
||||
boss: quest.boss,
|
||||
collect: quest.collect,
|
||||
lvl: quest.lvl,
|
||||
class: locked ? `inventory_quest_scroll_${quest.key}_locked` : `inventory_quest_scroll_${quest.key}`,
|
||||
purchaseType: 'quests',
|
||||
};
|
||||
}).value();
|
||||
|
||||
categories.push(category);
|
||||
});
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
shops.getTimeTravelersCategories = function getTimeTravelersCategories (user, language) {
|
||||
let categories = [];
|
||||
let stable = {pets: 'Pet-', mounts: 'Mount_Head_'};
|
||||
for (let type in stable) {
|
||||
if (stable.hasOwnProperty(type)) {
|
||||
let category = {
|
||||
identifier: type,
|
||||
text: i18n.t(type, language),
|
||||
items: [],
|
||||
};
|
||||
|
||||
for (let key in content.timeTravelStable[type]) {
|
||||
if (content.timeTravelStable[type].hasOwnProperty(key)) {
|
||||
if (!user.items[type][key]) {
|
||||
let item = {
|
||||
key,
|
||||
text: content.timeTravelStable[type][key](language),
|
||||
class: stable[type] + key,
|
||||
type,
|
||||
purchaseType: type,
|
||||
value: 1,
|
||||
notes: '',
|
||||
locked: false,
|
||||
currency: 'hourglasses',
|
||||
};
|
||||
category.items.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (category.items.length > 0) {
|
||||
categories.push(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let sets = content.timeTravelerStore(user.items.gear.owned);
|
||||
for (let setKey in sets) {
|
||||
if (sets.hasOwnProperty(setKey)) {
|
||||
let set = sets[setKey];
|
||||
let category = {
|
||||
identifier: set.key,
|
||||
text: set.text(language),
|
||||
purchaseAll: true,
|
||||
};
|
||||
|
||||
category.items = _.map(set.items, item => {
|
||||
return {
|
||||
key: item.key,
|
||||
text: item.text(language),
|
||||
notes: item.notes(language),
|
||||
type: item.type,
|
||||
purchaseType: 'gear',
|
||||
value: 1,
|
||||
locked: false,
|
||||
currency: 'hourglasses',
|
||||
class: `shop_${item.key}`,
|
||||
};
|
||||
});
|
||||
if (category.items.length > 0) {
|
||||
categories.push(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
// To switch seasons/available inventory, edit the availableSets object to whatever should be sold.
|
||||
// let availableSets = {
|
||||
// setKey: i18n.t('setTranslationString', language),
|
||||
// };
|
||||
shops.getSeasonalShopCategories = function getSeasonalShopCategories (user, language) {
|
||||
let availableSets = {
|
||||
};
|
||||
|
||||
let categories = [];
|
||||
|
||||
let flatGearArray = _.toArray(content.gear.flat);
|
||||
|
||||
for (let key in availableSets) {
|
||||
if (availableSets.hasOwnProperty(key)) {
|
||||
let category = {
|
||||
identifier: key,
|
||||
text: availableSets[key],
|
||||
};
|
||||
|
||||
category.items = _(flatGearArray).filter((gear) => {
|
||||
if (gear.index !== key) {
|
||||
return false;
|
||||
}
|
||||
return user.items.gear.owned[gear.key] === undefined;
|
||||
}).where({index: key}).map(gear => {
|
||||
return {
|
||||
key: gear.key,
|
||||
text: gear.text(language),
|
||||
notes: gear.notes(language),
|
||||
value: 1,
|
||||
type: gear.type,
|
||||
specialClass: gear.specialClass,
|
||||
locked: false,
|
||||
currency: 'gems',
|
||||
purchaseType: 'gear',
|
||||
};
|
||||
}).value();
|
||||
if (category.items.length > 0) {
|
||||
categories.push(category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
module.exports = shops;
|
||||
14
website/common/script/libs/silver.js
Normal file
14
website/common/script/libs/silver.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Silver amount from their money
|
||||
*/
|
||||
|
||||
// TODO move to client
|
||||
|
||||
module.exports = function silver (num) {
|
||||
if (num) {
|
||||
let centCount = Math.floor((num - Math.floor(num)) * 100);
|
||||
return `0${centCount}`.slice(-2);
|
||||
} else {
|
||||
return '00';
|
||||
}
|
||||
};
|
||||
4
website/common/script/libs/splitWhitespace.js
Normal file
4
website/common/script/libs/splitWhitespace.js
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
module.exports = function splitWhitespace (s) {
|
||||
return s.split(' ');
|
||||
};
|
||||
28
website/common/script/libs/statsComputed.js
Normal file
28
website/common/script/libs/statsComputed.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import _ from 'lodash';
|
||||
import content from '../content/index';
|
||||
import * as statHelpers from '../statHelpers';
|
||||
|
||||
module.exports = function statsComputed (user) {
|
||||
let paths = ['stats', 'stats.buffs', 'items.gear.equipped.weapon', 'items.gear.equipped.armor',
|
||||
'items.gear.equipped.head', 'items.gear.equipped.shield'];
|
||||
let computed = _.reduce(['per', 'con', 'str', 'int'], (m, stat) => {
|
||||
m[stat] = _.reduce(paths, (m2, path) => {
|
||||
let val = _.get(user, path);
|
||||
let item = content.gear.flat[val];
|
||||
if (!item) item = {};
|
||||
if (!item[stat]) {
|
||||
item[stat] = 0;
|
||||
} else {
|
||||
item[stat] = Number(item[stat]);
|
||||
}
|
||||
let thisMultiplier = item.klass === user.stats.class || item.specialClass === user.stats.class ? 1.5 : 1;
|
||||
let thisReturn = path.indexOf('items.gear') !== -1 ? item[stat] * thisMultiplier : Number(val[stat]);
|
||||
return m2 + thisReturn || 0;
|
||||
}, 0);
|
||||
m[stat] += Math.floor(statHelpers.capByLevel(user.stats.lvl) / 2);
|
||||
return m;
|
||||
}, {});
|
||||
|
||||
computed.maxMP = computed.int * 2 + 30;
|
||||
return computed;
|
||||
};
|
||||
80
website/common/script/libs/taskClasses.js
Normal file
80
website/common/script/libs/taskClasses.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import {
|
||||
shouldDo,
|
||||
} from '../cron';
|
||||
|
||||
/*
|
||||
Task classes given everything about the class
|
||||
*/
|
||||
|
||||
// TODO move to the client
|
||||
|
||||
module.exports = function taskClasses (task, filters = [], dayStart = 0, lastCron = Number(new Date()), showCompleted = false, main = false) {
|
||||
if (!task) {
|
||||
return '';
|
||||
}
|
||||
let type = task.type;
|
||||
let classes = task.type;
|
||||
let completed = task.completed;
|
||||
let value = task.value;
|
||||
let priority = task.priority;
|
||||
|
||||
if (main && !task._editing) {
|
||||
for (let filter in filters) {
|
||||
let enabled = filters[filter];
|
||||
if (!task.tags) task.tags = [];
|
||||
if (enabled && task.tags.indexOf(filter) === -1) {
|
||||
return 'hidden';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes = task.type;
|
||||
if (task._editing) {
|
||||
classes += ' beingEdited';
|
||||
}
|
||||
|
||||
if (type === 'todo' || type === 'daily') {
|
||||
if (completed || (type === 'daily' && !shouldDo(Number(new Date()), task, { // eslint-disable-line no-extra-parens
|
||||
dayStart,
|
||||
}))) {
|
||||
classes += ' completed';
|
||||
} else {
|
||||
classes += ' uncompleted';
|
||||
}
|
||||
} else if (type === 'habit') {
|
||||
if (task.down && task.up) {
|
||||
classes += ' habit-wide';
|
||||
}
|
||||
if (!task.down && !task.up) {
|
||||
classes += ' habit-narrow';
|
||||
}
|
||||
}
|
||||
|
||||
if (priority === 0.1) {
|
||||
classes += ' difficulty-trivial';
|
||||
} else if (priority === 1) {
|
||||
classes += ' difficulty-easy';
|
||||
} else if (priority === 1.5) {
|
||||
classes += ' difficulty-medium';
|
||||
} else if (priority === 2) {
|
||||
classes += ' difficulty-hard';
|
||||
}
|
||||
|
||||
if (value < -20) {
|
||||
classes += ' color-worst';
|
||||
} else if (value < -10) {
|
||||
classes += ' color-worse';
|
||||
} else if (value < -1) {
|
||||
classes += ' color-bad';
|
||||
} else if (value < 1) {
|
||||
classes += ' color-neutral';
|
||||
} else if (value < 5) {
|
||||
classes += ' color-good';
|
||||
} else if (value < 10) {
|
||||
classes += ' color-better';
|
||||
} else {
|
||||
classes += ' color-best';
|
||||
}
|
||||
|
||||
return classes;
|
||||
};
|
||||
74
website/common/script/libs/taskDefaults.js
Normal file
74
website/common/script/libs/taskDefaults.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
// Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before
|
||||
// sending up to the server for performance
|
||||
|
||||
// TODO move to client code?
|
||||
|
||||
const tasksTypes = ['habit', 'daily', 'todo', 'reward'];
|
||||
|
||||
module.exports = function taskDefaults (task = {}) {
|
||||
if (!task.type || tasksTypes.indexOf(task.type) === -1) {
|
||||
task.type = 'habit';
|
||||
}
|
||||
|
||||
let defaultId = uuid();
|
||||
let defaults = {
|
||||
_id: defaultId,
|
||||
text: task._id || defaultId,
|
||||
notes: '',
|
||||
tags: [],
|
||||
value: task.type === 'reward' ? 10 : 0,
|
||||
priority: 1,
|
||||
challenge: {},
|
||||
reminders: [],
|
||||
attribute: 'str',
|
||||
createdAt: new Date(), // TODO these are going to be overwritten by the server...
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
_.defaults(task, defaults);
|
||||
|
||||
if (task.type === 'habit' || task.type === 'daily') {
|
||||
_.defaults(task, {
|
||||
history: [],
|
||||
});
|
||||
}
|
||||
|
||||
if (task.type === 'todo' || task.type === 'daily') {
|
||||
_.defaults(task, {
|
||||
completed: false,
|
||||
collapseChecklist: false,
|
||||
checklist: [],
|
||||
});
|
||||
}
|
||||
|
||||
if (task.type === 'habit') {
|
||||
_.defaults(task, {
|
||||
up: true,
|
||||
down: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (task.type === 'daily') {
|
||||
_.defaults(task, {
|
||||
streak: 0,
|
||||
repeat: {
|
||||
m: true,
|
||||
t: true,
|
||||
w: true,
|
||||
th: true,
|
||||
f: true,
|
||||
s: true,
|
||||
su: true,
|
||||
},
|
||||
startDate: moment().startOf('day').toDate(),
|
||||
everyX: 1,
|
||||
frequency: 'weekly',
|
||||
});
|
||||
}
|
||||
|
||||
return task;
|
||||
};
|
||||
31
website/common/script/libs/updateStore.js
Normal file
31
website/common/script/libs/updateStore.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import _ from 'lodash';
|
||||
import content from '../content/index';
|
||||
|
||||
// Return the list of gear items available for purchase
|
||||
|
||||
let sortOrder = _.reduce(content.gearTypes, (accumulator, val, key) => {
|
||||
accumulator[val] = key;
|
||||
return accumulator;
|
||||
}, {});
|
||||
|
||||
module.exports = function updateStore (user) {
|
||||
let changes = [];
|
||||
|
||||
_.each(content.gearTypes, (type) => {
|
||||
let found = _.find(content.gear.tree[type][user.stats.class], (item) => {
|
||||
return !user.items.gear.owned[item.key];
|
||||
});
|
||||
|
||||
if (found) changes.push(found);
|
||||
});
|
||||
|
||||
changes = changes.concat(_.filter(content.gear.flat, (val) => {
|
||||
if (['special', 'mystery', 'armoire'].indexOf(val.klass) !== -1 && !user.items.gear.owned[val.key] && (val.canOwn ? val.canOwn(user) : false)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
|
||||
return _.sortBy(changes, (change) => sortOrder[change.type]);
|
||||
};
|
||||
4
website/common/script/libs/uuid.js
Normal file
4
website/common/script/libs/uuid.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import uuid from 'uuid';
|
||||
|
||||
// TODO remove this file completely
|
||||
module.exports = uuid.v4;
|
||||
Reference in New Issue
Block a user