Merge branch 'develop' into party-chat-translations
@@ -39,6 +39,7 @@ dist-client
|
||||
test/client/unit/coverage
|
||||
test/client/e2e/reports
|
||||
test/client-old/spec/mocks/translations.js
|
||||
yarn.lock
|
||||
|
||||
# Elastic Beanstalk Files
|
||||
.elasticbeanstalk/*
|
||||
|
||||
@@ -2,9 +2,13 @@ version: "3"
|
||||
services:
|
||||
|
||||
client:
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
volumes:
|
||||
- '.:/usr/src/habitrpg'
|
||||
|
||||
server:
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
volumes:
|
||||
- '.:/usr/src/habitrpg'
|
||||
|
||||
@@ -17,5 +17,5 @@ function setUpServer () {
|
||||
setUpServer();
|
||||
|
||||
// Replace this with your migration
|
||||
const processUsers = require('./tasks/habits-one-history-entry-per-day-challenges.js');
|
||||
const processUsers = require('./groups/reconcile-group-plan-members.js');
|
||||
processUsers();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
|
||||
const migrationName = 'mystery-items-201806.js'; // Update per month
|
||||
const migrationName = 'mystery-items-201808.js'; // Update per month
|
||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Award this month's mystery items to subscribers
|
||||
*/
|
||||
const MYSTERY_ITEMS = ['armor_mystery_201806', 'head_mystery_201806'];
|
||||
const MYSTERY_ITEMS = ['armor_mystery_201808', 'head_mystery_201808'];
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
let migrationName = '20180731_naming-day.js'; // Update when running in future years
|
||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Award Naming Day ladder items to participants in this month's Naming Day festivities
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING'); // FOR TEST DATABASE
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: migrationName},
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
fields: [
|
||||
'items.gear.owned',
|
||||
'items.mounts',
|
||||
'items.pets',
|
||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return;
|
||||
}
|
||||
|
||||
let userPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {};
|
||||
let push;
|
||||
|
||||
const inc = {
|
||||
'items.food.Cake_Base': 1,
|
||||
'items.food.Cake_CottonCandyBlue': 1,
|
||||
'items.food.Cake_CottonCandyPink': 1,
|
||||
'items.food.Cake_Desert': 1,
|
||||
'items.food.Cake_Golden': 1,
|
||||
'items.food.Cake_Red': 1,
|
||||
'items.food.Cake_Shade': 1,
|
||||
'items.food.Cake_Skeleton': 1,
|
||||
'items.food.Cake_White': 1,
|
||||
'items.food.Cake_Zombie': 1,
|
||||
'achievements.habiticaDays': 1,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.gear && user.items.gear.owned && typeof user.items.gear.owned.head_special_namingDay2017 !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.gear.owned.body_special_namingDay2018': false};
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_namingDay2018', _id: monk.id()}};
|
||||
} else if (user && user.items && user.items.pets && typeof user.items.pets['Gryphon-RoyalPurple'] !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.gear.owned.head_special_namingDay2017': false};
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_namingDay2017', _id: monk.id()}};
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Gryphon-RoyalPurple'] !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.pets.Gryphon-RoyalPurple': 5};
|
||||
} else {
|
||||
set = {migration: migrationName, 'items.mounts.Gryphon-RoyalPurple': true};
|
||||
}
|
||||
|
||||
if (push) {
|
||||
dbUsers.update({_id: user._id}, {$set: set, $push: push, $inc: inc});
|
||||
} else {
|
||||
dbUsers.update({_id: user._id}, {$set: set, $inc: inc});
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
module.exports = processUsers;
|
||||
@@ -0,0 +1,99 @@
|
||||
let migrationName = '20180724_summer-splash-orcas.js'; // Update per month
|
||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Award ladder items to participants in this year's Summer Splash festivities
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: migrationName},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2018-07-01')}, // rerun without date restriction after initial run
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
fields: [
|
||||
'items.mounts',
|
||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return;
|
||||
}
|
||||
|
||||
let userPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {};
|
||||
|
||||
if (user && user.items && user.items.pets && typeof user.items.pets['Orca-Base'] !== 'undefined') {
|
||||
set = {migration: migrationName};
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Orca-Base'] !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.pets.Orca-Base': 5};
|
||||
} else {
|
||||
set = {migration: migrationName, 'items.mounts.Orca-Base': true};
|
||||
}
|
||||
|
||||
dbUsers.update({_id: user._id}, {$set: set});
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
module.exports = processUsers;
|
||||
@@ -1,4 +1,4 @@
|
||||
let migrationName = '20180702_takeThis.js'; // Update per month
|
||||
let migrationName = '20180801_takeThis.js'; // Update per month
|
||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
@@ -15,7 +15,7 @@ function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: migrationName},
|
||||
challenges: {$in: ['f0481f95-1dde-4ae7-a876-d19502a45d61']}, // Update per month
|
||||
challenges: {$in: ['081f8912-3526-47d5-984f-f71bbeec77fc']}, // Update per month
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "4.52.2",
|
||||
"version": "4.58.0",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@slack/client": "^3.8.1",
|
||||
@@ -9,9 +9,9 @@
|
||||
"amazon-payments": "^0.2.7",
|
||||
"amplitude": "^3.5.0",
|
||||
"apidoc": "^0.17.5",
|
||||
"apn": "^2.2.0",
|
||||
"autoprefixer": "^8.5.0",
|
||||
"aws-sdk": "^2.239.1",
|
||||
"apn": "^2.2.0",
|
||||
"axios": "^0.18.0",
|
||||
"axios-progress-bar": "^1.2.0",
|
||||
"babel-core": "^6.26.3",
|
||||
@@ -26,7 +26,7 @@
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-register": "^6.6.0",
|
||||
"babel-runtime": "^6.11.6",
|
||||
"bcrypt": "^2.0.0",
|
||||
"bcrypt": "^3.0.0",
|
||||
"body-parser": "^1.18.3",
|
||||
"bootstrap": "^4.1.1",
|
||||
"bootstrap-vue": "^2.0.0-rc.9",
|
||||
@@ -35,7 +35,7 @@
|
||||
"coupon-code": "^0.4.5",
|
||||
"cross-env": "^5.1.5",
|
||||
"css-loader": "^0.28.11",
|
||||
"csv-stringify": "^2.1.0",
|
||||
"csv-stringify": "^3.0.0",
|
||||
"cwait": "^1.1.1",
|
||||
"domain-middleware": "~0.1.0",
|
||||
"express": "^4.16.3",
|
||||
@@ -43,7 +43,7 @@
|
||||
"express-validator": "^5.2.0",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"glob": "^7.1.2",
|
||||
"got": "^8.3.1",
|
||||
"got": "^9.0.0",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-babel": "^7.0.1",
|
||||
"gulp-imagemin": "^4.1.0",
|
||||
@@ -83,6 +83,7 @@
|
||||
"rimraf": "^2.4.3",
|
||||
"sass-loader": "^7.0.0",
|
||||
"shelljs": "^0.8.2",
|
||||
"smartbanner.js": "^1.9.1",
|
||||
"stripe": "^5.9.0",
|
||||
"superagent": "^3.8.3",
|
||||
"svg-inline-loader": "^0.8.0",
|
||||
@@ -95,7 +96,7 @@
|
||||
"url-loader": "^1.0.0",
|
||||
"useragent": "^2.1.9",
|
||||
"uuid": "^3.0.1",
|
||||
"validator": "^9.4.1",
|
||||
"validator": "^10.5.0",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vue": "^2.5.16",
|
||||
"vue-loader": "^14.2.2",
|
||||
@@ -163,19 +164,19 @@
|
||||
"expect.js": "^0.3.1",
|
||||
"http-proxy-middleware": "^0.18.0",
|
||||
"istanbul": "^1.1.0-alpha.1",
|
||||
"karma": "^2.0.2",
|
||||
"karma": "^3.0.0",
|
||||
"karma-babel-preprocessor": "^7.0.0",
|
||||
"karma-chai-plugins": "^0.9.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-coverage": "^1.1.2",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-sinon-chai": "^1.3.4",
|
||||
"karma-sinon-chai": "^2.0.0",
|
||||
"karma-sinon-stub-promise": "^1.0.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.32",
|
||||
"karma-webpack": "^3.0.0",
|
||||
"lcov-result-merger": "^2.0.0",
|
||||
"lcov-result-merger": "^3.0.0",
|
||||
"mocha": "^5.1.1",
|
||||
"monk": "^6.0.6",
|
||||
"nightwatch": "^0.9.21",
|
||||
|
||||
@@ -65,6 +65,12 @@ describe('cron', () => {
|
||||
expect(analytics.track.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('calls analytics when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(analytics.track.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
describe('end of the month perks', () => {
|
||||
beforeEach(() => {
|
||||
user.purchased.plan.customerId = 'subscribedId';
|
||||
@@ -655,76 +661,6 @@ describe('cron', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('user is sleeping', () => {
|
||||
beforeEach(() => {
|
||||
user.preferences.sleep = true;
|
||||
});
|
||||
|
||||
it('calls analytics', () => {
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(analytics.track.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('clears user buffs', () => {
|
||||
user.stats.buffs = {
|
||||
str: 1,
|
||||
int: 1,
|
||||
per: 1,
|
||||
con: 1,
|
||||
stealth: 1,
|
||||
streaks: true,
|
||||
};
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.stats.buffs.str).to.equal(0);
|
||||
expect(user.stats.buffs.int).to.equal(0);
|
||||
expect(user.stats.buffs.per).to.equal(0);
|
||||
expect(user.stats.buffs.con).to.equal(0);
|
||||
expect(user.stats.buffs.stealth).to.equal(0);
|
||||
expect(user.stats.buffs.streaks).to.be.false;
|
||||
});
|
||||
|
||||
it('resets all dailies without damaging user', () => {
|
||||
let daily = {
|
||||
text: 'test daily',
|
||||
type: 'daily',
|
||||
frequency: 'daily',
|
||||
everyX: 5,
|
||||
startDate: new Date(),
|
||||
};
|
||||
|
||||
let task = new Tasks.daily(Tasks.Task.sanitize(daily)); // eslint-disable-line new-cap
|
||||
tasksByType.dailys.push(task);
|
||||
tasksByType.dailys[0].completed = true;
|
||||
|
||||
let healthBefore = user.stats.hp;
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(tasksByType.dailys[0].completed).to.be.false;
|
||||
expect(user.stats.hp).to.equal(healthBefore);
|
||||
});
|
||||
|
||||
it('sets isDue for daily', () => {
|
||||
let daily = {
|
||||
text: 'test daily',
|
||||
type: 'daily',
|
||||
frequency: 'daily',
|
||||
everyX: 5,
|
||||
startDate: new Date(),
|
||||
};
|
||||
|
||||
let task = new Tasks.daily(Tasks.Task.sanitize(daily)); // eslint-disable-line new-cap
|
||||
tasksByType.dailys.push(task);
|
||||
tasksByType.dailys[0].completed = true;
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(tasksByType.dailys[0].isDue).to.be.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('todos', () => {
|
||||
beforeEach(() => {
|
||||
let todo = {
|
||||
@@ -846,6 +782,15 @@ describe('cron', () => {
|
||||
expect(tasksByType.dailys[0].isDue).to.be.false;
|
||||
});
|
||||
|
||||
it('computes isDue when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
tasksByType.dailys[0].frequency = 'daily';
|
||||
tasksByType.dailys[0].everyX = 5;
|
||||
tasksByType.dailys[0].startDate = moment().toDate();
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(tasksByType.dailys[0].isDue).to.exist;
|
||||
});
|
||||
|
||||
it('computes nextDue', () => {
|
||||
tasksByType.dailys[0].frequency = 'daily';
|
||||
tasksByType.dailys[0].everyX = 5;
|
||||
@@ -865,6 +810,13 @@ describe('cron', () => {
|
||||
expect(tasksByType.dailys[0].completed).to.be.false;
|
||||
});
|
||||
|
||||
it('should set tasks completed to false when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(tasksByType.dailys[0].completed).to.be.false;
|
||||
});
|
||||
|
||||
it('should reset task checklist for completed dailys', () => {
|
||||
tasksByType.dailys[0].checklist.push({title: 'test', completed: false});
|
||||
tasksByType.dailys[0].completed = true;
|
||||
@@ -872,6 +824,14 @@ describe('cron', () => {
|
||||
expect(tasksByType.dailys[0].checklist[0].completed).to.be.false;
|
||||
});
|
||||
|
||||
it('should reset task checklist for completed dailys when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
tasksByType.dailys[0].checklist.push({title: 'test', completed: false});
|
||||
tasksByType.dailys[0].completed = true;
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(tasksByType.dailys[0].checklist[0].completed).to.be.false;
|
||||
});
|
||||
|
||||
it('should reset task checklist for dailys with scheduled misses', () => {
|
||||
daysMissed = 10;
|
||||
tasksByType.dailys[0].checklist.push({title: 'test', completed: false});
|
||||
@@ -884,12 +844,19 @@ describe('cron', () => {
|
||||
daysMissed = 1;
|
||||
let hpBefore = user.stats.hp;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.stats.hp).to.be.lessThan(hpBefore);
|
||||
});
|
||||
|
||||
it('should not do damage for missing a daily when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
daysMissed = 1;
|
||||
let hpBefore = user.stats.hp;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(user.stats.hp).to.equal(hpBefore);
|
||||
});
|
||||
|
||||
it('should not do damage for missing a daily when CRON_SAFE_MODE is set', () => {
|
||||
sandbox.stub(nconf, 'get').withArgs('CRON_SAFE_MODE').returns('true');
|
||||
let cronOverride = requireAgain(pathToCronLib).cron;
|
||||
@@ -930,7 +897,7 @@ describe('cron', () => {
|
||||
expect(hpDifferenceOfPartiallyIncompleteDaily).to.be.lessThan(hpDifferenceOfFullyIncompleteDaily);
|
||||
});
|
||||
|
||||
it('should decrement quest progress down for missing a daily', () => {
|
||||
it('should decrement quest.progress.down for missing a daily', () => {
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
@@ -939,6 +906,16 @@ describe('cron', () => {
|
||||
expect(progress.down).to.equal(-1);
|
||||
});
|
||||
|
||||
it('should not decrement quest.progress.down for missing a daily when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
let progress = cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(progress.down).to.equal(0);
|
||||
});
|
||||
|
||||
it('should do damage for only yesterday\'s dailies', () => {
|
||||
daysMissed = 3;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
@@ -1017,7 +994,7 @@ describe('cron', () => {
|
||||
expect(tasksByType.habits[0].counterDown).to.equal(0);
|
||||
});
|
||||
|
||||
it('should reset habit counters even if user is resting in the Inn', () => {
|
||||
it('should reset habit counters even if user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
tasksByType.habits[0].counterUp = 1;
|
||||
tasksByType.habits[0].counterDown = 1;
|
||||
@@ -1278,7 +1255,23 @@ describe('cron', () => {
|
||||
expect(user.achievements.perfect).to.equal(0);
|
||||
});
|
||||
|
||||
it('increments user buffs if all (at least 1) due dailies were completed', () => {
|
||||
it('gives perfect day buff if all (at least 1) due dailies were completed', () => {
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
let previousBuffs = user.stats.buffs.toObject();
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.stats.buffs.str).to.be.greaterThan(previousBuffs.str);
|
||||
expect(user.stats.buffs.int).to.be.greaterThan(previousBuffs.int);
|
||||
expect(user.stats.buffs.per).to.be.greaterThan(previousBuffs.per);
|
||||
expect(user.stats.buffs.con).to.be.greaterThan(previousBuffs.con);
|
||||
});
|
||||
|
||||
it('gives perfect day buff if all (at least 1) due dailies were completed when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
@@ -1317,6 +1310,31 @@ describe('cron', () => {
|
||||
expect(user.stats.buffs.streaks).to.be.false;
|
||||
});
|
||||
|
||||
it('clears buffs if user does not have a perfect day (no due dailys) when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).add({days: 1});
|
||||
|
||||
user.stats.buffs = {
|
||||
str: 1,
|
||||
int: 1,
|
||||
per: 1,
|
||||
con: 1,
|
||||
stealth: 0,
|
||||
streaks: true,
|
||||
};
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.stats.buffs.str).to.equal(0);
|
||||
expect(user.stats.buffs.int).to.equal(0);
|
||||
expect(user.stats.buffs.per).to.equal(0);
|
||||
expect(user.stats.buffs.con).to.equal(0);
|
||||
expect(user.stats.buffs.stealth).to.equal(0);
|
||||
expect(user.stats.buffs.streaks).to.be.false;
|
||||
});
|
||||
|
||||
it('clears buffs if user does not have a perfect day (at least one due daily not completed)', () => {
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].completed = false;
|
||||
@@ -1341,7 +1359,50 @@ describe('cron', () => {
|
||||
expect(user.stats.buffs.streaks).to.be.false;
|
||||
});
|
||||
|
||||
it('still grants a perfect day when CRON_SAFE_MODE is set', () => {
|
||||
it('clears buffs if user does not have a perfect day (at least one due daily not completed) when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].completed = false;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
user.stats.buffs = {
|
||||
str: 1,
|
||||
int: 1,
|
||||
per: 1,
|
||||
con: 1,
|
||||
stealth: 0,
|
||||
streaks: true,
|
||||
};
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.stats.buffs.str).to.equal(0);
|
||||
expect(user.stats.buffs.int).to.equal(0);
|
||||
expect(user.stats.buffs.per).to.equal(0);
|
||||
expect(user.stats.buffs.con).to.equal(0);
|
||||
expect(user.stats.buffs.stealth).to.equal(0);
|
||||
expect(user.stats.buffs.streaks).to.be.false;
|
||||
});
|
||||
|
||||
it('always grants a perfect day buff when CRON_SAFE_MODE is set', () => {
|
||||
sandbox.stub(nconf, 'get').withArgs('CRON_SAFE_MODE').returns('true');
|
||||
let cronOverride = requireAgain(pathToCronLib).cron;
|
||||
daysMissed = 1;
|
||||
tasksByType.dailys[0].completed = false;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
let previousBuffs = user.stats.buffs.toObject();
|
||||
|
||||
cronOverride({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.stats.buffs.str).to.be.greaterThan(previousBuffs.str);
|
||||
expect(user.stats.buffs.int).to.be.greaterThan(previousBuffs.int);
|
||||
expect(user.stats.buffs.per).to.be.greaterThan(previousBuffs.per);
|
||||
expect(user.stats.buffs.con).to.be.greaterThan(previousBuffs.con);
|
||||
});
|
||||
|
||||
it('always grants a perfect day buff when CRON_SAFE_MODE is set when user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
sandbox.stub(nconf, 'get').withArgs('CRON_SAFE_MODE').returns('true');
|
||||
let cronOverride = requireAgain(pathToCronLib).cron;
|
||||
daysMissed = 1;
|
||||
@@ -1373,6 +1434,20 @@ describe('cron', () => {
|
||||
common.statsComputed.restore();
|
||||
});
|
||||
|
||||
it('should not add mp to user when user is sleeping', () => {
|
||||
const statsComputedRes = common.statsComputed(user);
|
||||
const stubbedStatsComputed = sinon.stub(common, 'statsComputed');
|
||||
|
||||
user.preferences.sleep = true;
|
||||
let mpBefore = user.stats.mp;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
stubbedStatsComputed.returns(Object.assign(statsComputedRes, {maxMP: 100}));
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(user.stats.mp).to.equal(mpBefore);
|
||||
|
||||
common.statsComputed.restore();
|
||||
});
|
||||
|
||||
it('set user\'s mp to statsComputed.maxMP when user.stats.mp is greater', () => {
|
||||
const statsComputedRes = common.statsComputed(user);
|
||||
const stubbedStatsComputed = sinon.stub(common, 'statsComputed');
|
||||
@@ -1568,7 +1643,7 @@ describe('cron', () => {
|
||||
expect(user.loginIncentives).to.eql(1);
|
||||
});
|
||||
|
||||
it('increments loginIncentives by 1 even if user has Dailies paused', () => {
|
||||
it('increments loginIncentives by 1 even if user is sleeping', () => {
|
||||
user.preferences.sleep = true;
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
expect(user.loginIncentives).to.eql(1);
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('slack', () => {
|
||||
title: 'Flag in Some group - (private guild)',
|
||||
title_link: undefined,
|
||||
text: 'some text',
|
||||
footer: sandbox.match(/<.*?groupId=group-id&chatId=chat-id\|Flag this message>/),
|
||||
footer: sandbox.match(/<.*?groupId=group-id&chatId=chat-id\|Flag this message.>/),
|
||||
mrkdwn_in: [
|
||||
'text',
|
||||
],
|
||||
|
||||
@@ -20,7 +20,7 @@ import { TAVERN_ID } from '../../../../website/common/script/';
|
||||
import shared from '../../../../website/common';
|
||||
|
||||
describe('Group Model', () => {
|
||||
let party, questLeader, participatingMember, nonParticipatingMember, undecidedMember;
|
||||
let party, questLeader, participatingMember, sleepingParticipatingMember, nonParticipatingMember, undecidedMember;
|
||||
|
||||
beforeEach(async () => {
|
||||
sandbox.stub(email, 'sendTxn');
|
||||
@@ -48,6 +48,11 @@ describe('Group Model', () => {
|
||||
party: { _id: party._id },
|
||||
profile: { name: 'Participating Member' },
|
||||
});
|
||||
sleepingParticipatingMember = new User({
|
||||
party: { _id: party._id },
|
||||
profile: { name: 'Sleeping Participating Member' },
|
||||
preferences: { sleep: true },
|
||||
});
|
||||
nonParticipatingMember = new User({
|
||||
party: { _id: party._id },
|
||||
profile: { name: 'Non-Participating Member' },
|
||||
@@ -61,6 +66,7 @@ describe('Group Model', () => {
|
||||
party.save(),
|
||||
questLeader.save(),
|
||||
participatingMember.save(),
|
||||
sleepingParticipatingMember.save(),
|
||||
nonParticipatingMember.save(),
|
||||
undecidedMember.save(),
|
||||
]);
|
||||
@@ -80,6 +86,7 @@ describe('Group Model', () => {
|
||||
party.quest.members = {
|
||||
[questLeader._id]: true,
|
||||
[participatingMember._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
};
|
||||
@@ -175,6 +182,34 @@ describe('Group Model', () => {
|
||||
expect(party._processBossQuest).to.not.be.called;
|
||||
expect(Group.prototype._processCollectionQuest).to.be.calledOnce;
|
||||
});
|
||||
|
||||
it('does not call _processBossQuest when user is resting in the inn', async () => {
|
||||
party.quest.key = 'whale';
|
||||
|
||||
await party.startQuest(questLeader);
|
||||
await party.save();
|
||||
|
||||
await Group.processQuestProgress(sleepingParticipatingMember, progress);
|
||||
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(party._processBossQuest).to.not.be.called;
|
||||
expect(party._processCollectionQuest).to.not.be.called;
|
||||
});
|
||||
|
||||
it('does not call _processCollectionQuest when user is resting in the inn', async () => {
|
||||
party.quest.key = 'evilsanta2';
|
||||
|
||||
await party.startQuest(questLeader);
|
||||
await party.save();
|
||||
|
||||
await Group.processQuestProgress(sleepingParticipatingMember, progress);
|
||||
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(party._processBossQuest).to.not.be.called;
|
||||
expect(party._processCollectionQuest).to.not.be.called;
|
||||
});
|
||||
});
|
||||
|
||||
context('Boss Quests', () => {
|
||||
@@ -225,17 +260,20 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
updatedNonParticipatingMember,
|
||||
updatedUndecidedMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id),
|
||||
User.findById(participatingMember._id),
|
||||
User.findById(sleepingParticipatingMember._id),
|
||||
User.findById(nonParticipatingMember._id),
|
||||
User.findById(undecidedMember._id),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.stats.hp).to.eql(42.5);
|
||||
expect(updatedParticipatingMember.stats.hp).to.eql(42.5);
|
||||
expect(updatedSleepingParticipatingMember.stats.hp).to.eql(42.5);
|
||||
expect(updatedNonParticipatingMember.stats.hp).to.eql(50);
|
||||
expect(updatedUndecidedMember.stats.hp).to.eql(50);
|
||||
});
|
||||
@@ -245,6 +283,7 @@ describe('Group Model', () => {
|
||||
party.quest.members = {
|
||||
[questLeader._id]: true,
|
||||
[participatingMember._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
};
|
||||
@@ -257,17 +296,20 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
updatedNonParticipatingMember,
|
||||
updatedUndecidedMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id),
|
||||
User.findById(participatingMember._id),
|
||||
User.findById(sleepingParticipatingMember._id),
|
||||
User.findById(nonParticipatingMember._id),
|
||||
User.findById(undecidedMember._id),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.stats.hp).to.eql(42.5);
|
||||
expect(updatedParticipatingMember.stats.hp).to.eql(42.5);
|
||||
expect(updatedSleepingParticipatingMember.stats.hp).to.eql(42.5);
|
||||
expect(updatedNonParticipatingMember.stats.hp).to.eql(50);
|
||||
expect(updatedUndecidedMember.stats.hp).to.eql(50);
|
||||
});
|
||||
@@ -546,9 +588,11 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id),
|
||||
User.findById(participatingMember._id),
|
||||
User.findById(sleepingParticipatingMember._id),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.achievements.quests[party.quest.key]).to.eql(1);
|
||||
@@ -557,6 +601,9 @@ describe('Group Model', () => {
|
||||
expect(updatedParticipatingMember.achievements.quests[party.quest.key]).to.eql(1);
|
||||
expect(updatedParticipatingMember.stats.exp).to.be.greaterThan(0);
|
||||
expect(updatedParticipatingMember.stats.gp).to.be.greaterThan(0);
|
||||
expect(updatedSleepingParticipatingMember.achievements.quests[party.quest.key]).to.eql(1);
|
||||
expect(updatedSleepingParticipatingMember.stats.exp).to.be.greaterThan(0);
|
||||
expect(updatedSleepingParticipatingMember.stats.gp).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -896,6 +943,7 @@ describe('Group Model', () => {
|
||||
it('returns an array of members whose quest status set to true', () => {
|
||||
party.quest.members = {
|
||||
[participatingMember._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[questLeader._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
@@ -903,6 +951,7 @@ describe('Group Model', () => {
|
||||
|
||||
expect(party.getParticipatingQuestMembers()).to.eql([
|
||||
participatingMember._id,
|
||||
sleepingParticipatingMember._id,
|
||||
questLeader._id,
|
||||
]);
|
||||
});
|
||||
@@ -1005,11 +1054,12 @@ describe('Group Model', () => {
|
||||
it('removes user from group quest', async () => {
|
||||
party.quest.members = {
|
||||
[participatingMember._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[questLeader._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
};
|
||||
party.memberCount = 4;
|
||||
party.memberCount = 5;
|
||||
await party.save();
|
||||
|
||||
await party.leave(participatingMember);
|
||||
@@ -1017,6 +1067,7 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
expect(party.quest.members).to.eql({
|
||||
[questLeader._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
});
|
||||
@@ -1024,6 +1075,7 @@ describe('Group Model', () => {
|
||||
|
||||
it('deletes a private party when the last member leaves', async () => {
|
||||
await party.leave(participatingMember);
|
||||
await party.leave(sleepingParticipatingMember);
|
||||
await party.leave(questLeader);
|
||||
await party.leave(nonParticipatingMember);
|
||||
await party.leave(undecidedMember);
|
||||
@@ -1095,6 +1147,7 @@ describe('Group Model', () => {
|
||||
party.privacy = 'public';
|
||||
|
||||
await party.leave(participatingMember);
|
||||
await party.leave(sleepingParticipatingMember);
|
||||
await party.leave(questLeader);
|
||||
await party.leave(nonParticipatingMember);
|
||||
await party.leave(undecidedMember);
|
||||
@@ -1325,6 +1378,7 @@ describe('Group Model', () => {
|
||||
party.quest.members = {
|
||||
[questLeader._id]: true,
|
||||
[participatingMember._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
};
|
||||
@@ -1381,6 +1435,7 @@ describe('Group Model', () => {
|
||||
let expectedQuestMembers = {};
|
||||
expectedQuestMembers[questLeader._id] = true;
|
||||
expectedQuestMembers[participatingMember._id] = true;
|
||||
expectedQuestMembers[sleepingParticipatingMember._id] = true;
|
||||
|
||||
expect(party.quest.members).to.eql(expectedQuestMembers);
|
||||
});
|
||||
@@ -1399,12 +1454,18 @@ describe('Group Model', () => {
|
||||
|
||||
questLeader = await User.findById(questLeader._id);
|
||||
participatingMember = await User.findById(participatingMember._id);
|
||||
sleepingParticipatingMember = await User.findById(sleepingParticipatingMember._id);
|
||||
|
||||
expect(participatingMember.party.quest.key).to.eql('whale');
|
||||
expect(participatingMember.party.quest.progress.down).to.eql(0);
|
||||
expect(participatingMember.party.quest.progress.collectedItems).to.eql(0);
|
||||
expect(participatingMember.party.quest.completed).to.eql(null);
|
||||
|
||||
expect(sleepingParticipatingMember.party.quest.key).to.eql('whale');
|
||||
expect(sleepingParticipatingMember.party.quest.progress.down).to.eql(0);
|
||||
expect(sleepingParticipatingMember.party.quest.progress.collectedItems).to.eql(0);
|
||||
expect(sleepingParticipatingMember.party.quest.completed).to.eql(null);
|
||||
|
||||
expect(questLeader.party.quest.key).to.eql('whale');
|
||||
expect(questLeader.party.quest.progress.down).to.eql(0);
|
||||
expect(questLeader.party.quest.progress.collectedItems).to.eql(0);
|
||||
@@ -1423,9 +1484,11 @@ describe('Group Model', () => {
|
||||
|
||||
it('sends email to participating members that quest has started', async () => {
|
||||
participatingMember.preferences.emailNotifications.questStarted = true;
|
||||
sleepingParticipatingMember.preferences.emailNotifications.questStarted = true;
|
||||
questLeader.preferences.emailNotifications.questStarted = true;
|
||||
await Promise.all([
|
||||
participatingMember.save(),
|
||||
sleepingParticipatingMember.save(),
|
||||
questLeader.save(),
|
||||
]);
|
||||
|
||||
@@ -1438,8 +1501,9 @@ describe('Group Model', () => {
|
||||
let memberIds = _.map(email.sendTxn.args[0][0], '_id');
|
||||
let typeOfEmail = email.sendTxn.args[0][1];
|
||||
|
||||
expect(memberIds).to.have.a.lengthOf(2);
|
||||
expect(memberIds).to.have.a.lengthOf(3);
|
||||
expect(memberIds).to.include(participatingMember._id);
|
||||
expect(memberIds).to.include(sleepingParticipatingMember._id);
|
||||
expect(memberIds).to.include(questLeader._id);
|
||||
expect(typeOfEmail).to.eql('quest-started');
|
||||
});
|
||||
@@ -1453,6 +1517,13 @@ describe('Group Model', () => {
|
||||
questStarted: true,
|
||||
},
|
||||
}];
|
||||
sleepingParticipatingMember.webhooks = [{
|
||||
type: 'questActivity',
|
||||
url: 'http://someurl.com',
|
||||
options: {
|
||||
questStarted: true,
|
||||
},
|
||||
}];
|
||||
questLeader.webhooks = [{
|
||||
type: 'questActivity',
|
||||
url: 'http://someurl.com',
|
||||
@@ -1461,13 +1532,13 @@ describe('Group Model', () => {
|
||||
},
|
||||
}];
|
||||
|
||||
await Promise.all([participatingMember.save(), questLeader.save()]);
|
||||
await Promise.all([participatingMember.save(), sleepingParticipatingMember.save(), questLeader.save()]);
|
||||
|
||||
await party.startQuest(nonParticipatingMember);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
expect(questActivityWebhook.send).to.be.calledTwice; // for 2 participating members
|
||||
expect(questActivityWebhook.send).to.be.calledThrice; // for 3 participating members
|
||||
|
||||
let args = questActivityWebhook.send.args[0];
|
||||
let webhooks = args[0].webhooks;
|
||||
@@ -1477,6 +1548,8 @@ describe('Group Model', () => {
|
||||
expect(webhooks).to.have.a.lengthOf(1);
|
||||
if (webhookOwner === questLeader._id) {
|
||||
expect(webhooks[0].id).to.eql(questLeader.webhooks[0].id);
|
||||
} else if (webhookOwner === sleepingParticipatingMember._id) {
|
||||
expect(webhooks[0].id).to.eql(sleepingParticipatingMember.webhooks[0].id);
|
||||
} else {
|
||||
expect(webhooks[0].id).to.eql(participatingMember.webhooks[0].id);
|
||||
}
|
||||
@@ -1487,9 +1560,11 @@ describe('Group Model', () => {
|
||||
|
||||
it('sends email only to members who have not opted out', async () => {
|
||||
participatingMember.preferences.emailNotifications.questStarted = false;
|
||||
sleepingParticipatingMember.preferences.emailNotifications.questStarted = false;
|
||||
questLeader.preferences.emailNotifications.questStarted = true;
|
||||
await Promise.all([
|
||||
participatingMember.save(),
|
||||
sleepingParticipatingMember.save(),
|
||||
questLeader.save(),
|
||||
]);
|
||||
|
||||
@@ -1503,14 +1578,17 @@ describe('Group Model', () => {
|
||||
|
||||
expect(memberIds).to.have.a.lengthOf(1);
|
||||
expect(memberIds).to.not.include(participatingMember._id);
|
||||
expect(memberIds).to.not.include(sleepingParticipatingMember._id);
|
||||
expect(memberIds).to.include(questLeader._id);
|
||||
});
|
||||
|
||||
it('does not send email to initiating member', async () => {
|
||||
participatingMember.preferences.emailNotifications.questStarted = true;
|
||||
sleepingParticipatingMember.preferences.emailNotifications.questStarted = true;
|
||||
questLeader.preferences.emailNotifications.questStarted = true;
|
||||
await Promise.all([
|
||||
participatingMember.save(),
|
||||
sleepingParticipatingMember.save(),
|
||||
questLeader.save(),
|
||||
]);
|
||||
|
||||
@@ -1522,8 +1600,9 @@ describe('Group Model', () => {
|
||||
|
||||
let memberIds = _.map(email.sendTxn.args[0][0], '_id');
|
||||
|
||||
expect(memberIds).to.have.a.lengthOf(1);
|
||||
expect(memberIds).to.have.a.lengthOf(2);
|
||||
expect(memberIds).to.not.include(participatingMember._id);
|
||||
expect(memberIds).to.include(sleepingParticipatingMember._id);
|
||||
expect(memberIds).to.include(questLeader._id);
|
||||
});
|
||||
|
||||
@@ -1532,7 +1611,7 @@ describe('Group Model', () => {
|
||||
|
||||
await party.startQuest(nonParticipatingMember);
|
||||
|
||||
let members = [questLeader._id, participatingMember._id];
|
||||
let members = [questLeader._id, participatingMember._id, sleepingParticipatingMember._id];
|
||||
|
||||
expect(User.update).to.be.calledWith(
|
||||
{ _id: { $in: members } },
|
||||
@@ -1597,6 +1676,7 @@ describe('Group Model', () => {
|
||||
party.quest.members = {
|
||||
[questLeader._id]: true,
|
||||
[participatingMember._id]: true,
|
||||
[sleepingParticipatingMember._id]: true,
|
||||
[nonParticipatingMember._id]: false,
|
||||
[undecidedMember._id]: null,
|
||||
};
|
||||
@@ -1619,7 +1699,7 @@ describe('Group Model', () => {
|
||||
|
||||
await party.finishQuest(quest);
|
||||
|
||||
expect(User.update).to.be.calledTwice;
|
||||
expect(User.update).to.be.calledThrice;
|
||||
});
|
||||
|
||||
it('stops retrying when a successful update has occurred', async () => {
|
||||
@@ -1629,7 +1709,7 @@ describe('Group Model', () => {
|
||||
|
||||
await party.finishQuest(quest);
|
||||
|
||||
expect(User.update).to.be.calledThrice;
|
||||
expect(User.update.callCount).to.equal(4);
|
||||
});
|
||||
|
||||
it('retries failed updates at most five times per user', async () => {
|
||||
@@ -1637,7 +1717,7 @@ describe('Group Model', () => {
|
||||
|
||||
await expect(party.finishQuest(quest)).to.eventually.be.rejected;
|
||||
|
||||
expect(User.update.callCount).to.eql(10);
|
||||
expect(User.update.callCount).to.eql(15); // for 3 users
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1647,17 +1727,19 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id),
|
||||
User.findById(participatingMember._id),
|
||||
User.findById(sleepingParticipatingMember._id),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.achievements.quests[quest.key]).to.eql(1);
|
||||
expect(updatedParticipatingMember.achievements.quests[quest.key]).to.eql(1);
|
||||
expect(updatedSleepingParticipatingMember.achievements.quests[quest.key]).to.eql(1);
|
||||
});
|
||||
|
||||
// Disable test, it fails on TravisCI, but only there
|
||||
xit('gives out super awesome Masterclasser achievement to the deserving', async () => {
|
||||
it('gives out super awesome Masterclasser achievement to the deserving', async () => {
|
||||
quest = questScrolls.lostMasterclasser4;
|
||||
party.quest.key = quest.key;
|
||||
|
||||
@@ -1684,17 +1766,19 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id).exec(),
|
||||
User.findById(participatingMember._id).exec(),
|
||||
User.findById(sleepingParticipatingMember._id).exec(),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.achievements.lostMasterclasser).to.eql(true);
|
||||
expect(updatedParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
|
||||
expect(updatedSleepingParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
|
||||
});
|
||||
|
||||
// Disable test, it fails on TravisCI, but only there
|
||||
xit('gives out super awesome Masterclasser achievement when quests done out of order', async () => {
|
||||
it('gives out super awesome Masterclasser achievement when quests done out of order', async () => {
|
||||
quest = questScrolls.lostMasterclasser1;
|
||||
party.quest.key = quest.key;
|
||||
|
||||
@@ -1721,13 +1805,16 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id).exec(),
|
||||
User.findById(participatingMember._id).exec(),
|
||||
User.findById(sleepingParticipatingMember._id).exec(),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.achievements.lostMasterclasser).to.eql(true);
|
||||
expect(updatedParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
|
||||
expect(updatedSleepingParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
|
||||
});
|
||||
|
||||
it('gives xp and gold', async () => {
|
||||
@@ -1736,15 +1823,19 @@ describe('Group Model', () => {
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id),
|
||||
User.findById(participatingMember._id),
|
||||
User.findById(sleepingParticipatingMember._id),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.stats.exp).to.eql(quest.drop.exp);
|
||||
expect(updatedLeader.stats.gp).to.eql(quest.drop.gp);
|
||||
expect(updatedParticipatingMember.stats.exp).to.eql(quest.drop.exp);
|
||||
expect(updatedParticipatingMember.stats.gp).to.eql(quest.drop.gp);
|
||||
expect(updatedSleepingParticipatingMember.stats.exp).to.eql(quest.drop.exp);
|
||||
expect(updatedSleepingParticipatingMember.stats.gp).to.eql(quest.drop.gp);
|
||||
});
|
||||
|
||||
context('drops', () => {
|
||||
@@ -1844,13 +1935,16 @@ describe('Group Model', () => {
|
||||
sandbox.spy(User, 'update');
|
||||
await party.finishQuest(quest);
|
||||
|
||||
expect(User.update).to.be.calledTwice;
|
||||
expect(User.update).to.be.calledThrice;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
_id: questLeader._id,
|
||||
});
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
_id: participatingMember._id,
|
||||
});
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
_id: sleepingParticipatingMember._id,
|
||||
});
|
||||
});
|
||||
|
||||
it('sets user quest object to a clean state', async () => {
|
||||
@@ -1883,7 +1977,7 @@ describe('Group Model', () => {
|
||||
},
|
||||
}];
|
||||
|
||||
await Promise.all([participatingMember.save(), questLeader.save()]);
|
||||
await Promise.all([participatingMember.save(), sleepingParticipatingMember.save(), questLeader.save()]);
|
||||
|
||||
await party.finishQuest(quest);
|
||||
|
||||
|
||||
@@ -304,14 +304,14 @@ describe('POST /challenges', () => {
|
||||
expect(groupLeader.challenges.length).to.equal(0);
|
||||
});
|
||||
|
||||
it('awards achievement if this is creator\'s first challenge', async () => {
|
||||
it('does not award joinedChallenge achievement for creating a challenge', async () => {
|
||||
await groupLeader.post('/challenges', {
|
||||
group: group._id,
|
||||
name: 'Test Challenge',
|
||||
shortName: 'TC Label',
|
||||
});
|
||||
groupLeader = await groupLeader.sync();
|
||||
expect(groupLeader.achievements.joinedChallenge).to.be.true;
|
||||
expect(groupLeader.achievements.joinedChallenge).to.not.be.true;
|
||||
});
|
||||
|
||||
it('sets summary to challenges name when not supplied', async () => {
|
||||
|
||||
@@ -3,15 +3,23 @@ import {
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
import { find } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import nconf from 'nconf';
|
||||
import { IncomingWebhook } from '@slack/client';
|
||||
|
||||
const BASE_URL = nconf.get('BASE_URL');
|
||||
|
||||
describe('POST /chat/:chatId/flag', () => {
|
||||
let user, admin, anotherUser, group;
|
||||
let user, admin, anotherUser, newUser, group;
|
||||
const TEST_MESSAGE = 'Test Message';
|
||||
const USER_AGE_FOR_FLAGGING = 3;
|
||||
|
||||
beforeEach(async () => {
|
||||
user = await generateUser({balance: 1});
|
||||
user = await generateUser({balance: 1, 'auth.timestamps.created': moment().subtract(USER_AGE_FOR_FLAGGING + 1, 'days').toDate()});
|
||||
admin = await generateUser({balance: 1, 'contributor.admin': true});
|
||||
anotherUser = await generateUser();
|
||||
anotherUser = await generateUser({'auth.timestamps.created': moment().subtract(USER_AGE_FOR_FLAGGING + 1, 'days').toDate()});
|
||||
newUser = await generateUser({'auth.timestamps.created': moment().subtract(1, 'days').toDate()});
|
||||
sandbox.stub(IncomingWebhook.prototype, 'send');
|
||||
|
||||
group = await user.post('/groups', {
|
||||
name: 'Test Guild',
|
||||
@@ -20,6 +28,10 @@ describe('POST /chat/:chatId/flag', () => {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('Returns an error when chat message is not found', async () => {
|
||||
await expect(user.post(`/groups/${group._id}/chat/incorrectMessage/flag`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
@@ -34,7 +46,7 @@ describe('POST /chat/:chatId/flag', () => {
|
||||
await expect(user.post(`/groups/${group._id}/chat/${message.message.id}/flag`)).to.eventually.be.ok;
|
||||
});
|
||||
|
||||
it('Flags a chat', async () => {
|
||||
it('Flags a chat and sends normal message to moderator Slack when user is not new', async () => {
|
||||
let { message } = await anotherUser.post(`/groups/${group._id}/chat`, {message: TEST_MESSAGE});
|
||||
|
||||
let flagResult = await user.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
@@ -45,6 +57,62 @@ describe('POST /chat/:chatId/flag', () => {
|
||||
|
||||
let messageToCheck = find(groupWithFlags.chat, {id: message.id});
|
||||
expect(messageToCheck.flags[user._id]).to.equal(true);
|
||||
|
||||
// Slack message to mods
|
||||
const timestamp = `${moment(message.timestamp).utc().format('YYYY-MM-DD HH:mm')} UTC`;
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
||||
text: `${user.profile.name} (${user.id}; language: en) flagged a message`,
|
||||
attachments: [{
|
||||
fallback: 'Flag Message',
|
||||
color: 'danger',
|
||||
author_name: `${anotherUser.profile.name} - ${anotherUser.auth.local.email} - ${anotherUser._id}\n${timestamp}`,
|
||||
title: 'Flag in Test Guild',
|
||||
title_link: `${BASE_URL}/groups/guild/${group._id}`,
|
||||
text: TEST_MESSAGE,
|
||||
footer: `<https://habitrpg.github.io/flag-o-rama/?groupId=${group._id}&chatId=${message.id}|Flag this message.>`,
|
||||
mrkdwn_in: [
|
||||
'text',
|
||||
],
|
||||
}],
|
||||
});
|
||||
/* eslint-ensable camelcase */
|
||||
});
|
||||
|
||||
it('Does not increment message flag count and sends different message to moderator Slack when user is new', async () => {
|
||||
let automatedComment = `The post's flag count has not been increased because the flagger's account is less than ${USER_AGE_FOR_FLAGGING} days old.`;
|
||||
let { message } = await newUser.post(`/groups/${group._id}/chat`, {message: TEST_MESSAGE});
|
||||
|
||||
let flagResult = await newUser.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
expect(flagResult.flags[newUser._id]).to.equal(true);
|
||||
expect(flagResult.flagCount).to.equal(0);
|
||||
|
||||
let groupWithFlags = await admin.get(`/groups/${group._id}`);
|
||||
|
||||
let messageToCheck = find(groupWithFlags.chat, {id: message.id});
|
||||
expect(messageToCheck.flags[newUser._id]).to.equal(true);
|
||||
|
||||
// Slack message to mods
|
||||
const timestamp = `${moment(message.timestamp).utc().format('YYYY-MM-DD HH:mm')} UTC`;
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
||||
text: `${newUser.profile.name} (${newUser.id}; language: en) flagged a message`,
|
||||
attachments: [{
|
||||
fallback: 'Flag Message',
|
||||
color: 'danger',
|
||||
author_name: `${newUser.profile.name} - ${newUser.auth.local.email} - ${newUser._id}\n${timestamp}`,
|
||||
title: 'Flag in Test Guild',
|
||||
title_link: `${BASE_URL}/groups/guild/${group._id}`,
|
||||
text: TEST_MESSAGE,
|
||||
footer: `<https://habitrpg.github.io/flag-o-rama/?groupId=${group._id}&chatId=${message.id}|Flag this message.> ${automatedComment}`,
|
||||
mrkdwn_in: [
|
||||
'text',
|
||||
],
|
||||
}],
|
||||
});
|
||||
/* eslint-ensable camelcase */
|
||||
});
|
||||
|
||||
it('Flags a chat when the author\'s account was deleted', async () => {
|
||||
@@ -117,7 +185,7 @@ describe('POST /chat/:chatId/flag', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error when user tries to flag a message that is already flagged', async () => {
|
||||
it('Returns an error when user tries to flag a message that they already flagged', async () => {
|
||||
let { message } = await anotherUser.post(`/groups/${group._id}/chat`, {message: TEST_MESSAGE});
|
||||
|
||||
await user.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { IncomingWebhook } from '@slack/client';
|
||||
import nconf from 'nconf';
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
generateUser,
|
||||
@@ -15,8 +17,6 @@ import { getMatchesByWordArray } from '../../../../../website/server/libs/string
|
||||
import bannedWords from '../../../../../website/server/libs/bannedWords';
|
||||
import guildsAllowingBannedWords from '../../../../../website/server/libs/guildsAllowingBannedWords';
|
||||
import * as email from '../../../../../website/server/libs/email';
|
||||
import { IncomingWebhook } from '@slack/client';
|
||||
import nconf from 'nconf';
|
||||
|
||||
const BASE_URL = nconf.get('BASE_URL');
|
||||
|
||||
@@ -80,12 +80,14 @@ describe('POST /chat', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error when chat privileges are revoked when sending a message to a public guild', async () => {
|
||||
let userWithChatRevoked = await member.update({'flags.chatRevoked': true});
|
||||
await expect(userWithChatRevoked.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
describe('mute user', () => {
|
||||
it('returns an error when chat privileges are revoked when sending a message to a public guild', async () => {
|
||||
const userWithChatRevoked = await member.update({'flags.chatRevoked': true});
|
||||
await expect(userWithChatRevoked.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -259,7 +261,6 @@ describe('POST /chat', () => {
|
||||
title: 'Slur in Test Guild',
|
||||
title_link: `${BASE_URL}/groups/guild/${groupWithChat.id}`,
|
||||
text: testSlurMessage,
|
||||
// footer: sandbox.match(/<.*?groupId=group-id&chatId=chat-id\|Flag this message>/),
|
||||
mrkdwn_in: [
|
||||
'text',
|
||||
],
|
||||
@@ -274,6 +275,7 @@ describe('POST /chat', () => {
|
||||
message: t('chatPrivilegesRevoked'),
|
||||
});
|
||||
|
||||
// @TODO: The next test should not depend on this. We should reset the user test in a beforeEach
|
||||
// Restore chat privileges to continue testing
|
||||
user.flags.chatRevoked = false;
|
||||
await user.update({'flags.chatRevoked': false});
|
||||
@@ -312,7 +314,6 @@ describe('POST /chat', () => {
|
||||
title: 'Slur in Party - (private party)',
|
||||
title_link: undefined,
|
||||
text: testSlurMessage,
|
||||
// footer: sandbox.match(/<.*?groupId=group-id&chatId=chat-id\|Flag this message>/),
|
||||
mrkdwn_in: [
|
||||
'text',
|
||||
],
|
||||
|
||||
@@ -4,23 +4,24 @@ import {
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
import config from '../../../../../config.json';
|
||||
import moment from 'moment';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('POST /groups/:id/chat/:id/clearflags', () => {
|
||||
const USER_AGE_FOR_FLAGGING = 3;
|
||||
let groupWithChat, message, author, nonAdmin, admin;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
let { group, groupLeader } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
groupWithChat = group;
|
||||
author = groupLeader;
|
||||
nonAdmin = members[0];
|
||||
nonAdmin = await generateUser({'auth.timestamps.created': moment().subtract(USER_AGE_FOR_FLAGGING + 1, 'days').toDate()});
|
||||
admin = await generateUser({'contributor.admin': true});
|
||||
|
||||
message = await author.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some message' });
|
||||
@@ -69,9 +70,14 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
|
||||
privateMessage = privateMessage.message;
|
||||
|
||||
await admin.post(`/groups/${group._id}/chat/${privateMessage.id}/flag`);
|
||||
|
||||
// first test that the flag was actually successful
|
||||
let messages = await members[0].get(`/groups/${group._id}/chat`);
|
||||
expect(messages[0].flagCount).to.eql(5);
|
||||
|
||||
await admin.post(`/groups/${group._id}/chat/${privateMessage.id}/clearflags`);
|
||||
|
||||
let messages = await members[0].get(`/groups/${group._id}/chat`);
|
||||
messages = await members[0].get(`/groups/${group._id}/chat`);
|
||||
expect(messages[0].flagCount).to.eql(0);
|
||||
});
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('GET /groups/:groupId/members', () => {
|
||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
||||
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||
'size', 'hair', 'skin', 'shirt',
|
||||
'chair', 'costume', 'sleep', 'background', 'tasks',
|
||||
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
||||
].sort());
|
||||
|
||||
expect(memberRes.stats.maxMP).to.exist;
|
||||
@@ -98,7 +98,7 @@ describe('GET /groups/:groupId/members', () => {
|
||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
||||
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||
'size', 'hair', 'skin', 'shirt',
|
||||
'chair', 'costume', 'sleep', 'background', 'tasks',
|
||||
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
||||
].sort());
|
||||
|
||||
expect(memberRes.stats.maxMP).to.exist;
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('GET /members/:memberId', () => {
|
||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
||||
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||
'size', 'hair', 'skin', 'shirt',
|
||||
'chair', 'costume', 'sleep', 'background', 'tasks',
|
||||
'chair', 'costume', 'sleep', 'background', 'tasks', 'disableClasses',
|
||||
].sort());
|
||||
|
||||
expect(memberRes.stats.maxMP).to.exist;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
|
||||
describe('Prevent multiple notifications', () => {
|
||||
let partyLeader, partyMembers, party;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
members: 4,
|
||||
});
|
||||
|
||||
party = group;
|
||||
partyLeader = groupLeader;
|
||||
partyMembers = members;
|
||||
});
|
||||
|
||||
it('does not add the same notification twice', async () => {
|
||||
const multipleChatMessages = [];
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
for (let memberIndex = 0; memberIndex < partyMembers.length; memberIndex++) {
|
||||
multipleChatMessages.push(
|
||||
partyMembers[memberIndex].post(`/groups/${party._id}/chat`, { message: `Message ${i}_${memberIndex}`}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(multipleChatMessages);
|
||||
|
||||
const userWithNotification = await partyLeader.get('/user');
|
||||
|
||||
expect(userWithNotification.notifications.length).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
|
||||
|
||||
describe('payments - stripe - #subscribeCancel', () => {
|
||||
let endpoint = '/stripe/subscribe/cancel?redirect=none';
|
||||
let endpoint = '/stripe/subscribe/cancel?noRedirect=true';
|
||||
let user, group, stripeCancelSubscriptionStub;
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
@@ -58,6 +58,21 @@ describe('POST /user/class/cast/:spellId', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error if use Healing Light spell with full health', async () => {
|
||||
await user.update({
|
||||
'stats.class': 'healer',
|
||||
'stats.lvl': 11,
|
||||
'stats.hp': 50,
|
||||
'stats.mp': 200,
|
||||
});
|
||||
await expect(user.post('/user/class/cast/heal'))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('messageHealthAlreadyMax'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error if spell.lvl > user.level', async () => {
|
||||
await user.update({'stats.mp': 200, 'stats.class': 'wizard'});
|
||||
await expect(user.post('/user/class/cast/earth'))
|
||||
|
||||
@@ -50,11 +50,24 @@ describe('POST /user/push-devices', () => {
|
||||
});
|
||||
|
||||
it('adds a push device to the user', async () => {
|
||||
let response = await user.post('/user/push-devices', {type, regId});
|
||||
const response = await user.post('/user/push-devices', {type, regId});
|
||||
await user.sync();
|
||||
|
||||
expect(response.message).to.equal(t('pushDeviceAdded'));
|
||||
expect(response.data[0].type).to.equal(type);
|
||||
expect(response.data[0].regId).to.equal(regId);
|
||||
expect(user.pushDevices[0].type).to.equal(type);
|
||||
expect(user.pushDevices[0].regId).to.equal(regId);
|
||||
});
|
||||
|
||||
it('removes a push device to the user', async () => {
|
||||
await user.post('/user/push-devices', {type, regId});
|
||||
|
||||
const response = await user.del(`/user/push-devices/${regId}`);
|
||||
await user.sync();
|
||||
|
||||
expect(response.message).to.equal(t('pushDeviceRemoved'));
|
||||
expect(response.data[0]).to.not.exist;
|
||||
expect(user.pushDevices[0]).to.not.exist;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
generateUser,
|
||||
} from '../../helpers/common.helper';
|
||||
import spells from '../../../website/common/script/content/spells';
|
||||
import {
|
||||
NotAuthorized,
|
||||
} from '../../../website/common/script/libs/errors';
|
||||
import i18n from '../../../website/common/script/i18n';
|
||||
|
||||
// TODO complete the test suite...
|
||||
|
||||
describe('shared.ops.spells', () => {
|
||||
let user;
|
||||
|
||||
beforeEach(() => {
|
||||
user = generateUser();
|
||||
});
|
||||
|
||||
it('returns an error when healer tries to cast Healing Light with full health', (done) => {
|
||||
user.stats.class = 'healer';
|
||||
user.stats.lvl = 11;
|
||||
user.stats.hp = 50;
|
||||
user.stats.mp = 200;
|
||||
|
||||
let spell = spells.healer.heal;
|
||||
|
||||
try {
|
||||
spell.cast(user);
|
||||
} catch (err) {
|
||||
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||
expect(err.message).to.equal(i18n.t('messageHealthAlreadyMax'));
|
||||
expect(user.stats.hp).to.eql(50);
|
||||
expect(user.stats.mp).to.eql(200);
|
||||
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -295,9 +295,14 @@ export default {
|
||||
|
||||
// Set up Error interceptors
|
||||
axios.interceptors.response.use((response) => {
|
||||
if (this.user && response.data && response.data.notifications) {
|
||||
this.$set(this.user, 'notifications', response.data.notifications);
|
||||
}
|
||||
const responseHasNotifications = response.data && response.data.notifications;
|
||||
if (!responseHasNotifications) return response;
|
||||
|
||||
const responseIsUpdateUser = this.user && this.user._v >= response.data.userV;
|
||||
if (!responseIsUpdateUser) return response;
|
||||
|
||||
this.$set(this.user, 'notifications', response.data.notifications);
|
||||
|
||||
return response;
|
||||
}, (error) => {
|
||||
if (error.response.status >= 400) {
|
||||
@@ -659,3 +664,4 @@ export default {
|
||||
<style src="assets/css/sprites/spritesmith-main-21.css"></style>
|
||||
<style src="assets/css/sprites/spritesmith-main-22.css"></style>
|
||||
<style src="assets/css/sprites.css"></style>
|
||||
<style src="smartbanner.js/dist/smartbanner.min.css"></style>
|
||||
|
||||
@@ -1,78 +1,48 @@
|
||||
.promo_aquatic_glass_potions {
|
||||
.promo_armoire_backgrounds_201808 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -853px 0px;
|
||||
background-position: -421px -223px;
|
||||
width: 141px;
|
||||
height: 441px;
|
||||
}
|
||||
.promo_armoire_backgrounds_201807 {
|
||||
.promo_ember_potions {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -853px -442px;
|
||||
background-position: -563px -223px;
|
||||
width: 141px;
|
||||
height: 441px;
|
||||
}
|
||||
.promo_ios {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -477px 0px;
|
||||
background-position: 0px -337px;
|
||||
width: 375px;
|
||||
height: 361px;
|
||||
}
|
||||
.promo_mystery_201806 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -995px -442px;
|
||||
width: 121px;
|
||||
height: 114px;
|
||||
}
|
||||
.promo_seafoam {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -995px 0px;
|
||||
width: 141px;
|
||||
height: 441px;
|
||||
}
|
||||
.promo_seaserpent {
|
||||
.promo_kangaroo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px 0px;
|
||||
width: 476px;
|
||||
height: 364px;
|
||||
width: 420px;
|
||||
height: 336px;
|
||||
}
|
||||
.promo_seasonal_shop_summer {
|
||||
.promo_mystery_201808 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -401px -552px;
|
||||
width: 162px;
|
||||
height: 138px;
|
||||
}
|
||||
.promo_splashy_skins {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -142px -365px;
|
||||
width: 375px;
|
||||
height: 186px;
|
||||
}
|
||||
.customize-option.promo_splashy_skins {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -167px -380px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.promo_summer_splash_2018 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -365px;
|
||||
width: 141px;
|
||||
height: 588px;
|
||||
background-position: -734px -251px;
|
||||
width: 78px;
|
||||
height: 81px;
|
||||
}
|
||||
.promo_take_this {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -995px -557px;
|
||||
background-position: -734px -181px;
|
||||
width: 96px;
|
||||
height: 69px;
|
||||
}
|
||||
.promo_unconventional_armor {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -518px -365px;
|
||||
background-position: -734px 0px;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
}
|
||||
.scene_pomodoro {
|
||||
.scene_casting_spells {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -142px -552px;
|
||||
width: 258px;
|
||||
height: 258px;
|
||||
background-position: -421px 0px;
|
||||
width: 312px;
|
||||
height: 222px;
|
||||
}
|
||||
|
||||
@@ -354,13 +354,13 @@
|
||||
}
|
||||
.background_at_the_docks {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px 0px;
|
||||
background-position: -710px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_aurora {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -148px;
|
||||
background-position: -710px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -372,19 +372,19 @@
|
||||
}
|
||||
.background_back_of_giant_beast {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -296px;
|
||||
background-position: -710px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bamboo_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -444px;
|
||||
background-position: 0px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_beach {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -592px;
|
||||
background-position: -142px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -424,375 +424,387 @@
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_bug_covered_log {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1128px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_buried_treasure {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_champions_colosseum {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -148px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cherry_trees {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -296px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_chessboard_land {
|
||||
.background_bridge {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_clouds {
|
||||
.background_bug_covered_log {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -592px;
|
||||
background-position: -1277px 0px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_coral_reef {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -740px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cornfields {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cozy_library {
|
||||
.background_buried_treasure {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_crosscountry_ski_trail {
|
||||
.background_champions_colosseum {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -296px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cherry_trees {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -444px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_chessboard_land {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_crystal_cave {
|
||||
.background_clouds {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -141px -1184px;
|
||||
background-position: -1277px -740px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dark_deep {
|
||||
.background_coral_reef {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cornfields {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cozy_library {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_deep_mine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -423px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_deep_sea {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -564px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_desert_dunes {
|
||||
.background_crosscountry_ski_trail {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_castle {
|
||||
.background_crystal_cave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -846px -1184px;
|
||||
background-position: -282px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_city {
|
||||
.background_dark_deep {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_ruins {
|
||||
.background_deep_mine {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1128px -1184px;
|
||||
background-position: -564px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_distant_castle {
|
||||
.background_deep_sea {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1269px -1184px;
|
||||
background-position: -705px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_drifting_raft {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px 0px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_driving_a_coach {
|
||||
.background_desert_dunes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_driving_a_sleigh {
|
||||
.background_dilatory_castle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dusty_canyons {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -444px;
|
||||
background-position: -987px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_elegant_balcony {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fairy_ring {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -740px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fantastical_shoe_store {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_farmhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fiber_arts_room {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_floating_islands {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_floral_meadow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -141px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_a_field_of_wildflowers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.customize-option.background_flying_over_a_field_of_wildflowers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -309px -755px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.background_flying_over_an_ancient_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_icy_steppes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -705px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_frigid_peak {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -846px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_frozen_lake {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -987px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_garden_shed {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_gazebo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1269px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_birdhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1410px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_florals {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_seashell {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_wave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_gorgeous_greenhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_grand_staircase {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_graveyard {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -740px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_green {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_guardian_statues {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_gumdrop_land {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_habit_city_streets {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_harvest_feast {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_harvest_fields {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_harvest_moon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_haunted_house {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -423px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_ice_cave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_iceberg {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -705px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_idyllic_cabin {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -846px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_island_waterfalls {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -987px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_kelp_forest {
|
||||
.background_dilatory_city {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dilatory_ruins {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1269px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_distant_castle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px 0px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_drifting_raft {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -148px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_driving_a_coach {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_driving_a_sleigh {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_dusty_canyons {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -592px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_elegant_balcony {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fairy_ring {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fantastical_shoe_store {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_farmhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_fiber_arts_room {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_floating_islands {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -141px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_floral_meadow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -282px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_a_field_of_wildflowers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.customize-option.background_flying_over_a_field_of_wildflowers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -451px -755px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.background_flying_over_an_ancient_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_icy_steppes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_rocky_canyon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -852px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -987px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_frigid_peak {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1128px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_frozen_lake {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1269px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_garden_shed {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_gazebo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px 0px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_birdhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -148px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_florals {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -148px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_seashell {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -296px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_giant_wave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -444px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_gorgeous_greenhouse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_grand_staircase {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -994px -740px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_graveyard {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_green {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_guardian_statues {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_gumdrop_land {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_habit_city_streets {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_harvest_feast {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -282px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_harvest_fields {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -284px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_harvest_moon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_haunted_house {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -705px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_ice_cave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -568px -888px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_iceberg {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -987px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_idyllic_cabin {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -296px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_island_waterfalls {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -992px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_kelp_forest {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -710px 0px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_lighthouse_shore {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -990px -888px;
|
||||
background-position: -710px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_lilypad {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -849px -888px;
|
||||
background-position: -846px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_magic_beanstalk {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -708px -888px;
|
||||
background-position: -564px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -816,13 +828,13 @@
|
||||
}
|
||||
.background_market {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -282px -1480px;
|
||||
background-position: -1559px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_meandering_cave {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -141px -1480px;
|
||||
background-position: -1559px -740px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -834,7 +846,7 @@
|
||||
}
|
||||
.background_midnight_clouds {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -1036px;
|
||||
background-position: -1559px -444px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -846,31 +858,31 @@
|
||||
}
|
||||
.background_mist_shrouded_mountain {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -444px;
|
||||
background-position: -1410px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_mistiflying_circus {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -296px;
|
||||
background-position: -846px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_mountain_lake {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -148px;
|
||||
background-position: -705px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_mountain_pyramid {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px 0px;
|
||||
background-position: -564px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_night_dunes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1128px -1332px;
|
||||
background-position: -423px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -894,13 +906,13 @@
|
||||
}
|
||||
.background_orchard {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -1184px;
|
||||
background-position: -1128px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_pagodas {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -592px;
|
||||
background-position: -846px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -918,13 +930,13 @@
|
||||
}
|
||||
.background_pumpkin_patch {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -987px -1184px;
|
||||
background-position: 0px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_purple {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -705px -1184px;
|
||||
background-position: -1277px -592px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -948,13 +960,13 @@
|
||||
}
|
||||
.background_rainy_city {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -444px;
|
||||
background-position: -141px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_red {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px 0px;
|
||||
background-position: 0px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -984,61 +996,61 @@
|
||||
}
|
||||
.background_seafarer_ship {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -592px;
|
||||
background-position: -423px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_shimmering_ice_prism {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -444px;
|
||||
background-position: -141px -1480px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_shimmery_bubbles {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -567px -888px;
|
||||
background-position: -1559px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_slimy_swamp {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -426px -888px;
|
||||
background-position: -1559px -592px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_snowman_army {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -564px -1480px;
|
||||
background-position: -1559px -296px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_snowy_pines {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -1332px;
|
||||
background-position: 0px -1332px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_snowy_sunrise {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1559px -592px;
|
||||
background-position: -1418px -740px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_south_pole {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -564px -1332px;
|
||||
background-position: -1418px -444px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_sparkling_snowflake {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -423px -1332px;
|
||||
background-position: -423px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_spider_web {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -282px -1332px;
|
||||
background-position: -141px -1184px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
@@ -1050,61 +1062,49 @@
|
||||
}
|
||||
.background_spring_rain {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -148px;
|
||||
background-position: -1128px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_stable {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -282px -1184px;
|
||||
background-position: -564px -1036px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_stained_glass {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1184px;
|
||||
background-position: -1136px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_starry_skies {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1277px -1036px;
|
||||
background-position: -1136px -592px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_starry_winter_night {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -142px -592px;
|
||||
background-position: -284px -592px;
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_stoikalm_volcanoes {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -141px -1036px;
|
||||
background-position: -851px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_stone_circle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: 0px -1036px;
|
||||
background-position: -1277px -148px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_stormy_rooftops {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1136px -888px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_stormy_ship {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -1418px -296px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_strange_sewers {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-0.png');
|
||||
background-position: -564px -1036px;
|
||||
background-position: -1136px -444px;
|
||||
width: 140px;
|
||||
height: 147px;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 553 KiB After Width: | Height: | Size: 549 KiB |
|
Before Width: | Height: | Size: 432 KiB After Width: | Height: | Size: 449 KiB |
|
Before Width: | Height: | Size: 342 KiB After Width: | Height: | Size: 297 KiB |
|
Before Width: | Height: | Size: 323 KiB After Width: | Height: | Size: 346 KiB |
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 113 KiB |
@@ -2,8 +2,8 @@
|
||||
// possible values are: normal, fall, habitoween, thanksgiving, winter, nye, birthday, valentines, spring, summer
|
||||
// more to be added on future seasons
|
||||
|
||||
$npc_market_flavor: 'summer';
|
||||
$npc_quests_flavor: 'summer';
|
||||
$npc_seasonal_flavor: 'summer';
|
||||
$npc_timetravelers_flavor: 'summer';
|
||||
$npc_tavern_flavor: 'summer';
|
||||
$npc_market_flavor: 'normal';
|
||||
$npc_quests_flavor: 'normal';
|
||||
$npc_seasonal_flavor: 'normal';
|
||||
$npc_timetravelers_flavor: 'normal';
|
||||
$npc_tavern_flavor: 'normal';
|
||||
|
||||
@@ -164,30 +164,30 @@ export default {
|
||||
classGear (heroClass) {
|
||||
if (heroClass === 'rogue') {
|
||||
return {
|
||||
armor: 'armor_special_summer2018Rogue',
|
||||
head: 'head_special_summer2018Rogue',
|
||||
shield: 'shield_special_summer2018Rogue',
|
||||
weapon: 'weapon_special_summer2018Rogue',
|
||||
armor: 'armor_rogue_5',
|
||||
head: 'head_rogue_5',
|
||||
shield: 'shield_rogue_6',
|
||||
weapon: 'weapon_rogue_6',
|
||||
};
|
||||
} else if (heroClass === 'wizard') {
|
||||
return {
|
||||
armor: 'armor_special_summer2018Mage',
|
||||
head: 'head_special_summer2018Mage',
|
||||
weapon: 'weapon_special_summer2018Mage',
|
||||
armor: 'armor_wizard_5',
|
||||
head: 'head_wizard_5',
|
||||
weapon: 'weapon_wizard_6',
|
||||
};
|
||||
} else if (heroClass === 'healer') {
|
||||
return {
|
||||
armor: 'armor_special_summer2018Healer',
|
||||
head: 'head_special_summer2018Healer',
|
||||
shield: 'shield_special_summer2018Healer',
|
||||
weapon: 'weapon_special_summer2018Healer',
|
||||
armor: 'armor_healer_5',
|
||||
head: 'head_healer_5',
|
||||
shield: 'shield_healer_5',
|
||||
weapon: 'weapon_healer_6',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
armor: 'armor_special_summer2018Warrior',
|
||||
head: 'head_special_summer2018Warrior',
|
||||
shield: 'shield_special_summer2018Warrior',
|
||||
weapon: 'weapon_special_summer2018Warrior',
|
||||
armor: 'armor_warrior_5',
|
||||
head: 'head_warrior_5',
|
||||
shield: 'shield_warrior_5',
|
||||
weapon: 'weapon_warrior_6',
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,21 +6,21 @@ b-modal#login-incentives(:title="data.message", size='md', :hide-footer="true")
|
||||
.row.reward-row
|
||||
.col-12
|
||||
avatar.avatar(:member='user', :avatarOnly='true', :withBackground='true')
|
||||
.text-center.col-12
|
||||
.text-center.col-12(v-if='nextReward')
|
||||
.reward-wrap(v-if="!data.rewardText")
|
||||
div(v-if="nextReward.rewardKey.length === 1", :class="nextReward.rewardKey[0]")
|
||||
.reward(v-for="reward in nextReward.rewardKey", v-if="nextReward.rewardKey.length > 1", :class='reward')
|
||||
.reward-wrap(v-if="data.rewardText")
|
||||
div(v-if="data.rewardKey.length === 1", :class="data.rewardKey[0]")
|
||||
.reward(v-for="reward in data.rewardKey", v-if="data.rewardKey.length > 1", :class='reward')
|
||||
.col-12.text-center(v-if="data.nextRewardAt")
|
||||
.col-12.text-center(v-if="data && data.nextRewardAt")
|
||||
h4 {{ $t('countLeft', {count: data.nextRewardAt - user.loginIncentives}) }}
|
||||
.row
|
||||
.col-12.text-center(v-if='data.rewardText')
|
||||
p {{ $t('earnedRewardForDevotion', {reward: data.rewardText}) }}
|
||||
.col-12.text-center
|
||||
p {{ $t('incentivesDescription') }}
|
||||
.col-12.text-center(v-if="data.nextRewardAt")
|
||||
.col-12.text-center(v-if="data && data.nextRewardAt")
|
||||
h3 {{ $t('nextRewardUnlocksIn', {numberOfCheckinsLeft: data.nextRewardAt - user.loginIncentives}) }}
|
||||
.modal-footer
|
||||
.col-12.text-center
|
||||
@@ -70,8 +70,9 @@ export default {
|
||||
user: 'user.data',
|
||||
}),
|
||||
nextReward () {
|
||||
let nextRewardKey = this.loginIncentives[this.user.loginIncentives].nextRewardAt;
|
||||
let nextReward = this.loginIncentives[nextRewardKey];
|
||||
if (!this.loginIncentives[this.user.loginIncentives]) return;
|
||||
const nextRewardKey = this.loginIncentives[this.user.loginIncentives].nextRewardAt;
|
||||
const nextReward = this.loginIncentives[nextRewardKey];
|
||||
return nextReward;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
.social-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
white-space: inherit;
|
||||
text-align: center;
|
||||
|
||||
.text {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
.col-12.col-md-6
|
||||
.btn.btn-secondary.social-button(@click='socialAuth("google")')
|
||||
.svg-icon.social-icon(v-html="icons.googleIcon")
|
||||
span {{registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'})}}
|
||||
.text {{registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'})}}
|
||||
.form-group(v-if='registering')
|
||||
label(for='usernameInput', v-once) {{$t('username')}}
|
||||
input#usernameInput.form-control(type='text', :placeholder='$t("usernamePlaceholder")', v-model='username')
|
||||
@@ -207,6 +207,8 @@
|
||||
|
||||
.social-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
white-space: inherit;
|
||||
text-align: center;
|
||||
|
||||
.text {
|
||||
|
||||
@@ -15,22 +15,22 @@
|
||||
|
||||
// Show avatar only if not currently affected by visual buff
|
||||
template(v-if="showAvatar()")
|
||||
span(:class="'chair_' + member.preferences.chair")
|
||||
span(:class="getGearClass('back')")
|
||||
span(:class="skinClass")
|
||||
span(:class="member.preferences.size + '_shirt_' + member.preferences.shirt")
|
||||
span.head_0
|
||||
span(:class="member.preferences.size + '_' + getGearClass('armor')")
|
||||
span(:class="getGearClass('back_collar')")
|
||||
span(:class="['chair_' + member.preferences.chair, specialMountClass]")
|
||||
span(:class="[getGearClass('back'), specialMountClass]")
|
||||
span(:class="[skinClass, specialMountClass]")
|
||||
span(:class="[member.preferences.size + '_shirt_' + member.preferences.shirt, specialMountClass]")
|
||||
span(:class="['head_0', specialMountClass]")
|
||||
span(:class="[member.preferences.size + '_' + getGearClass('armor'), specialMountClass]")
|
||||
span(:class="[getGearClass('back_collar'), specialMountClass]")
|
||||
template(v-for="type in ['bangs', 'base', 'mustache', 'beard']")
|
||||
span(:class="'hair_' + type + '_' + member.preferences.hair[type] + '_' + member.preferences.hair.color")
|
||||
span(:class="getGearClass('body')")
|
||||
span(:class="getGearClass('eyewear')")
|
||||
span(:class="getGearClass('head')")
|
||||
span(:class="getGearClass('headAccessory')")
|
||||
span(:class="'hair_flower_' + member.preferences.hair.flower")
|
||||
span(v-if="!hideGear('shield')", :class="getGearClass('shield')")
|
||||
span(v-if="!hideGear('weapon')", :class="getGearClass('weapon')")
|
||||
span(:class="['hair_' + type + '_' + member.preferences.hair[type] + '_' + member.preferences.hair.color, specialMountClass]")
|
||||
span(:class="[getGearClass('body'), specialMountClass]")
|
||||
span(:class="[getGearClass('eyewear'), specialMountClass]")
|
||||
span(:class="[getGearClass('head'), specialMountClass]")
|
||||
span(:class="[getGearClass('headAccessory'), specialMountClass]")
|
||||
span(:class="['hair_flower_' + member.preferences.hair.flower, specialMountClass]")
|
||||
span(v-if="!hideGear('shield')", :class="[getGearClass('shield'), specialMountClass]")
|
||||
span(v-if="!hideGear('weapon')", :class="[getGearClass('weapon'), specialMountClass]")
|
||||
|
||||
// Resting
|
||||
span.zzz(v-if="member.preferences.sleep")
|
||||
@@ -67,6 +67,10 @@
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.offset-kangaroo {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -172,6 +176,11 @@ export default {
|
||||
costumeClass () {
|
||||
return this.member.preferences.costume ? 'costume' : 'equipped';
|
||||
},
|
||||
specialMountClass () {
|
||||
if (!this.avatarOnly && this.member.items.currentMount && this.member.items.currentMount.indexOf('Kangaroo') !== -1) {
|
||||
return 'offset-kangaroo';
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getGearClass (gearType) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.row
|
||||
challenge-modal(v-on:updatedChallenge='updatedChallenge')
|
||||
leave-challenge-modal(:challengeId='challenge._id')
|
||||
close-challenge-modal(:members='members', :challengeId='challenge._id')
|
||||
close-challenge-modal(:members='members', :challengeId='challenge._id', :prize='challenge.prize')
|
||||
challenge-member-progress-modal(:challengeId='challenge._id')
|
||||
.col-12.col-md-8.standard-page
|
||||
.row
|
||||
@@ -344,14 +344,14 @@ export default {
|
||||
this.tasksByType[task.type].splice(index, 1);
|
||||
},
|
||||
showMemberModal () {
|
||||
// @TODO: Change these to options and add a custom event to members modal
|
||||
this.$store.state.memberModalOptions.challengeId = this.challenge._id;
|
||||
this.$store.state.memberModalOptions.groupId = 'challenge'; // @TODO: change these terrible settings
|
||||
this.$store.state.memberModalOptions.group = this.group;
|
||||
this.$store.state.memberModalOptions.memberCount = this.challenge.memberCount;
|
||||
this.$store.state.memberModalOptions.viewingMembers = this.members;
|
||||
this.$store.state.memberModalOptions.fetchMoreMembers = this.loadMembers;
|
||||
this.$root.$emit('bv::show::modal', 'members-modal');
|
||||
this.$root.$emit('habitica:show-member-modal', {
|
||||
challengeId: this.challenge._id,
|
||||
groupId: 'challenge', // @TODO: change these terrible settings
|
||||
group: this.group,
|
||||
memberCount: this.challenge.memberCount,
|
||||
viewingMembers: this.members,
|
||||
fetchMoreMembers: this.loadMembers,
|
||||
});
|
||||
},
|
||||
async joinChallenge () {
|
||||
this.user.challenges.push(this.searchId);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
div.category-wrap(@click.prevent="toggleCategorySelect")
|
||||
span.category-select(v-if='workingChallenge.categories.length === 0') {{$t('none')}}
|
||||
.category-label(v-for='category in workingChallenge.categories') {{$t(categoriesHashByKey[category])}}
|
||||
.category-box(v-if="showCategorySelect")
|
||||
.category-box(v-if="showCategorySelect && creating")
|
||||
.form-check(
|
||||
v-for="group in categoryOptions",
|
||||
:key="group.key",
|
||||
|
||||
@@ -74,7 +74,7 @@ div
|
||||
import memberSearchDropdown from 'client/components/members/memberSearchDropdown';
|
||||
|
||||
export default {
|
||||
props: ['challengeId', 'members'],
|
||||
props: ['challengeId', 'members', 'prize'],
|
||||
components: {
|
||||
memberSearchDropdown,
|
||||
},
|
||||
@@ -102,7 +102,10 @@ export default {
|
||||
},
|
||||
async deleteChallenge () {
|
||||
if (!confirm('Are you sure you want to delete this challenge?')) return;
|
||||
this.challenge = await this.$store.dispatch('challenges:deleteChallenge', {challengeId: this.challengeId});
|
||||
this.challenge = await this.$store.dispatch('challenges:deleteChallenge', {
|
||||
challengeId: this.challengeId,
|
||||
prize: this.prize,
|
||||
});
|
||||
this.$router.push('/challenges/myChallenges');
|
||||
},
|
||||
},
|
||||
|
||||
@@ -11,26 +11,27 @@ div
|
||||
)
|
||||
| {{msg.user}}
|
||||
.svg-icon(v-html="tierIcon", v-if='showShowTierStyle')
|
||||
p.time {{msg.timestamp | timeAgo}}
|
||||
p.time(v-b-tooltip="", :title="msg.timestamp | date") {{msg.timestamp | timeAgo}}
|
||||
.text(v-markdown='msg.text')
|
||||
hr
|
||||
.action(@click='like()', v-if='!inbox && msg.likes', :class='{active: msg.likes[user._id]}')
|
||||
.svg-icon(v-html="icons.like")
|
||||
span(v-if='!msg.likes[user._id]') {{ $t('like') }}
|
||||
span(v-if='msg.likes[user._id]') {{ $t('liked') }}
|
||||
span.action(v-if='!inbox', @click='copyAsTodo(msg)')
|
||||
.svg-icon(v-html="icons.copy")
|
||||
| {{$t('copyAsTodo')}}
|
||||
span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted && msg.uuid !== "system"', @click='report(msg)')
|
||||
.svg-icon(v-html="icons.report")
|
||||
| {{$t('report')}}
|
||||
// @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys
|
||||
span.action(v-if='msg.uuid === user._id || inbox || user.contributor.admin', @click='remove()')
|
||||
.svg-icon(v-html="icons.delete")
|
||||
| {{$t('delete')}}
|
||||
span.action.float-right.liked(v-if='likeCount > 0')
|
||||
.svg-icon(v-html="icons.liked")
|
||||
| + {{ likeCount }}
|
||||
div(v-if='msg.id')
|
||||
.action(@click='like()', v-if='!inbox && msg.likes', :class='{active: msg.likes[user._id]}')
|
||||
.svg-icon(v-html="icons.like")
|
||||
span(v-if='!msg.likes[user._id]') {{ $t('like') }}
|
||||
span(v-if='msg.likes[user._id]') {{ $t('liked') }}
|
||||
span.action(v-if='!inbox', @click='copyAsTodo(msg)')
|
||||
.svg-icon(v-html="icons.copy")
|
||||
| {{$t('copyAsTodo')}}
|
||||
span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted && msg.uuid !== "system"', @click='report(msg)')
|
||||
.svg-icon(v-html="icons.report")
|
||||
| {{$t('report')}}
|
||||
// @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys
|
||||
span.action(v-if='msg.uuid === user._id || inbox || user.contributor.admin', @click='remove()')
|
||||
.svg-icon(v-html="icons.delete")
|
||||
| {{$t('delete')}}
|
||||
span.action.float-right.liked(v-if='likeCount > 0')
|
||||
.svg-icon(v-html="icons.liked")
|
||||
| + {{ likeCount }}
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -72,6 +73,7 @@ div
|
||||
.time {
|
||||
font-size: 12px;
|
||||
color: #878190;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.text {
|
||||
@@ -165,7 +167,7 @@ export default {
|
||||
return moment(value).fromNow();
|
||||
},
|
||||
date (value) {
|
||||
// @TODO: Add user preference
|
||||
// @TODO: Vue doesn't support this so we cant user preference
|
||||
return moment(value).toDate();
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.container
|
||||
.row
|
||||
.col-12
|
||||
copy-as-todo-modal(:group-name='groupName', :group-id='groupId')
|
||||
copy-as-todo-modal(:group-type='groupType', :group-name='groupName', :group-id='groupId')
|
||||
report-flag-modal
|
||||
div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)')
|
||||
// @TODO: is there a different way to do these conditionals? This creates an infinite loop
|
||||
@@ -87,7 +87,7 @@ import reportFlagModal from './reportFlagModal';
|
||||
import chatCard from './chatCard';
|
||||
|
||||
export default {
|
||||
props: ['chat', 'groupId', 'groupName', 'inbox'],
|
||||
props: ['chat', 'groupType', 'groupId', 'groupName', 'inbox'],
|
||||
components: {
|
||||
copyAsTodoModal,
|
||||
reportFlagModal,
|
||||
@@ -202,8 +202,17 @@ export default {
|
||||
|
||||
if (!profile._id) {
|
||||
const result = await this.$store.dispatch('members:fetchMember', { memberId });
|
||||
this.cachedProfileData[memberId] = result.data.data;
|
||||
profile = result.data.data;
|
||||
if (result.response && result.response.status === 404) {
|
||||
return this.$store.dispatch('snackbars:add', {
|
||||
title: 'Habitica',
|
||||
text: this.$t('messageDeletedUser'),
|
||||
type: 'error',
|
||||
timeout: false,
|
||||
});
|
||||
} else {
|
||||
this.cachedProfileData[memberId] = result.data.data;
|
||||
profile = result.data.data;
|
||||
}
|
||||
}
|
||||
|
||||
// Open the modal only if the data is available
|
||||
|
||||
@@ -18,6 +18,7 @@ import notificationsMixin from 'client/mixins/notifications';
|
||||
import Task from 'client/components/tasks/task';
|
||||
|
||||
import taskDefaults from 'common/script/libs/taskDefaults';
|
||||
import { TAVERN_ID } from '../../../common/script/constants';
|
||||
|
||||
const baseUrl = 'https://habitica.com';
|
||||
|
||||
@@ -29,7 +30,7 @@ export default {
|
||||
Task,
|
||||
},
|
||||
mixins: [notificationsMixin],
|
||||
props: ['copyingMessage', 'groupName', 'groupId'],
|
||||
props: ['copyingMessage', 'groupType', 'groupName', 'groupId'],
|
||||
data () {
|
||||
return {
|
||||
isUser: true,
|
||||
@@ -38,7 +39,7 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
this.$root.$on('habitica::copy-as-todo', message => {
|
||||
const notes = `${message.user || 'system message'}${message.user ? ' wrote' : ''} in [${this.groupName}](${baseUrl}/groups/guild/${this.groupId})`;
|
||||
const notes = `${message.user || 'system message'}${message.user ? ' wrote' : ''} in [${this.groupName}](${this.groupPath()})`;
|
||||
const newTask = {
|
||||
text: message.text,
|
||||
type: 'todo',
|
||||
@@ -55,6 +56,15 @@ export default {
|
||||
...mapActions({
|
||||
createTask: 'tasks:create',
|
||||
}),
|
||||
groupPath () {
|
||||
if (this.groupId === TAVERN_ID) {
|
||||
return `${baseUrl}/groups/tavern`;
|
||||
} else if (this.groupType === 'party') {
|
||||
return `${baseUrl}/party`;
|
||||
} else {
|
||||
return `${baseUrl}/groups/guild/${this.groupId}`;
|
||||
}
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'copyAsTodo');
|
||||
},
|
||||
|
||||
@@ -222,7 +222,7 @@ b-modal#avatar-modal(title="", :size='editing ? "lg" : "md"', :hide-header='true
|
||||
.col-12.customize-options
|
||||
.option(@click='set({"preferences.chair": "none"})', :class='{active: user.preferences.chair === "none"}')
|
||||
| None
|
||||
.option(v-for='option in ["black", "blue", "green", "pink", "red", "yellow"]',
|
||||
.option(v-for='option in chairKeys',
|
||||
:class='{active: user.preferences.chair === option}')
|
||||
.chair.sprite.customize-option(:class="`button_chair_${option}`", @click='set({"preferences.chair": option})')
|
||||
#flowers.row(v-if='activeSubPage === "flower"')
|
||||
@@ -856,7 +856,7 @@ import isPinned from 'common/script/libs/isPinned';
|
||||
const skinsBySet = groupBy(appearance.skin, 'set.key');
|
||||
const hairColorBySet = groupBy(appearance.hair.color, 'set.key');
|
||||
|
||||
let tasksByCategory = {
|
||||
const tasksByCategory = {
|
||||
work: [
|
||||
{
|
||||
type: 'habit',
|
||||
@@ -1014,6 +1014,7 @@ export default {
|
||||
baseHair5Keys: [1, 2],
|
||||
baseHair6Keys: [1, 2, 3],
|
||||
animalEarsKeys: ['bearEars', 'cactusEars', 'foxEars', 'lionEars', 'pandaEars', 'pigEars', 'tigerEars', 'wolfEars'],
|
||||
chairKeys: ['black', 'blue', 'green', 'pink', 'red', 'yellow', 'handleless_black', 'handleless_blue', 'handleless_green', 'handleless_pink', 'handleless_red', 'handleless_yellow'],
|
||||
icons: Object.freeze({
|
||||
logoPurple,
|
||||
bodyIcon,
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
.row
|
||||
.hr.col-12
|
||||
chat-message(:chat.sync='group.chat', :group-id='group._id', :group-name='group.name')
|
||||
chat-message(:chat.sync='group.chat', :group-type='group.type', :group-id='group._id', :group-name='group.name')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -19,19 +19,20 @@ b-modal#create-party-modal(title="Empty", size='lg', hide-footer=true)
|
||||
p(v-once) {{$t('wantToJoinPartyDescription')}}
|
||||
button.btn.btn-primary(v-once, @click='shareUserId()') {{$t('shartUserId')}}
|
||||
.share-userid-options(v-if="shareUserIdShown")
|
||||
.option-item(v-once)
|
||||
.option-item(@click='copyUserId()')
|
||||
.svg-icon(v-html="icons.copy")
|
||||
input(type="text", v-model="user._id", id="userIdInput")
|
||||
| Copy User ID
|
||||
.option-item(v-once)
|
||||
//.option-item(v-once)
|
||||
.svg-icon(v-html="icons.greyBadge")
|
||||
| {{$t('lookingForGroup')}}
|
||||
.option-item(v-once)
|
||||
//.option-item(v-once)
|
||||
.svg-icon(v-html="icons.qrCode")
|
||||
| {{$t('qrCode')}}
|
||||
.option-item(v-once)
|
||||
//.option-item(v-once)
|
||||
.svg-icon.facebook(v-html="icons.facebook")
|
||||
| Facebook
|
||||
.option-item(v-once)
|
||||
//.option-item(v-once)
|
||||
.svg-icon(v-html="icons.twitter")
|
||||
| Twitter
|
||||
</template>
|
||||
@@ -108,10 +109,15 @@ b-modal#create-party-modal(title="Empty", size='lg', hide-footer=true)
|
||||
border-radius: 2px;
|
||||
width: 220px;
|
||||
position: absolute;
|
||||
top: -8em;
|
||||
top: 9em;
|
||||
left: 4.8em;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
|
||||
#userIdInput {
|
||||
position: absolute;
|
||||
left: 1000rem;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
padding: 1em;
|
||||
|
||||
@@ -183,6 +189,12 @@ export default {
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
this.$router.push('/party');
|
||||
},
|
||||
copyUserId () {
|
||||
const copyText = document.getElementById('userIdInput');
|
||||
copyText.select();
|
||||
document.execCommand('copy');
|
||||
alert('User ID has been copied');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
group-form-modal(v-if='isParty')
|
||||
start-quest-modal(:group='this.group')
|
||||
quest-details-modal(:group='this.group')
|
||||
participant-list-modal(:group='this.group')
|
||||
group-gems-modal
|
||||
.col-12.col-sm-8.standard-page
|
||||
.row
|
||||
@@ -126,7 +127,7 @@
|
||||
.sidebar {
|
||||
background-color: $gray-600;
|
||||
padding-bottom: 2em;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.buttons-wrapper {
|
||||
@@ -262,6 +263,7 @@ import * as Analytics from 'client/libs/analytics';
|
||||
import membersModal from './membersModal';
|
||||
import startQuestModal from './startQuestModal';
|
||||
import questDetailsModal from './questDetailsModal';
|
||||
import participantListModal from './participantListModal';
|
||||
import groupFormModal from './groupFormModal';
|
||||
import groupChallenges from '../challenges/groupChallenges';
|
||||
import groupGemsModal from 'client/components/groups/groupGemsModal';
|
||||
@@ -292,6 +294,7 @@ export default {
|
||||
groupFormModal,
|
||||
groupChallenges,
|
||||
questDetailsModal,
|
||||
participantListModal,
|
||||
groupGemsModal,
|
||||
questSidebarSection,
|
||||
sidebarSection,
|
||||
@@ -426,12 +429,13 @@ export default {
|
||||
return this.$store.dispatch('members:getGroupMembers', payload);
|
||||
},
|
||||
showMemberModal () {
|
||||
this.$store.state.memberModalOptions.groupId = this.group._id;
|
||||
this.$store.state.memberModalOptions.group = this.group;
|
||||
this.$store.state.memberModalOptions.memberCount = this.group.memberCount;
|
||||
this.$store.state.memberModalOptions.viewingMembers = this.members;
|
||||
this.$store.state.memberModalOptions.fetchMoreMembers = this.loadMembers;
|
||||
this.$root.$emit('bv::show::modal', 'members-modal');
|
||||
this.$root.$emit('habitica:show-member-modal', {
|
||||
groupId: this.group._id,
|
||||
group: this.group,
|
||||
memberCount: this.group.memberCount,
|
||||
viewingMembers: this.members,
|
||||
fetchMoreMembers: this.loadMembers,
|
||||
});
|
||||
},
|
||||
fetchRecentMessages () {
|
||||
this.fetchGuild();
|
||||
@@ -538,24 +542,6 @@ export default {
|
||||
this.$store.state.upgradingGroup = this.group;
|
||||
this.$router.push('/group-plans');
|
||||
},
|
||||
clickStartQuest () {
|
||||
Analytics.track({
|
||||
hitType: 'event',
|
||||
eventCategory: 'button',
|
||||
eventAction: 'click',
|
||||
eventLabel: 'Start a Quest',
|
||||
});
|
||||
|
||||
let hasQuests = find(this.user.items.quests, (quest) => {
|
||||
return quest > 0;
|
||||
});
|
||||
|
||||
if (hasQuests) {
|
||||
this.$root.$emit('bv::show::modal', 'start-quest-modal');
|
||||
return;
|
||||
}
|
||||
// $rootScope.$state.go('options.inventory.quests');
|
||||
},
|
||||
showGroupGems () {
|
||||
this.$root.$emit('bv::show::modal', 'group-gems-modal');
|
||||
},
|
||||
|
||||
@@ -53,7 +53,7 @@ div
|
||||
span.dropdown-icon-item
|
||||
.svg-icon.inline(v-html="icons.removeIcon")
|
||||
span.text {{$t('removeManager2')}}
|
||||
b-dropdown-item(@click='viewProgress(member)')
|
||||
b-dropdown-item(@click='viewProgress(member)', v-if='challengeId')
|
||||
span.dropdown-icon-item
|
||||
span.text {{ $t('viewProgress') }}
|
||||
.row(v-if='isLoadMoreAvailable')
|
||||
@@ -278,7 +278,20 @@ export default {
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.getMembers();
|
||||
this.$root.$on('habitica:show-member-modal', (data) => {
|
||||
// @TODO: Remove store
|
||||
this.$store.state.memberModalOptions.challengeId = data.challengeId;
|
||||
this.$store.state.memberModalOptions.groupId = data.groupId;
|
||||
this.$store.state.memberModalOptions.group = data.group;
|
||||
this.$store.state.memberModalOptions.memberCount = data.memberCount;
|
||||
this.$store.state.memberModalOptions.viewingMembers = data.viewingMembers;
|
||||
this.$store.state.memberModalOptions.fetchMoreMembers = data.fetchMoreMembers;
|
||||
this.$root.$emit('bv::show::modal', 'members-modal');
|
||||
this.getMembers();
|
||||
});
|
||||
},
|
||||
destroyed () {
|
||||
this.$root.$off('habitica:show-member-modal');
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
@@ -325,6 +338,9 @@ export default {
|
||||
// @TOOD: We might not need this since groupId is computed now
|
||||
this.getMembers();
|
||||
},
|
||||
challengeId () {
|
||||
this.getMembers();
|
||||
},
|
||||
group () {
|
||||
this.getMembers();
|
||||
},
|
||||
@@ -363,9 +379,8 @@ export default {
|
||||
});
|
||||
this.invites = invites;
|
||||
}
|
||||
if (this.$store.state.memberModalOptions.viewingMembers.length > 0) {
|
||||
this.members = this.$store.state.memberModalOptions.viewingMembers;
|
||||
}
|
||||
|
||||
this.members = this.$store.state.memberModalOptions.viewingMembers;
|
||||
},
|
||||
async clickMember (uid, forceShow) {
|
||||
let user = this.$store.state.user.data;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<template lang="pug">
|
||||
b-modal#participant-list(size='md', :hide-footer='true')
|
||||
.header-wrap(slot="modal-header")
|
||||
.row
|
||||
.col-6
|
||||
h1(v-once) {{ $t('participantsTitle') }}
|
||||
.col-6
|
||||
button(type="button" aria-label="Close" class="close", @click='close()')
|
||||
span(aria-hidden="true") ×
|
||||
.row(v-for='member in participants')
|
||||
.col-12.no-padding-left
|
||||
member-details(:member='member')
|
||||
.modal-footer
|
||||
button.btn.btn-primary(@click='close()') {{ $t('close') }}
|
||||
</template>
|
||||
|
||||
<style lang='scss'>
|
||||
#participant-list {
|
||||
.modal-header {
|
||||
background-color: #edecee;
|
||||
border-radius: 8px 8px 0 0;
|
||||
box-shadow: 0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
background-color: #edecee;
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
.small-text, .character-name {
|
||||
color: #878190;
|
||||
}
|
||||
|
||||
.no-padding-left {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.member-details {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.header-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #4f2a93;
|
||||
}
|
||||
|
||||
#participant-list_modal_body {
|
||||
padding: 0;
|
||||
max-height: 450px;
|
||||
|
||||
.member-details {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'client/libs/store';
|
||||
|
||||
import MemberDetails from '../memberDetails';
|
||||
|
||||
export default {
|
||||
props: ['group'],
|
||||
components: {
|
||||
MemberDetails,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
partyMembers: 'party:members',
|
||||
}),
|
||||
participants () {
|
||||
let partyMembers = this.partyMembers || [];
|
||||
return partyMembers.filter(member => this.group.quest.members[member._id] === true);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'participant-list');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -76,10 +76,18 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
|
||||
|
||||
.gold {
|
||||
color: #fdbb5a;
|
||||
|
||||
.member-count {
|
||||
color: #fdbb5a;
|
||||
}
|
||||
}
|
||||
|
||||
.silver {
|
||||
color: #c2c2c2;
|
||||
|
||||
.member-count {
|
||||
color: #c2c2c2;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-column {
|
||||
|
||||
@@ -24,6 +24,9 @@ sidebar-section(:title="$t('questDetailsTitle')")
|
||||
h3(v-once) {{ questData.text() }}
|
||||
.quest-box
|
||||
.collect-info(v-if='questData.collect')
|
||||
.row
|
||||
.col-12
|
||||
a.float-right(@click="openParticipantList()") {{ $t('participantsTitle') }}
|
||||
.row(v-for='(value, key) in questData.collect')
|
||||
.col-2
|
||||
div(:class="'quest_' + questData.key + '_' + key")
|
||||
@@ -38,7 +41,7 @@ sidebar-section(:title="$t('questDetailsTitle')")
|
||||
.col-6
|
||||
h4.float-left(v-once) {{ questData.boss.name() }}
|
||||
.col-6
|
||||
span.float-right(v-once) {{ $t('participantsTitle') }}
|
||||
a.float-right(@click="openParticipantList()") {{ $t('participantsTitle') }}
|
||||
.row
|
||||
.col-12
|
||||
.grey-progress-bar
|
||||
@@ -134,6 +137,12 @@ sidebar-section(:title="$t('questDetailsTitle')")
|
||||
padding: .5em;
|
||||
margin-bottom: 1em;
|
||||
|
||||
a {
|
||||
font-family: 'Roboto Condensed', sans-serif;
|
||||
font-weight: bold;
|
||||
color: $gray-10;
|
||||
}
|
||||
|
||||
svg: {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -258,6 +267,9 @@ export default {
|
||||
openQuestDetails () {
|
||||
this.$root.$emit('bv::show::modal', 'quest-details');
|
||||
},
|
||||
openParticipantList () {
|
||||
this.$root.$emit('bv::show::modal', 'participant-list');
|
||||
},
|
||||
async questAbort () {
|
||||
if (!confirm(this.$t('sureAbort'))) return;
|
||||
if (!confirm(this.$t('doubleSureAbort'))) return;
|
||||
|
||||
@@ -148,8 +148,13 @@ export default {
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
let questKeys = Object.keys(this.user.items.quests);
|
||||
this.selectedQuest = questKeys[0];
|
||||
const userQuests = this.user.items.quests;
|
||||
for (const key in userQuests) {
|
||||
if (userQuests[key] > 0) {
|
||||
this.selectedQuest = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.$root.$on('selectQuest', this.selectQuest);
|
||||
},
|
||||
@@ -177,13 +182,14 @@ export default {
|
||||
let groupId = this.group._id || this.user.party._id;
|
||||
|
||||
const key = this.selectedQuest;
|
||||
const response = await this.$store.dispatch('guilds:inviteToQuest', {groupId, key});
|
||||
const quest = response.data.data;
|
||||
|
||||
if (this.$store.state.party.data) this.$store.state.party.data.quest = quest;
|
||||
|
||||
this.loading = false;
|
||||
try {
|
||||
const response = await this.$store.dispatch('guilds:inviteToQuest', {groupId, key});
|
||||
const quest = response.data.data;
|
||||
|
||||
if (this.$store.state.party.data) this.$store.state.party.data.quest = quest;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
this.$root.$emit('bv::hide::modal', 'start-quest-modal');
|
||||
},
|
||||
},
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-if='hero.flags', v-model='hero.flags.chatRevoked')
|
||||
| Chat Privileges Revoked
|
||||
strong Chat Privileges Revoked
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
@@ -103,10 +103,10 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// import keys from 'lodash/keys';
|
||||
import each from 'lodash/each';
|
||||
|
||||
import markdownDirective from 'client/directives/markdown';
|
||||
import styleHelper from 'client/mixins/styleHelper';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import quests from 'common/script/content/quests';
|
||||
import { mountInfo, petInfo } from 'common/script/content/stable';
|
||||
@@ -115,7 +115,7 @@ import gear from 'common/script/content/gear';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
export default {
|
||||
mixins: [notifications],
|
||||
mixins: [notifications, styleHelper],
|
||||
data () {
|
||||
return {
|
||||
heroes: [],
|
||||
@@ -174,7 +174,7 @@ export default {
|
||||
async loadHero (uuid, heroIndex) {
|
||||
this.currentHeroIndex = heroIndex;
|
||||
let hero = await this.$store.dispatch('hall:getHero', { uuid });
|
||||
this.hero = Object.assign({}, this.hero, hero);
|
||||
this.hero = Object.assign({}, hero);
|
||||
if (!this.hero.flags) {
|
||||
this.hero.flags = {
|
||||
chatRevoked: false,
|
||||
@@ -204,9 +204,6 @@ export default {
|
||||
startingPage: 'profile',
|
||||
});
|
||||
},
|
||||
userLevelStyle () {
|
||||
// @TODO: implement
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -35,26 +35,11 @@ div
|
||||
span.small-text(v-html="$t('inviteFriendsParty')")
|
||||
br
|
||||
button.btn.btn-primary(@click='createOrInviteParty()') {{ user.party._id ? $t('inviteFriends') : $t('startAParty') }}
|
||||
a.useMobileApp(v-if="isAndroidMobile()", v-once, href="https://play.google.com/store/apps/details?id=com.habitrpg.android.habitica") {{ $t('useMobileApps') }}
|
||||
a.useMobileApp(v-if="isIOSMobile()", v-once, href="https://itunes.apple.com/us/app/habitica-gamified-task-manager/id994882113?mt=8") {{ $t('useMobileApps') }}
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.useMobileApp {
|
||||
background: red;
|
||||
color: white;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
margin: 10px 5px 0 0;
|
||||
height: 64px;
|
||||
text-align: center;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#app-header {
|
||||
padding-left: 24px;
|
||||
padding-top: 9px;
|
||||
@@ -155,12 +140,6 @@ export default {
|
||||
...mapActions({
|
||||
getPartyMembers: 'party:getMembers',
|
||||
}),
|
||||
isAndroidMobile () {
|
||||
return navigator.userAgent.match(/Android/i);
|
||||
},
|
||||
isIOSMobile () {
|
||||
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
|
||||
},
|
||||
expandMember (memberId) {
|
||||
if (this.expandedMember === memberId) {
|
||||
this.expandedMember = null;
|
||||
@@ -176,11 +155,11 @@ export default {
|
||||
}
|
||||
},
|
||||
showPartyMembers () {
|
||||
// Set the party details for the members-modal component
|
||||
this.$store.state.memberModalOptions.groupId = this.user.party._id;
|
||||
this.$store.state.memberModalOptions.viewingMembers = this.partyMembers;
|
||||
this.$store.state.memberModalOptions.group = this.user.party;
|
||||
this.$root.$emit('bv::show::modal', 'members-modal');
|
||||
this.$root.$emit('habitica:show-member-modal', {
|
||||
groupId: this.user.party._id,
|
||||
viewingMembers: this.partyMembers,
|
||||
group: this.user.party,
|
||||
});
|
||||
},
|
||||
setPartyMembersWidth ($event) {
|
||||
if (this.currentWidth !== $event.width) {
|
||||
|
||||
@@ -396,12 +396,13 @@ export default {
|
||||
toggleUserDropdown () {
|
||||
this.isUserDropdownOpen = !this.isUserDropdownOpen;
|
||||
},
|
||||
sync () {
|
||||
async sync () {
|
||||
this.$root.$emit('habitica::resync-requested');
|
||||
return Promise.all([
|
||||
await Promise.all([
|
||||
this.$store.dispatch('user:fetch', {forceLoad: true}),
|
||||
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
|
||||
]);
|
||||
this.$root.$emit('habitica::resync-completed');
|
||||
},
|
||||
async getUserGroupPlans () {
|
||||
this.$store.state.groupPlans = await this.$store.dispatch('guilds:getGroupPlans');
|
||||
|
||||
@@ -27,8 +27,8 @@ menu-dropdown.item-notifications(:right="true", @toggled="handleOpenStatusChange
|
||||
v-if="notificationsCount === 0"
|
||||
)
|
||||
.svg-icon(v-html="icons.success")
|
||||
h2 You're all caught up!
|
||||
p The notification fairies give you a raucous round of applause! Well done!
|
||||
h2 {{ $t('noNotifications') }}
|
||||
p {{ $t('noNotificationsText') }}
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
||||
@@ -8,8 +8,8 @@ menu-dropdown.item-user(:right="true")
|
||||
a.dropdown-item.edit-avatar.dropdown-separated(@click='showAvatar()')
|
||||
h3 {{ user.profile.name }}
|
||||
span.small-text {{ $t('editAvatar') }}
|
||||
a.nav-link.dropdown-item.dropdown-separated(@click.prevent='showInbox()')
|
||||
| {{ $t('messages') }}
|
||||
a.nav-link.dropdown-item.dropdown-separated.d-flex.justify-content-between.align-items-center(@click.prevent='showInbox()')
|
||||
div {{ $t('messages') }}
|
||||
message-count(v-if='user.inbox.newMessages > 0', :count="user.inbox.newMessages")
|
||||
a.dropdown-item(@click='showAvatar("backgrounds", "2018")') {{ $t('backgrounds') }}
|
||||
a.dropdown-item(@click='showProfile("stats")') {{ $t('stats') }}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<template lang="pug">
|
||||
b-modal#hatching-modal(@change="resetHatchablePet($event)")
|
||||
div.content(v-if="hatchablePet")
|
||||
div.potionEggGroup
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_HatchingPotion_'+hatchablePet.potionKey")
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_Egg_'+hatchablePet.eggKey")
|
||||
h4.title {{ hatchablePet.name }}
|
||||
div.text(v-html="$t('hatchDialogText', { potionName: hatchablePet.potionName, eggName: hatchablePet.eggName, petName: hatchablePet.name })")
|
||||
span.svg-icon.icon-10(v-html="icons.close", slot="modal-header", @click="closeHatchPetDialog()")
|
||||
div(slot="modal-footer")
|
||||
button.btn.btn-primary(@click="hatchPet(hatchablePet)") {{ $t('hatch') }}
|
||||
button.btn.btn-secondary.btn-flat(@click="closeHatchPetDialog()") {{ $t('cancel') }}
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~client/assets/scss/modal.scss';
|
||||
|
||||
#hatching-modal {
|
||||
@include centeredModal();
|
||||
|
||||
.modal-dialog {
|
||||
width: 310px;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
margin: 9px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
color: #4e4a57;
|
||||
}
|
||||
|
||||
.text {
|
||||
height: 60px;
|
||||
font-size: 14px;
|
||||
line-height: 1.43;
|
||||
text-align: center;
|
||||
color: #686274;
|
||||
}
|
||||
|
||||
span.svg-icon.icon-10 {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import svgClose from 'assets/svg/close.svg';
|
||||
|
||||
import petMixin from 'client/mixins/petMixin';
|
||||
|
||||
export default {
|
||||
props: ['hatchablePet'],
|
||||
mixins: [petMixin],
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close: svgClose,
|
||||
}),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetHatchablePet ($event) {
|
||||
if (!$event) {
|
||||
this.hatchablePet = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,245 +1,205 @@
|
||||
<template lang="pug">
|
||||
// @TODO: breakdown to componentes and use some SOLID
|
||||
.row.stable(v-mousePosition="30", @mouseMoved="mouseMoved($event)")
|
||||
.standard-sidebar.d-none.d-sm-block
|
||||
div
|
||||
#npmMattStable.npc_matt
|
||||
b-popover(
|
||||
triggers="hover",
|
||||
placement="right",
|
||||
target="npmMattStable"
|
||||
)
|
||||
h4.popover-content-title(v-once) {{ $t('mattBoch') }}
|
||||
.popover-content-text(v-once) {{ $t('mattBochText1') }}
|
||||
|
||||
.row.stable(v-mousePosition="30", @mouseMoved="mouseMoved($event)")
|
||||
.standard-sidebar.d-none.d-sm-block
|
||||
div
|
||||
#npmMattStable.npc_matt
|
||||
b-popover(
|
||||
triggers="hover",
|
||||
placement="right",
|
||||
target="npmMattStable"
|
||||
)
|
||||
h4.popover-content-title(v-once) {{ $t('mattBoch') }}
|
||||
.popover-content-text(v-once) {{ $t('mattBochText1') }}
|
||||
.form-group
|
||||
input.form-control.input-search(type="text", v-model="searchText", :placeholder="$t('search')")
|
||||
.form
|
||||
h2(v-once) {{ $t('filter') }}
|
||||
h3(v-once) {{ $t('pets') }}
|
||||
.form-group
|
||||
input.form-control.input-search(type="text", v-model="searchText", :placeholder="$t('search')")
|
||||
|
||||
.form
|
||||
h2(v-once) {{ $t('filter') }}
|
||||
h3(v-once) {{ $t('pets') }}
|
||||
.form-group
|
||||
.form-check(
|
||||
v-for="petGroup in petGroups",
|
||||
:key="petGroup.key"
|
||||
)
|
||||
.custom-control.custom-checkbox
|
||||
input.custom-control-input(
|
||||
type="checkbox",
|
||||
v-model="viewOptions[petGroup.key].selected",
|
||||
:disabled="viewOptions[petGroup.key].animalCount == 0",
|
||||
:id="petGroup.key",
|
||||
)
|
||||
label.custom-control-label(v-once, :for="petGroup.key") {{ petGroup.label }}
|
||||
h3(v-once) {{ $t('mounts') }}
|
||||
.form-group
|
||||
.form-check(
|
||||
v-for="mountGroup in mountGroups",
|
||||
:key="mountGroup.key"
|
||||
)
|
||||
.custom-control.custom-checkbox
|
||||
input.custom-control-input(
|
||||
type="checkbox",
|
||||
v-model="viewOptions[mountGroup.key].selected",
|
||||
:disabled="viewOptions[mountGroup.key].animalCount == 0",
|
||||
:id="mountGroup.key",
|
||||
)
|
||||
label.custom-control-label(v-once, :for="mountGroup.key") {{ mountGroup.label }}
|
||||
|
||||
div.form-group.clearfix
|
||||
h3.float-left {{ $t('hideMissing') }}
|
||||
toggle-switch.float-right(
|
||||
:checked="hideMissing",
|
||||
@change="updateHideMissing"
|
||||
)
|
||||
.standard-page
|
||||
.clearfix
|
||||
h1.float-left.mb-4.page-header(v-once) {{ $t('stable') }}
|
||||
|
||||
div.float-right
|
||||
span.dropdown-label {{ $t('sortBy') }}
|
||||
b-dropdown(:text="$t(selectedSortBy)", right=true)
|
||||
b-dropdown-item(
|
||||
v-for="sort in sortByItems",
|
||||
@click="selectedSortBy = sort",
|
||||
:active="selectedSortBy === sort",
|
||||
:key="sort"
|
||||
) {{ $t(sort) }}
|
||||
|
||||
h2.mb-3
|
||||
| {{ $t('pets') }}
|
||||
|
|
||||
span.badge.badge-pill.badge-default {{countOwnedAnimals(petGroups[0], 'pet')}}
|
||||
|
||||
div(
|
||||
v-for="(petGroup, index) in petGroups",
|
||||
v-if="viewOptions[petGroup.key].selected",
|
||||
:key="petGroup.key"
|
||||
)
|
||||
h4(v-if="viewOptions[petGroup.key].animalCount !== 0") {{ petGroup.label }}
|
||||
|
||||
.pet-row.d-flex(
|
||||
v-for="(group, key, index) in pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)",
|
||||
v-if='index === 0 || $_openedItemRows_isToggled(petGroup.key)')
|
||||
.pet-group(
|
||||
v-for='item in group'
|
||||
v-drag.drop.food="item.key",
|
||||
@itemDragOver="onDragOver($event, item)",
|
||||
@itemDropped="onDrop($event, item)",
|
||||
@itemDragLeave="onDragLeave()",
|
||||
:class="{'last': item.isLastInRow}"
|
||||
)
|
||||
petItem(
|
||||
:item="item",
|
||||
:itemContentClass="getPetItemClass(item)",
|
||||
:popoverPosition="'top'",
|
||||
:progress="item.progress",
|
||||
:emptyItem="!item.isOwned()",
|
||||
:showPopover="currentDraggingFood == null",
|
||||
:highlightBorder="highlightPet == item.key",
|
||||
@click="petClicked(item)"
|
||||
)
|
||||
span(slot="popoverContent")
|
||||
div.hatchablePopover(v-if="item.isHatchable()")
|
||||
h4.popover-content-title {{ item.name }}
|
||||
div.popover-content-text(v-html="$t('haveHatchablePet', { potion: item.potionName, egg: item.eggName })")
|
||||
div.potionEggGroup
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_HatchingPotion_'+item.potionKey")
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_Egg_'+item.eggKey")
|
||||
div(v-else)
|
||||
h4.popover-content-title {{ item.name }}
|
||||
template(slot="itemBadge", slot-scope="context")
|
||||
starBadge(:selected="item.key === currentPet", :show="item.isOwned()", @click="selectPet(item)")
|
||||
|
||||
.btn.btn-flat.btn-show-more(@click="setShowMore(petGroup.key)", v-if='petGroup.key !== "specialPets"')
|
||||
| {{ $_openedItemRows_isToggled(petGroup.key) ? $t('showLess') : $t('showMore') }}
|
||||
|
||||
h2
|
||||
| {{ $t('mounts') }}
|
||||
|
|
||||
span.badge.badge-pill.badge-default {{countOwnedAnimals(mountGroups[0], 'mount')}}
|
||||
|
||||
div(
|
||||
v-for="mountGroup in mountGroups",
|
||||
v-if="viewOptions[mountGroup.key].selected",
|
||||
:key="mountGroup.key"
|
||||
)
|
||||
h4(v-if="viewOptions[mountGroup.key].animalCount != 0") {{ mountGroup.label }}
|
||||
|
||||
.pet-row.d-flex(v-for="(group, key, index) in mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)"
|
||||
v-if='index === 0 || $_openedItemRows_isToggled(mountGroup.key)')
|
||||
.pet-group(v-for='item in group')
|
||||
mountItem(
|
||||
:item="item",
|
||||
:itemContentClass="item.isOwned() ? ('Mount_Icon_' + item.key) : 'PixelPaw GreyedOut'",
|
||||
:key="item.key",
|
||||
:popoverPosition="'top'",
|
||||
:emptyItem="!item.isOwned()",
|
||||
:showPopover="true",
|
||||
@click="selectMount(item)"
|
||||
)
|
||||
span(slot="popoverContent")
|
||||
h4.popover-content-title {{ item.name }}
|
||||
template(slot="itemBadge", slot-scope="context")
|
||||
starBadge(
|
||||
:selected="item.key === currentMount",
|
||||
:show="item.isOwned()",
|
||||
@click="selectMount(item)",
|
||||
)
|
||||
|
||||
.btn.btn-flat.btn-show-more(@click="setShowMore(mountGroup.key)", v-if='mountGroup.key !== "specialMounts"')
|
||||
| {{ $_openedItemRows_isToggled(mountGroup.key) ? $t('showLess') : $t('showMore') }}
|
||||
|
||||
drawer(
|
||||
:title="$t('quickInventory')",
|
||||
:errorMessage="(!hasDrawerTabItems(selectedDrawerTab)) ? ((selectedDrawerTab === 0) ? $t('noFoodAvailable') : $t('noSaddlesAvailable')) : null"
|
||||
)
|
||||
div(slot="drawer-header")
|
||||
.drawer-tab-container
|
||||
.drawer-tab.text-right
|
||||
a.drawer-tab-text(
|
||||
@click="selectedDrawerTab = 0",
|
||||
:class="{'drawer-tab-text-active': selectedDrawerTab === 0}",
|
||||
) {{ drawerTabs[0].label }}
|
||||
.clearfix
|
||||
.drawer-tab.float-left
|
||||
a.drawer-tab-text(
|
||||
@click="selectedDrawerTab = 1",
|
||||
:class="{ 'drawer-tab-text-active': selectedDrawerTab === 1 }",
|
||||
) {{ drawerTabs[1].label }}
|
||||
|
||||
#petLikeToEatStable.drawer-help-text(v-once)
|
||||
| {{ $t('petLikeToEat') + ' ' }}
|
||||
span.svg-icon.inline.icon-16(v-html="icons.information")
|
||||
b-popover(
|
||||
target="petLikeToEatStable"
|
||||
placement="top"
|
||||
)
|
||||
.popover-content-text(v-html="$t('petLikeToEatText')", v-once)
|
||||
drawer-slider(
|
||||
:items="drawerTabs[selectedDrawerTab].items",
|
||||
:scrollButtonsVisible="hasDrawerTabItems(selectedDrawerTab)",
|
||||
slot="drawer-slider",
|
||||
:itemWidth=94,
|
||||
:itemMargin=24,
|
||||
:itemType="selectedDrawerTab"
|
||||
.form-check(
|
||||
v-for="petGroup in petGroups",
|
||||
:key="petGroup.key"
|
||||
)
|
||||
template(slot="item", slot-scope="context")
|
||||
foodItem(
|
||||
:item="context.item",
|
||||
:itemCount="userItems.food[context.item.key]",
|
||||
:active="currentDraggingFood == context.item",
|
||||
@itemDragEnd="onDragEnd()",
|
||||
@itemDragStart="onDragStart($event, context.item)",
|
||||
@itemClick="onFoodClicked($event, context.item)"
|
||||
.custom-control.custom-checkbox
|
||||
input.custom-control-input(
|
||||
type="checkbox",
|
||||
v-model="viewOptions[petGroup.key].selected",
|
||||
:disabled="viewOptions[petGroup.key].animalCount == 0",
|
||||
:id="petGroup.key",
|
||||
)
|
||||
b-modal#welcome-modal(
|
||||
:ok-only="true",
|
||||
:ok-title="$t('gotIt')",
|
||||
:visible="!hideDialog",
|
||||
:hide-header="true",
|
||||
@hide="hideFlag()"
|
||||
)
|
||||
div.content
|
||||
div.npc_matt
|
||||
h1.page-header(v-once) {{ $t('welcomeStable') }}
|
||||
div.content-text(v-once) {{ $t('welcomeStableText') }}
|
||||
b-modal#hatching-modal(
|
||||
@change="resetHatchablePet($event)"
|
||||
)
|
||||
div.content(v-if="hatchablePet")
|
||||
div.potionEggGroup
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_HatchingPotion_'+hatchablePet.potionKey")
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_Egg_'+hatchablePet.eggKey")
|
||||
h4.title {{ hatchablePet.name }}
|
||||
div.text(v-html="$t('hatchDialogText', { potionName: hatchablePet.potionName, eggName: hatchablePet.eggName, petName: hatchablePet.name })")
|
||||
label.custom-control-label(v-once, :for="petGroup.key") {{ petGroup.label }}
|
||||
h3(v-once) {{ $t('mounts') }}
|
||||
.form-group
|
||||
.form-check(
|
||||
v-for="mountGroup in mountGroups",
|
||||
:key="mountGroup.key"
|
||||
)
|
||||
.custom-control.custom-checkbox
|
||||
input.custom-control-input(
|
||||
type="checkbox",
|
||||
v-model="viewOptions[mountGroup.key].selected",
|
||||
:disabled="viewOptions[mountGroup.key].animalCount == 0",
|
||||
:id="mountGroup.key",
|
||||
)
|
||||
label.custom-control-label(v-once, :for="mountGroup.key") {{ mountGroup.label }}
|
||||
|
||||
span.svg-icon.icon-10(v-html="icons.close", slot="modal-header", @click="closeHatchPetDialog()")
|
||||
div.form-group.clearfix
|
||||
h3.float-left {{ $t('hideMissing') }}
|
||||
toggle-switch.float-right(
|
||||
:checked="hideMissing",
|
||||
@change="updateHideMissing"
|
||||
)
|
||||
.standard-page
|
||||
.clearfix
|
||||
h1.float-left.mb-4.page-header(v-once) {{ $t('stable') }}
|
||||
|
||||
div(slot="modal-footer")
|
||||
button.btn.btn-primary(@click="hatchPet(hatchablePet)") {{ $t('hatch') }}
|
||||
button.btn.btn-secondary.btn-flat(@click="closeHatchPetDialog()") {{ $t('cancel') }}
|
||||
div.float-right
|
||||
span.dropdown-label {{ $t('sortBy') }}
|
||||
b-dropdown(:text="$t(selectedSortBy)", right=true)
|
||||
b-dropdown-item(
|
||||
v-for="sort in sortByItems",
|
||||
@click="selectedSortBy = sort",
|
||||
:active="selectedSortBy === sort",
|
||||
:key="sort"
|
||||
) {{ $t(sort) }}
|
||||
|
||||
hatchedPetDialog(
|
||||
:hideText="true",
|
||||
)
|
||||
h2.mb-3
|
||||
| {{ $t('pets') }}
|
||||
|
|
||||
span.badge.badge-pill.badge-default {{countOwnedAnimals(petGroups[0], 'pet')}}
|
||||
|
||||
div.foodInfo(ref="dragginFoodInfo")
|
||||
div(v-if="currentDraggingFood != null")
|
||||
div.food-icon(:class="'Pet_Food_'+currentDraggingFood.key")
|
||||
div.popover
|
||||
div.popover-content {{ $t('dragThisFood', {foodName: currentDraggingFood.text() }) }}
|
||||
div(v-for="(petGroup, index) in petGroups",
|
||||
v-if="viewOptions[petGroup.key].selected",
|
||||
:key="petGroup.key")
|
||||
h4(v-if="viewOptions[petGroup.key].animalCount !== 0") {{ petGroup.label }}
|
||||
|
||||
div.foodInfo.mouse(ref="clickFoodInfo", v-if="foodClickMode")
|
||||
div(v-if="currentDraggingFood != null")
|
||||
div.food-icon(:class="'Pet_Food_'+currentDraggingFood.key")
|
||||
div.popover
|
||||
div.popover-content {{ $t('clickOnPetToFeed', {foodName: currentDraggingFood.text() }) }}
|
||||
mount-raised-modal
|
||||
.pet-row.d-flex(
|
||||
v-for="(group, key, index) in pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)",
|
||||
v-if='index === 0 || $_openedItemRows_isToggled(petGroup.key)')
|
||||
.pet-group(
|
||||
v-for='item in group'
|
||||
v-drag.drop.food="item.key",
|
||||
@itemDragOver="onDragOver($event, item)",
|
||||
@itemDropped="onDrop($event, item)",
|
||||
@itemDragLeave="onDragLeave()",
|
||||
:class="{'last': item.isLastInRow}"
|
||||
)
|
||||
petItem(
|
||||
:item="item",
|
||||
:itemContentClass="getPetItemClass(item)",
|
||||
:popoverPosition="'top'",
|
||||
:progress="item.progress",
|
||||
:emptyItem="!item.isOwned()",
|
||||
:showPopover="currentDraggingFood == null",
|
||||
:highlightBorder="highlightPet == item.key",
|
||||
@click="petClicked(item)"
|
||||
)
|
||||
span(slot="popoverContent")
|
||||
div.hatchablePopover(v-if="item.isHatchable()")
|
||||
h4.popover-content-title {{ item.name }}
|
||||
div.popover-content-text(v-html="$t('haveHatchablePet', { potion: item.potionName, egg: item.eggName })")
|
||||
div.potionEggGroup
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_HatchingPotion_'+item.potionKey")
|
||||
div.potionEggBackground
|
||||
div(:class="'Pet_Egg_'+item.eggKey")
|
||||
div(v-else)
|
||||
h4.popover-content-title {{ item.name }}
|
||||
template(slot="itemBadge", slot-scope="context")
|
||||
starBadge(:selected="item.key === currentPet", :show="item.isOwned()", @click="selectPet(item)")
|
||||
|
||||
.btn.btn-flat.btn-show-more(@click="setShowMore(petGroup.key)", v-if='petGroup.key !== "specialPets"')
|
||||
| {{ $_openedItemRows_isToggled(petGroup.key) ? $t('showLess') : $t('showMore') }}
|
||||
|
||||
h2
|
||||
| {{ $t('mounts') }}
|
||||
|
|
||||
span.badge.badge-pill.badge-default {{countOwnedAnimals(mountGroups[0], 'mount')}}
|
||||
|
||||
div(v-for="mountGroup in mountGroups",
|
||||
v-if="viewOptions[mountGroup.key].selected",
|
||||
:key="mountGroup.key")
|
||||
h4(v-if="viewOptions[mountGroup.key].animalCount != 0") {{ mountGroup.label }}
|
||||
|
||||
.pet-row.d-flex(v-for="(group, key, index) in mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)"
|
||||
v-if='index === 0 || $_openedItemRows_isToggled(mountGroup.key)')
|
||||
.pet-group(v-for='item in group')
|
||||
mountItem(
|
||||
:item="item",
|
||||
:itemContentClass="item.isOwned() ? ('Mount_Icon_' + item.key) : 'PixelPaw GreyedOut'",
|
||||
:key="item.key",
|
||||
:popoverPosition="'top'",
|
||||
:emptyItem="!item.isOwned()",
|
||||
:showPopover="true",
|
||||
@click="selectMount(item)"
|
||||
)
|
||||
span(slot="popoverContent")
|
||||
h4.popover-content-title {{ item.name }}
|
||||
template(slot="itemBadge", slot-scope="context")
|
||||
starBadge(
|
||||
:selected="item.key === currentMount",
|
||||
:show="item.isOwned()",
|
||||
@click="selectMount(item)",
|
||||
)
|
||||
|
||||
.btn.btn-flat.btn-show-more(@click="setShowMore(mountGroup.key)", v-if='mountGroup.key !== "specialMounts"')
|
||||
| {{ $_openedItemRows_isToggled(mountGroup.key) ? $t('showLess') : $t('showMore') }}
|
||||
|
||||
drawer(:title="$t('quickInventory')",
|
||||
:errorMessage="(!hasDrawerTabItems(selectedDrawerTab)) ? ((selectedDrawerTab === 0) ? $t('noFoodAvailable') : $t('noSaddlesAvailable')) : null")
|
||||
div(slot="drawer-header")
|
||||
.drawer-tab-container
|
||||
.drawer-tab.text-right
|
||||
a.drawer-tab-text(
|
||||
@click="selectedDrawerTab = 0",
|
||||
:class="{'drawer-tab-text-active': selectedDrawerTab === 0}",
|
||||
) {{ drawerTabs[0].label }}
|
||||
.clearfix
|
||||
.drawer-tab.float-left
|
||||
a.drawer-tab-text(
|
||||
@click="selectedDrawerTab = 1",
|
||||
:class="{ 'drawer-tab-text-active': selectedDrawerTab === 1 }",
|
||||
) {{ drawerTabs[1].label }}
|
||||
|
||||
#petLikeToEatStable.drawer-help-text(v-once)
|
||||
| {{ $t('petLikeToEat') + ' ' }}
|
||||
span.svg-icon.inline.icon-16(v-html="icons.information")
|
||||
b-popover(
|
||||
target="petLikeToEatStable"
|
||||
placement="top"
|
||||
)
|
||||
.popover-content-text(v-html="$t('petLikeToEatText')", v-once)
|
||||
drawer-slider(
|
||||
:items="drawerTabs[selectedDrawerTab].items",
|
||||
:scrollButtonsVisible="hasDrawerTabItems(selectedDrawerTab)",
|
||||
slot="drawer-slider",
|
||||
:itemWidth=94,
|
||||
:itemMargin=24,
|
||||
:itemType="selectedDrawerTab"
|
||||
)
|
||||
template(slot="item", slot-scope="context")
|
||||
foodItem(
|
||||
:item="context.item",
|
||||
:itemCount="userItems.food[context.item.key]",
|
||||
:active="currentDraggingFood == context.item",
|
||||
@itemDragEnd="onDragEnd()",
|
||||
@itemDragStart="onDragStart($event, context.item)",
|
||||
@itemClick="onFoodClicked($event, context.item)"
|
||||
)
|
||||
hatchedPetDialog(:hideText="true")
|
||||
div.foodInfo(ref="dragginFoodInfo")
|
||||
div(v-if="currentDraggingFood != null")
|
||||
div.food-icon(:class="'Pet_Food_'+currentDraggingFood.key")
|
||||
div.popover
|
||||
div.popover-content {{ $t('dragThisFood', {foodName: currentDraggingFood.text() }) }}
|
||||
div.foodInfo.mouse(ref="clickFoodInfo", v-if="foodClickMode")
|
||||
div(v-if="currentDraggingFood != null")
|
||||
div.food-icon(:class="'Pet_Food_'+currentDraggingFood.key")
|
||||
div.popover
|
||||
div.popover-content {{ $t('clickOnPetToFeed', {foodName: currentDraggingFood.text() }) }}
|
||||
mount-raised-modal
|
||||
welcome-modal
|
||||
hatching-modal(:hatchablePet.sync='hatchablePet')
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
@@ -328,79 +288,6 @@
|
||||
height: 114px;
|
||||
}
|
||||
|
||||
#welcome-modal {
|
||||
@include centeredModal();
|
||||
|
||||
.npc_matt {
|
||||
margin: 0 auto 21px auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
|
||||
// the modal already has 15px padding
|
||||
margin-left: 33px;
|
||||
margin-right: 33px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.content-text {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 1.43;
|
||||
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
#hatching-modal {
|
||||
@include centeredModal();
|
||||
|
||||
.modal-dialog {
|
||||
width: 310px;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
margin: 9px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 24px;
|
||||
font-family: Roboto;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
font-stretch: condensed;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
color: #4e4a57;
|
||||
}
|
||||
|
||||
.text {
|
||||
height: 60px;
|
||||
font-family: Roboto;
|
||||
font-size: 14px;
|
||||
line-height: 1.43;
|
||||
text-align: center;
|
||||
color: #686274;
|
||||
}
|
||||
|
||||
span.svg-icon.icon-10 {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-backdrop.fade.show {
|
||||
background-color: $purple-50;
|
||||
opacity: 0.9;
|
||||
@@ -476,7 +363,7 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'client/libs/store';
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
import _each from 'lodash/each';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
@@ -492,6 +379,8 @@
|
||||
import FoodItem from './foodItem';
|
||||
import HatchedPetDialog from './hatchedPetDialog';
|
||||
import MountRaisedModal from './mountRaisedModal';
|
||||
import WelcomeModal from './welcomeModal';
|
||||
import HatchingModal from './hatchingModal';
|
||||
import Drawer from 'client/components/ui/drawer';
|
||||
import toggleSwitch from 'client/components/ui/toggleSwitch';
|
||||
import StarBadge from 'client/components/ui/starBadge';
|
||||
@@ -505,10 +394,10 @@
|
||||
import createAnimal from 'client/libs/createAnimal';
|
||||
|
||||
import svgInformation from 'assets/svg/information.svg';
|
||||
import svgClose from 'assets/svg/close.svg';
|
||||
|
||||
import notifications from 'client/mixins/notifications';
|
||||
import openedItemRowsMixin from 'client/mixins/openedItemRows';
|
||||
import petMixin from 'client/mixins/petMixin';
|
||||
|
||||
// TODO Normalize special pets and mounts
|
||||
// import Store from 'client/store';
|
||||
@@ -518,7 +407,7 @@
|
||||
let lastMouseMoveEvent = {};
|
||||
|
||||
export default {
|
||||
mixins: [notifications, openedItemRowsMixin],
|
||||
mixins: [notifications, openedItemRowsMixin, petMixin],
|
||||
components: {
|
||||
PetItem,
|
||||
Item,
|
||||
@@ -532,6 +421,8 @@
|
||||
DrawerSlider,
|
||||
HatchedPetDialog,
|
||||
MountRaisedModal,
|
||||
WelcomeModal,
|
||||
HatchingModal,
|
||||
},
|
||||
directives: {
|
||||
resize: ResizeDirective,
|
||||
@@ -554,7 +445,6 @@
|
||||
],
|
||||
icons: Object.freeze({
|
||||
information: svgInformation,
|
||||
close: svgClose,
|
||||
}),
|
||||
|
||||
highlightPet: '',
|
||||
@@ -578,7 +468,6 @@
|
||||
currentPet: 'user.data.items.currentPet',
|
||||
currentMount: 'user.data.items.currentMount',
|
||||
userItems: 'user.data.items',
|
||||
hideDialog: 'user.data.flags.tutorial.common.mounts',
|
||||
user: 'user.data',
|
||||
}),
|
||||
petGroups () {
|
||||
@@ -871,12 +760,6 @@
|
||||
selectMount (item) {
|
||||
this.$store.dispatch('common:equip', {key: item.key, type: 'mount'});
|
||||
},
|
||||
hatchPet (pet) {
|
||||
this.closeHatchPetDialog();
|
||||
|
||||
this.$store.dispatch('common:hatch', {egg: pet.eggKey, hatchingPotion: pet.potionKey});
|
||||
this.text(this.$t('hatchedPet', {egg: pet.eggName, potion: pet.potionName}));
|
||||
},
|
||||
onDragStart (ev, food) {
|
||||
this.currentDraggingFood = food;
|
||||
|
||||
@@ -952,14 +835,6 @@
|
||||
});
|
||||
}
|
||||
},
|
||||
closeHatchPetDialog () {
|
||||
this.$root.$emit('bv::hide::modal', 'hatching-modal');
|
||||
},
|
||||
resetHatchablePet ($event) {
|
||||
if (!$event) {
|
||||
this.hatchablePet = null;
|
||||
}
|
||||
},
|
||||
onFoodClicked ($event, food) {
|
||||
if (this.currentDraggingFood === null || this.currentDraggingFood !== food) {
|
||||
this.currentDraggingFood = food;
|
||||
@@ -981,11 +856,6 @@
|
||||
lastMouseMoveEvent = $event;
|
||||
}
|
||||
},
|
||||
hideFlag () {
|
||||
this.$store.dispatch('user:set', {
|
||||
'flags.tutorial.common.mounts': true,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||