mirror of
https://github.com/HabitRPG/habitica.git
synced 2026-05-12 11:39:44 -05:00
Compare commits
170 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70d59be39b | |||
| c562c93158 | |||
| 519da49886 | |||
| 79d50cb3e0 | |||
| c588c2b2ff | |||
| 77a490283c | |||
| e49d26eacd | |||
| 7b0fd57eb9 | |||
| 7171334e31 | |||
| a3235214b2 | |||
| fca234c45a | |||
| 7519023f06 | |||
| df84d7c7b1 | |||
| e837ebec49 | |||
| c7ed693e18 | |||
| e72a25ad02 | |||
| 2c12d5ee29 | |||
| c3f0abadd7 | |||
| adf0a2efca | |||
| e4523c09dc | |||
| 91d98b86e1 | |||
| 779fb8bce5 | |||
| f0fc83ed85 | |||
| 30d2108c78 | |||
| ab68e8a5fe | |||
| 31e9100ba2 | |||
| 0070f366bb | |||
| 2be6865a5c | |||
| db85768e9d | |||
| 3d40413882 | |||
| cc88e75950 | |||
| a5ae3e5877 | |||
| 60ed9d2944 | |||
| 91fc4235aa | |||
| 42e8dd1361 | |||
| 0a4bbbf173 | |||
| df22f5f7bf | |||
| bb28bb5969 | |||
| e4e8e0ff60 | |||
| e9a15fcb83 | |||
| a5602eec8d | |||
| 867eed176e | |||
| ba883ae104 | |||
| deba7b6220 | |||
| 69c538858b | |||
| 17072dcc45 | |||
| 2448f401f2 | |||
| 5745e3df5f | |||
| d4a5823916 | |||
| 86b15cb580 | |||
| 8e5b66a73e | |||
| f755d4c133 | |||
| 102c71c4ca | |||
| a7bde80349 | |||
| bedce203ee | |||
| 8ba7117fa5 | |||
| fe5d4a0551 | |||
| deebc09a79 | |||
| b63f2fa1fa | |||
| 60b180681e | |||
| 7c1c18a329 | |||
| 0b0cbb45f4 | |||
| 0e03f079a7 | |||
| a71e44b331 | |||
| 48917fd8be | |||
| 2a054a25ee | |||
| d176c31382 | |||
| 8150fef993 | |||
| f0637dcf49 | |||
| 0518b90eab | |||
| f968bdd3a9 | |||
| e3a1ea6180 | |||
| 17f6054ef0 | |||
| 9b8f213c63 | |||
| daccade2e2 | |||
| 48bb3e2886 | |||
| 308d557770 | |||
| 0f4816c674 | |||
| f1b98a530d | |||
| 1498eba8d4 | |||
| fc16ffbf2d | |||
| 021180fa59 | |||
| 102e6a64ad | |||
| 79a5c2ec5f | |||
| 8cd6e1654f | |||
| 63ea21c46d | |||
| 0a23dd5311 | |||
| 6e3a367832 | |||
| f3348aca4c | |||
| 90e1bc9d5e | |||
| 453bf3a961 | |||
| b026daec90 | |||
| 49f45d27e3 | |||
| 479cfb76ef | |||
| 0e0cd99ded | |||
| 7e210c56b0 | |||
| d92a03048b | |||
| 8183699cb7 | |||
| 9f9e6c4950 | |||
| c77dd5f200 | |||
| 06ac6ae80c | |||
| 13e87b1ea0 | |||
| 4a32a29bea | |||
| 71e165433a | |||
| c2515a4042 | |||
| e31bfdc22b | |||
| e9e4265545 | |||
| 9e0777bb42 | |||
| b159182188 | |||
| ca1b8370a0 | |||
| a397da2b93 | |||
| b5acc0e0d6 | |||
| 2635c5fcee | |||
| ee2936834a | |||
| c94a5304c7 | |||
| c6b004a474 | |||
| de918ec43b | |||
| 069e994b25 | |||
| 663692f2d5 | |||
| 0ba4761083 | |||
| afad3815a2 | |||
| 0c85835dc2 | |||
| 54df8397a7 | |||
| 0644032a4f | |||
| 44265ac616 | |||
| ac3b953633 | |||
| 5de2921d22 | |||
| c1a0f8a8d1 | |||
| 7e9506391f | |||
| 3c7ca56089 | |||
| 0d155535c3 | |||
| 09a0d2b3b8 | |||
| 83dcf8d56a | |||
| bfc13bc21b | |||
| 5afb46f237 | |||
| 9cc4fc19d3 | |||
| cc81629f09 | |||
| e83db7a28a | |||
| 80e193e4ce | |||
| 76fa6ec1b8 | |||
| 1ac4466c24 | |||
| 03f0061c85 | |||
| c349de6908 | |||
| fd7f3a646e | |||
| 7244c1bebc | |||
| 20df5eeb8f | |||
| 23f7dd94b6 | |||
| 7125da4533 | |||
| 684cb59a7c | |||
| 9274fe9a10 | |||
| a21f083761 | |||
| c7e2834fc6 | |||
| a08c26b076 | |||
| f4aa88e1ff | |||
| 53eab7aa29 | |||
| 8374d61f52 | |||
| 4c943b7575 | |||
| 24032b57f6 | |||
| 8628c774e5 | |||
| 523f044914 | |||
| 892c9ad040 | |||
| 570f39c620 | |||
| a73316ef9f | |||
| 6d6195ae6a | |||
| 4ba66c7018 | |||
| 54b9424c6e | |||
| af574634b0 | |||
| d1e1c09b4a | |||
| 4f5a720c30 | |||
| 4ddfdb84ac |
+1
-1
Submodule habitica-images updated: 311cb01059...9982925604
@@ -0,0 +1,158 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20230522_pet_group_achievements';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {
|
||||
migration: MIGRATION_NAME,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.pets) {
|
||||
const pets = user.items.pets;
|
||||
if (pets['Parrot-Base']
|
||||
&& pets['Parrot-CottonCandyBlue']
|
||||
&& pets['Parrot-CottonCandyPink']
|
||||
&& pets['Parrot-Desert']
|
||||
&& pets['Parrot-Golden']
|
||||
&& pets['Parrot-Red']
|
||||
&& pets['Parrot-Shade']
|
||||
&& pets['Parrot-Skeleton']
|
||||
&& pets['Parrot-White']
|
||||
&& pets['Parrot-Zombie']
|
||||
&& pets['Rooster-Base']
|
||||
&& pets['Rooster-CottonCandyBlue']
|
||||
&& pets['Rooster-CottonCandyPink']
|
||||
&& pets['Rooster-Desert']
|
||||
&& pets['Rooster-Golden']
|
||||
&& pets['Rooster-Red']
|
||||
&& pets['Rooster-Shade']
|
||||
&& pets['Rooster-Skeleton']
|
||||
&& pets['Rooster-White']
|
||||
&& pets['Rooster-Zombie']
|
||||
&& pets['Triceratops-Base']
|
||||
&& pets['Triceratops-CottonCandyBlue']
|
||||
&& pets['Triceratops-CottonCandyPink']
|
||||
&& pets['Triceratops-Desert']
|
||||
&& pets['Triceratops-Golden']
|
||||
&& pets['Triceratops-Red']
|
||||
&& pets['Triceratops-Shade']
|
||||
&& pets['Triceratops-Skeleton']
|
||||
&& pets['Triceratops-White']
|
||||
&& pets['Triceratops-Zombie']
|
||||
&& pets['TRex-Base']
|
||||
&& pets['TRex-CottonCandyBlue']
|
||||
&& pets['TRex-CottonCandyPink']
|
||||
&& pets['TRex-Desert']
|
||||
&& pets['TRex-Golden']
|
||||
&& pets['TRex-Red']
|
||||
&& pets['TRex-Shade']
|
||||
&& pets['TRex-Skeleton']
|
||||
&& pets['TRex-White']
|
||||
&& pets['TRex-Zombie']
|
||||
&& pets['Pterodactyl-Base']
|
||||
&& pets['Pterodactyl-CottonCandyBlue']
|
||||
&& pets['Pterodactyl-CottonCandyPink']
|
||||
&& pets['Pterodactyl-Desert']
|
||||
&& pets['Pterodactyl-Golden']
|
||||
&& pets['Pterodactyl-Red']
|
||||
&& pets['Pterodactyl-Shade']
|
||||
&& pets['Pterodactyl-Skeleton']
|
||||
&& pets['Pterodactyl-White']
|
||||
&& pets['Pterodactyl-Zombie']
|
||||
&& pets['Owl-Base']
|
||||
&& pets['Owl-CottonCandyBlue']
|
||||
&& pets['Owl-CottonCandyPink']
|
||||
&& pets['Owl-Desert']
|
||||
&& pets['Owl-Golden']
|
||||
&& pets['Owl-Red']
|
||||
&& pets['Owl-Shade']
|
||||
&& pets['Owl-Skeleton']
|
||||
&& pets['Owl-White']
|
||||
&& pets['Owl-Zombie']
|
||||
&& pets['Velociraptor-Base']
|
||||
&& pets['Velociraptor-CottonCandyBlue']
|
||||
&& pets['Velociraptor-CottonCandyPink']
|
||||
&& pets['Velociraptor-Desert']
|
||||
&& pets['Velociraptor-Golden']
|
||||
&& pets['Velociraptor-Red']
|
||||
&& pets['Velociraptor-Shade']
|
||||
&& pets['Velociraptor-Skeleton']
|
||||
&& pets['Velociraptor-White']
|
||||
&& pets['Velociraptor-Zombie']
|
||||
&& pets['Penguin-Base']
|
||||
&& pets['Penguin-CottonCandyBlue']
|
||||
&& pets['Penguin-CottonCandyPink']
|
||||
&& pets['Penguin-Desert']
|
||||
&& pets['Penguin-Golden']
|
||||
&& pets['Penguin-Red']
|
||||
&& pets['Penguin-Shade']
|
||||
&& pets['Penguin-Skeleton']
|
||||
&& pets['Penguin-White']
|
||||
&& pets['Penguin-Zombie']
|
||||
&& pets['Falcon-Base']
|
||||
&& pets['Falcon-CottonCandyBlue']
|
||||
&& pets['Falcon-CottonCandyPink']
|
||||
&& pets['Falcon-Desert']
|
||||
&& pets['Falcon-Golden']
|
||||
&& pets['Falcon-Red']
|
||||
&& pets['Falcon-Shade']
|
||||
&& pets['Falcon-Skeleton']
|
||||
&& pets['Falcon-White']
|
||||
&& pets['Falcon-Zombie']
|
||||
&& pets['Peacock-Base']
|
||||
&& pets['Peacock-CottonCandyBlue']
|
||||
&& pets['Peacock-CottonCandyPink']
|
||||
&& pets['Peacock-Desert']
|
||||
&& pets['Peacock-Golden']
|
||||
&& pets['Peacock-Red']
|
||||
&& pets['Peacock-Shade']
|
||||
&& pets['Peacock-Skeleton']
|
||||
&& pets['Peacock-White']
|
||||
&& pets['Peacock-Zombie']) {
|
||||
set['achievements.dinosaurDynasty'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
let query = {
|
||||
// migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2023-04-15') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
Generated
+1794
-1263
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "4.268.1",
|
||||
"version": "4.276.0",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.12",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/register": "^7.18.9",
|
||||
"@babel/core": "^7.22.5",
|
||||
"@babel/preset-env": "^7.22.5",
|
||||
"@babel/register": "^7.22.5",
|
||||
"@google-cloud/trace-agent": "^7.1.2",
|
||||
"@parse/node-apn": "^5.1.3",
|
||||
"@slack/webhook": "^6.1.0",
|
||||
@@ -14,9 +14,9 @@
|
||||
"amazon-payments": "^0.2.9",
|
||||
"amplitude": "^6.0.0",
|
||||
"apidoc": "^0.54.0",
|
||||
"apple-auth": "^1.0.7",
|
||||
"apple-auth": "^1.0.9",
|
||||
"bcrypt": "^5.1.0",
|
||||
"body-parser": "^1.20.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"bootstrap": "^4.6.0",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-session": "^2.0.0",
|
||||
@@ -42,7 +42,7 @@
|
||||
"image-size": "^1.0.2",
|
||||
"in-app-purchase": "^1.11.3",
|
||||
"js2xmlparser": "^5.0.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"jwks-rsa": "^2.1.5",
|
||||
"lodash": "^4.17.21",
|
||||
"merge-stream": "^2.0.0",
|
||||
@@ -67,16 +67,16 @@
|
||||
"remove-markdown": "^0.5.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"short-uuid": "^4.2.2",
|
||||
"stripe": "^11.10.0",
|
||||
"superagent": "^8.0.6",
|
||||
"stripe": "^12.9.0",
|
||||
"superagent": "^8.0.9",
|
||||
"universal-analytics": "^0.5.3",
|
||||
"useragent": "^2.1.9",
|
||||
"uuid": "^9.0.0",
|
||||
"validator": "^13.9.0",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"winston": "^3.8.2",
|
||||
"winston": "^3.9.0",
|
||||
"winston-loggly-bulk": "^3.2.1",
|
||||
"xml2js": "^0.4.23"
|
||||
"xml2js": "^0.6.0"
|
||||
},
|
||||
"private": true,
|
||||
"engines": {
|
||||
@@ -110,7 +110,7 @@
|
||||
"apidoc": "gulp apidoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^1.2.2",
|
||||
"axios": "^1.3.6",
|
||||
"chai": "^4.3.7",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-moment": "^0.1.0",
|
||||
@@ -122,7 +122,7 @@
|
||||
"monk": "^7.3.4",
|
||||
"require-again": "^2.0.0",
|
||||
"run-rs": "^0.7.7",
|
||||
"sinon": "^15.0.1",
|
||||
"sinon": "^15.1.2",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"sinon-stub-promise": "^4.0.0"
|
||||
},
|
||||
|
||||
@@ -748,9 +748,19 @@ describe('payments/index', () => {
|
||||
});
|
||||
|
||||
it('does not add to plans.consecutive.offset if 1 month subscription', async () => {
|
||||
data.sub.key = 'basic_earned';
|
||||
await api.createSubscription(data);
|
||||
|
||||
expect(user.purchased.plan.extraMonths).to.eql(0);
|
||||
expect(user.purchased.plan.consecutive.offset).to.eql(0);
|
||||
});
|
||||
|
||||
it('resets plans.consecutive.offset if 1 month subscription', async () => {
|
||||
user.purchased.plan.consecutive.offset = 1;
|
||||
await user.save();
|
||||
data.sub.key = 'basic_earned';
|
||||
await api.createSubscription(data);
|
||||
|
||||
expect(user.purchased.plan.consecutive.offset).to.eql(0);
|
||||
});
|
||||
|
||||
it('adds 5 to plan.consecutive.gemCapExtra for 3 month block', async () => {
|
||||
|
||||
@@ -242,7 +242,7 @@ describe('cron middleware', () => {
|
||||
|
||||
sandbox.spy(cronLib, 'recoverCron');
|
||||
|
||||
sandbox.stub(User, 'update')
|
||||
sandbox.stub(User, 'updateOne')
|
||||
.withArgs({
|
||||
_id: user._id,
|
||||
$or: [
|
||||
|
||||
@@ -1732,7 +1732,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('updates participting members (not including user)', async () => {
|
||||
sandbox.spy(User, 'update');
|
||||
sandbox.spy(User, 'updateMany');
|
||||
|
||||
await party.startQuest(nonParticipatingMember);
|
||||
|
||||
@@ -1740,7 +1740,7 @@ describe('Group Model', () => {
|
||||
questLeader._id, participatingMember._id, sleepingParticipatingMember._id,
|
||||
];
|
||||
|
||||
expect(User.update).to.be.calledWith(
|
||||
expect(User.updateMany).to.be.calledWith(
|
||||
{ _id: { $in: members } },
|
||||
{
|
||||
$set: {
|
||||
@@ -1753,11 +1753,11 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('updates non-user quest leader and decrements quest scroll', async () => {
|
||||
sandbox.spy(User, 'update');
|
||||
sandbox.spy(User, 'updateOne');
|
||||
|
||||
await party.startQuest(participatingMember);
|
||||
|
||||
expect(User.update).to.be.calledWith(
|
||||
expect(User.updateOne).to.be.calledWith(
|
||||
{ _id: questLeader._id },
|
||||
{
|
||||
$inc: {
|
||||
@@ -1819,29 +1819,29 @@ describe('Group Model', () => {
|
||||
};
|
||||
|
||||
it('doesn\'t retry successful operations', async () => {
|
||||
sandbox.stub(User, 'update').returns(successfulMock);
|
||||
sandbox.stub(User, 'updateOne').returns(successfulMock);
|
||||
|
||||
await party.finishQuest(quest);
|
||||
|
||||
expect(User.update).to.be.calledThrice;
|
||||
expect(User.updateOne).to.be.calledThrice;
|
||||
});
|
||||
|
||||
it('stops retrying when a successful update has occurred', async () => {
|
||||
const updateStub = sandbox.stub(User, 'update');
|
||||
const updateStub = sandbox.stub(User, 'updateOne');
|
||||
updateStub.onCall(0).returns(failedMock);
|
||||
updateStub.returns(successfulMock);
|
||||
|
||||
await party.finishQuest(quest);
|
||||
|
||||
expect(User.update.callCount).to.equal(4);
|
||||
expect(User.updateOne.callCount).to.equal(4);
|
||||
});
|
||||
|
||||
it('retries failed updates at most five times per user', async () => {
|
||||
sandbox.stub(User, 'update').returns(failedMock);
|
||||
sandbox.stub(User, 'updateOne').returns(failedMock);
|
||||
|
||||
await expect(party.finishQuest(quest)).to.eventually.be.rejected;
|
||||
|
||||
expect(User.update.callCount).to.eql(15); // for 3 users
|
||||
expect(User.updateOne.callCount).to.eql(15); // for 3 users
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2088,17 +2088,17 @@ describe('Group Model', () => {
|
||||
|
||||
context('Party quests', () => {
|
||||
it('updates participating members with rewards', async () => {
|
||||
sandbox.spy(User, 'update');
|
||||
sandbox.spy(User, 'updateOne');
|
||||
await party.finishQuest(quest);
|
||||
|
||||
expect(User.update).to.be.calledThrice;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
expect(User.updateOne).to.be.calledThrice;
|
||||
expect(User.updateOne).to.be.calledWithMatch({
|
||||
_id: questLeader._id,
|
||||
});
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
expect(User.updateOne).to.be.calledWithMatch({
|
||||
_id: participatingMember._id,
|
||||
});
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
expect(User.updateOne).to.be.calledWithMatch({
|
||||
_id: sleepingParticipatingMember._id,
|
||||
});
|
||||
});
|
||||
@@ -2173,11 +2173,11 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('updates all users with rewards', async () => {
|
||||
sandbox.spy(User, 'update');
|
||||
sandbox.spy(User, 'updateMany');
|
||||
await party.finishQuest(tavernQuest);
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({});
|
||||
expect(User.updateMany).to.be.calledOnce;
|
||||
expect(User.updateMany).to.be.calledWithMatch({});
|
||||
});
|
||||
|
||||
it('sets quest completed to the world quest key', async () => {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { v4 as generateUUID } from 'uuid';
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
checkExistence,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
|
||||
@@ -258,47 +257,6 @@ describe('POST /group/:groupId/join', () => {
|
||||
await expect(user.get('/user')).to.eventually.have.nested.property('items.quests.basilist', 2);
|
||||
});
|
||||
|
||||
it('deletes previous party where the user was the only member', async () => {
|
||||
const userToInvite = await generateUser();
|
||||
const oldParty = await userToInvite.post('/groups', { // add user to a party
|
||||
name: 'Another Test Party',
|
||||
type: 'party',
|
||||
});
|
||||
|
||||
await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(true);
|
||||
await user.post(`/groups/${party._id}/invite`, {
|
||||
uuids: [userToInvite._id],
|
||||
});
|
||||
await userToInvite.post(`/groups/${party._id}/join`);
|
||||
|
||||
await expect(user.get('/user')).to.eventually.have.nested.property('party._id', party._id);
|
||||
await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(false);
|
||||
});
|
||||
|
||||
it('does not allow user to leave a party if a quest was active and they were the only member', async () => {
|
||||
const userToInvite = await generateUser();
|
||||
const oldParty = await userToInvite.post('/groups', { // add user to a party
|
||||
name: 'Another Test Party',
|
||||
type: 'party',
|
||||
});
|
||||
|
||||
await userToInvite.update({
|
||||
[`items.quests.${PET_QUEST}`]: 1,
|
||||
});
|
||||
await userToInvite.post(`/groups/${oldParty._id}/quests/invite/${PET_QUEST}`);
|
||||
|
||||
await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(true);
|
||||
await user.post(`/groups/${party._id}/invite`, {
|
||||
uuids: [userToInvite._id],
|
||||
});
|
||||
|
||||
await expect(userToInvite.post(`/groups/${party._id}/join`)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('messageCannotLeaveWhileQuesting'),
|
||||
});
|
||||
});
|
||||
|
||||
it('invites joining member to active quest', async () => {
|
||||
await user.update({
|
||||
[`items.quests.${PET_QUEST}`]: 1,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
import nconf from 'nconf';
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
generateUser,
|
||||
generateGroup,
|
||||
translate as t,
|
||||
@@ -581,20 +582,7 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('allow inviting a user to a party if they are partying solo', async () => {
|
||||
const userToInvite = await generateUser();
|
||||
await userToInvite.post('/groups', { // add user to a party
|
||||
name: 'Another Test Party',
|
||||
type: 'party',
|
||||
});
|
||||
|
||||
await inviter.post(`/groups/${party._id}/invite`, {
|
||||
uuids: [userToInvite._id],
|
||||
});
|
||||
expect((await userToInvite.get('/user')).invitations.parties[0].id).to.equal(party._id);
|
||||
});
|
||||
|
||||
it('allow inviting a user to 2 different parties', async () => {
|
||||
it('allows inviting a user to 2 different parties', async () => {
|
||||
// Create another inviter
|
||||
const inviter2 = await generateUser();
|
||||
|
||||
@@ -635,29 +623,48 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
});
|
||||
expect((await userToInvite.get('/user')).invitations.parties[0].id).to.equal(party._id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('party size limits', () => {
|
||||
let party;
|
||||
let partyLeader;
|
||||
|
||||
beforeEach(async () => {
|
||||
group = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Party',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
// Generate party with 20 members
|
||||
members: PARTY_LIMIT_MEMBERS - 10,
|
||||
});
|
||||
party = group.group;
|
||||
partyLeader = group.groupLeader;
|
||||
});
|
||||
|
||||
it('allows 30 members in a party', async () => {
|
||||
const invitesToGenerate = [];
|
||||
// Generate 29 users to invite (29 + leader = 30 members)
|
||||
for (let i = 0; i < PARTY_LIMIT_MEMBERS - 1; i += 1) {
|
||||
// Generate 10 new invites
|
||||
for (let i = 1; i < 10; i += 1) {
|
||||
invitesToGenerate.push(generateUser());
|
||||
}
|
||||
const generatedInvites = await Promise.all(invitesToGenerate);
|
||||
// Invite users
|
||||
expect(await inviter.post(`/groups/${party._id}/invite`, {
|
||||
expect(await partyLeader.post(`/groups/${party._id}/invite`, {
|
||||
uuids: generatedInvites.map(invite => invite._id),
|
||||
})).to.be.an('array');
|
||||
}).timeout(10000);
|
||||
|
||||
it('does not allow 30+ members in a party', async () => {
|
||||
it('does not allow >30 members in a party', async () => {
|
||||
const invitesToGenerate = [];
|
||||
// Generate 30 users to invite (30 + leader = 31 members)
|
||||
for (let i = 0; i < PARTY_LIMIT_MEMBERS; i += 1) {
|
||||
// Generate 11 invites
|
||||
for (let i = 1; i < 11; i += 1) {
|
||||
invitesToGenerate.push(generateUser());
|
||||
}
|
||||
const generatedInvites = await Promise.all(invitesToGenerate);
|
||||
// Invite users
|
||||
await expect(inviter.post(`/groups/${party._id}/invite`, {
|
||||
await expect(partyLeader.post(`/groups/${party._id}/invite`, {
|
||||
uuids: generatedInvites.map(invite => invite._id),
|
||||
}))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
|
||||
@@ -202,18 +202,86 @@ describe('POST /user/class/cast/:spellId', () => {
|
||||
await group.groupLeader.post('/user/class/cast/mpheal');
|
||||
|
||||
promises = [];
|
||||
promises.push(group.groupLeader.sync());
|
||||
promises.push(group.members[0].sync());
|
||||
promises.push(group.members[1].sync());
|
||||
promises.push(group.members[2].sync());
|
||||
promises.push(group.members[3].sync());
|
||||
await Promise.all(promises);
|
||||
|
||||
expect(group.groupLeader.stats.mp).to.be.equal(170); // spell caster
|
||||
expect(group.members[0].stats.mp).to.be.greaterThan(0); // warrior
|
||||
expect(group.members[1].stats.mp).to.equal(0); // wizard
|
||||
expect(group.members[2].stats.mp).to.be.greaterThan(0); // rogue
|
||||
expect(group.members[3].stats.mp).to.be.greaterThan(0); // healer
|
||||
});
|
||||
|
||||
const spellList = [
|
||||
{
|
||||
className: 'warrior',
|
||||
spells: [['smash', 'task'], ['defensiveStance'], ['valorousPresence'], ['intimidate']],
|
||||
},
|
||||
{
|
||||
className: 'wizard',
|
||||
spells: [['fireball', 'task'], ['mpheal'], ['earth'], ['frost']],
|
||||
},
|
||||
{
|
||||
className: 'healer',
|
||||
spells: [['heal'], ['brightness'], ['protectAura'], ['healAll']],
|
||||
},
|
||||
{
|
||||
className: 'rogue',
|
||||
spells: [['pickPocket', 'task'], ['backStab', 'task'], ['toolsOfTrade'], ['stealth']],
|
||||
},
|
||||
];
|
||||
|
||||
spellList.forEach(async habitClass => {
|
||||
describe(`For a ${habitClass.className}`, async () => {
|
||||
habitClass.spells.forEach(async spell => {
|
||||
describe(`Using ${spell[0]}`, async () => {
|
||||
it('Deducts MP from spell caster', async () => {
|
||||
const { groupLeader } = await createAndPopulateGroup({
|
||||
groupDetails: { type: 'party', privacy: 'private' },
|
||||
members: 3,
|
||||
});
|
||||
await groupLeader.update({
|
||||
'stats.mp': 200, 'stats.class': habitClass.className, 'stats.lvl': 20, 'stats.hp': 40,
|
||||
});
|
||||
// need this for task spells and for stealth
|
||||
const task = await groupLeader.post('/tasks/user', {
|
||||
text: 'test habit',
|
||||
type: 'daily',
|
||||
});
|
||||
if (spell.length === 2 && spell[1] === 'task') {
|
||||
await groupLeader.post(`/user/class/cast/${spell[0]}?targetId=${task._id}`);
|
||||
} else {
|
||||
await groupLeader.post(`/user/class/cast/${spell[0]}`);
|
||||
}
|
||||
await groupLeader.sync();
|
||||
expect(groupLeader.stats.mp).to.be.lessThan(200);
|
||||
});
|
||||
it('works without a party', async () => {
|
||||
await user.update({
|
||||
'stats.mp': 200, 'stats.class': habitClass.className, 'stats.lvl': 20, 'stats.hp': 40,
|
||||
});
|
||||
// need this for task spells and for stealth
|
||||
const task = await user.post('/tasks/user', {
|
||||
text: 'test habit',
|
||||
type: 'daily',
|
||||
});
|
||||
if (spell.length === 2 && spell[1] === 'task') {
|
||||
await user.post(`/user/class/cast/${spell[0]}?targetId=${task._id}`);
|
||||
} else {
|
||||
await user.post(`/user/class/cast/${spell[0]}`);
|
||||
}
|
||||
await user.sync();
|
||||
expect(user.stats.mp).to.be.lessThan(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('cast bulk', async () => {
|
||||
let { group, groupLeader } = await createAndPopulateGroup({ // eslint-disable-line prefer-const
|
||||
groupDetails: { type: 'party', privacy: 'private' },
|
||||
|
||||
Generated
+53
-52
@@ -1842,9 +1842,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-optional-chaining": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz",
|
||||
"integrity": "sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==",
|
||||
"version": "7.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz",
|
||||
"integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==",
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.20.2",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.20.0",
|
||||
@@ -1870,9 +1870,9 @@
|
||||
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
|
||||
"integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
|
||||
"version": "7.21.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz",
|
||||
"integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==",
|
||||
"requires": {
|
||||
"@babel/helper-string-parser": "^7.19.4",
|
||||
"@babel/helper-validator-identifier": "^7.19.1",
|
||||
@@ -13321,14 +13321,12 @@
|
||||
"emojis-list": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
|
||||
"optional": true
|
||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"optional": true
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
@@ -13339,7 +13337,6 @@
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
@@ -13381,7 +13378,6 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
@@ -13390,7 +13386,6 @@
|
||||
"version": "npm:vue-loader@16.8.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
|
||||
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
@@ -13401,7 +13396,6 @@
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
@@ -16907,9 +16901,9 @@
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.27.2",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.27.2.tgz",
|
||||
"integrity": "sha512-9ashVQskuh5AZEZ1JdQWp1GqSoC1e1G87MzRqg2gIfVAQ7Qn9K+uFj8EcniUFA4P2NLZfV+TOlX1SzoKfo+s7w=="
|
||||
"version": "3.31.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.0.tgz",
|
||||
"integrity": "sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.11.0",
|
||||
@@ -17958,9 +17952,9 @@
|
||||
}
|
||||
},
|
||||
"dompurify": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
|
||||
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
|
||||
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
|
||||
},
|
||||
"domutils": {
|
||||
"version": "1.7.0",
|
||||
@@ -21077,6 +21071,11 @@
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||
},
|
||||
"immutable": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
||||
"integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg=="
|
||||
},
|
||||
"import-cwd": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
||||
@@ -21437,9 +21436,9 @@
|
||||
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="
|
||||
},
|
||||
"intro.js": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/intro.js/-/intro.js-6.0.0.tgz",
|
||||
"integrity": "sha512-ZUiR6BoLSvPSlLG0boewnWVgji1fE1gBvP/pyw5pgCKXEDQz1mMeUxarggClPNs71UTq364LwSk9zxz17A9gaQ=="
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/intro.js/-/intro.js-7.0.1.tgz",
|
||||
"integrity": "sha512-1oqz6aOz9cGQ3CrtVYhCSo6AkjnXUn302kcIWLaZ3TI4kKssRXDwDSz4VRoGcfC1jN+WfaSJXRBrITz+QVEBzg=="
|
||||
},
|
||||
"invariant": {
|
||||
"version": "2.2.4",
|
||||
@@ -22019,9 +22018,9 @@
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.3.tgz",
|
||||
"integrity": "sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg=="
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz",
|
||||
"integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ=="
|
||||
},
|
||||
"js-message": {
|
||||
"version": "1.0.5",
|
||||
@@ -27367,17 +27366,19 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.34.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.34.0.tgz",
|
||||
"integrity": "sha512-rHEN0BscqjUYuomUEaqq3BMgsXqQfkcMVR7UhscsAVub0/spUrZGBMxQXFS2kfiDsPLZw5yuU9iJEFNC2x38Qw==",
|
||||
"version": "1.63.4",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.63.4.tgz",
|
||||
"integrity": "sha512-Sx/+weUmK+oiIlI+9sdD0wZHsqpbgQg8wSwSnGBjwb5GwqFhYNwwnI+UWZtLjKvKyFlKkatRK235qQ3mokyPoQ==",
|
||||
"requires": {
|
||||
"chokidar": ">=3.0.0 <4.0.0"
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
@@ -27397,18 +27398,18 @@
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
|
||||
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"requires": {
|
||||
"anymatch": "~3.1.1",
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.1",
|
||||
"glob-parent": "~5.1.0",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.5.0"
|
||||
"readdirp": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
@@ -27447,9 +27448,9 @@
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
|
||||
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"requires": {
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
@@ -27801,9 +27802,9 @@
|
||||
}
|
||||
},
|
||||
"smartbanner.js": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/smartbanner.js/-/smartbanner.js-1.19.1.tgz",
|
||||
"integrity": "sha512-x3alFTlk6pLuqrm9PrYQv1E+86CrEIgPf/KJ+nP5342BmOWstbdR8OwD3TPmM56zHQm4MEr/eoqbEcfTKdvdKw=="
|
||||
"version": "1.19.2",
|
||||
"resolved": "https://registry.npmjs.org/smartbanner.js/-/smartbanner.js-1.19.2.tgz",
|
||||
"integrity": "sha512-hwcGNp5Hza5PJHTmqP6H8q0XBYhloIQyJgdzv0ldz3HQSeEuKB2riVraQXdKuquE6ZU/0M0yubno53xJ/ZiQQg=="
|
||||
},
|
||||
"snapdragon": {
|
||||
"version": "0.8.2",
|
||||
@@ -28175,9 +28176,9 @@
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"stopword": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/stopword/-/stopword-2.0.7.tgz",
|
||||
"integrity": "sha512-s+uLKAxrproCLrq0Wcd3JAIjlJLx6l80b2Rzt0u8+ra5SzGkHnNG8PS3DfGmYk2TrKePDVLL4SdKYwKpgSLc+w=="
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/stopword/-/stopword-2.0.8.tgz",
|
||||
"integrity": "sha512-btlEC2vEuhCuvshz99hSGsY8GzaP5qzDPQm56j6rR/R38p8xdsOXgU5a6tIgvU/4hcCta1Vlo/2FVXA9m0f8XA=="
|
||||
},
|
||||
"store2": {
|
||||
"version": "2.10.0",
|
||||
@@ -30271,9 +30272,9 @@
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
|
||||
},
|
||||
"uuid-browser": {
|
||||
"version": "3.1.0",
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap-vue": "^2.23.1",
|
||||
"chai": "^4.3.7",
|
||||
"core-js": "^3.27.2",
|
||||
"dompurify": "^2.4.3",
|
||||
"core-js": "^3.31.0",
|
||||
"dompurify": "^3.0.3",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-habitrpg": "^6.2.0",
|
||||
"eslint-plugin-mocha": "^5.3.0",
|
||||
@@ -41,20 +41,20 @@
|
||||
"habitica-markdown": "^3.0.0",
|
||||
"hellojs": "^1.20.0",
|
||||
"inspectpack": "^4.7.1",
|
||||
"intro.js": "^6.0.0",
|
||||
"jquery": "^3.6.3",
|
||||
"intro.js": "^7.0.1",
|
||||
"jquery": "^3.7.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.4",
|
||||
"nconf": "^0.12.0",
|
||||
"sass": "^1.34.0",
|
||||
"sass": "^1.63.4",
|
||||
"sass-loader": "^8.0.2",
|
||||
"smartbanner.js": "^1.19.1",
|
||||
"stopword": "^2.0.7",
|
||||
"smartbanner.js": "^1.19.2",
|
||||
"stopword": "^2.0.8",
|
||||
"svg-inline-loader": "^0.8.2",
|
||||
"svg-url-loader": "^7.1.1",
|
||||
"svgo": "^1.3.2",
|
||||
"svgo-loader": "^2.2.1",
|
||||
"uuid": "^8.3.2",
|
||||
"uuid": "^9.0.0",
|
||||
"validator": "^13.9.0",
|
||||
"vue": "^2.7.10",
|
||||
"vue-cli-plugin-storybook": "2.1.0",
|
||||
@@ -66,6 +66,6 @@
|
||||
"webpack": "^4.46.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.20.7"
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,11 @@
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
.achievement-dinosaurDynasty2x {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/achievement-dinosaurDynasty2x.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.achievement-domesticated2x {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/achievement-domesticated2x.png');
|
||||
width: 60px;
|
||||
@@ -705,6 +710,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_boardwalk_into_sunset {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_boardwalk_into_sunset.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_branches_of_a_holiday_tree {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_branches_of_a_holiday_tree.png');
|
||||
width: 141px;
|
||||
@@ -780,6 +790,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_colorful_coral {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_colorful_coral.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_coral_reef {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_coral_reef.png');
|
||||
width: 141px;
|
||||
@@ -810,6 +825,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_crater_lake {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_crater_lake.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_creepy_castle {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_creepy_castle.png');
|
||||
width: 141px;
|
||||
@@ -820,6 +840,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_cretaceous_forest {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_cretaceous_forest.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_crosscountry_ski_trail {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_crosscountry_ski_trail.png');
|
||||
width: 141px;
|
||||
@@ -1054,6 +1079,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_hedge_maze {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_flying_over_hedge_maze.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_flying_over_icy_steppes {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_flying_over_icy_steppes.png');
|
||||
width: 141px;
|
||||
@@ -1329,11 +1359,21 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_in_a_painting {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_a_painting.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_in_an_ancient_tomb {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_an_ancient_tomb.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_in_an_aquarium {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_an_aquarium.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_in_front_of_fountain {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_in_front_of_fountain.png');
|
||||
width: 141px;
|
||||
@@ -1354,6 +1394,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_inside_adventurers_hideout {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_inside_adventurers_hideout.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_inside_an_ornament {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_inside_an_ornament.png');
|
||||
width: 141px;
|
||||
@@ -1544,6 +1589,11 @@
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_on_a_paddlewheel_boat {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_on_a_paddlewheel_boat.png');
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
}
|
||||
.background_on_tree_branch {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/background_on_tree_branch.png');
|
||||
width: 141px;
|
||||
@@ -2386,6 +2436,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_boardwalk_into_sunset {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_boardwalk_into_sunset.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_branches_of_a_holiday_tree {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_branches_of_a_holiday_tree.png');
|
||||
width: 68px;
|
||||
@@ -2466,6 +2521,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_colorful_coral {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_colorful_coral.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_coral_reef {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_coral_reef.png');
|
||||
width: 68px;
|
||||
@@ -2496,6 +2556,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_crater_lake {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_crater_lake.png');
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.icon_background_creepy_castle {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_creepy_castle.png');
|
||||
width: 60px;
|
||||
@@ -2506,6 +2571,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_cretaceous_forest {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_cretaceous_forest.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_crosscountry_ski_trail {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_crosscountry_ski_trail.png');
|
||||
width: 68px;
|
||||
@@ -2740,6 +2810,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_flying_over_hedge_maze {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_flying_over_hedge_maze.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_flying_over_icy_steppes {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_flying_over_icy_steppes.png');
|
||||
width: 68px;
|
||||
@@ -3015,11 +3090,21 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_in_a_painting {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_a_painting.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_in_an_ancient_tomb {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_an_ancient_tomb.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_in_an_aquarium {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_an_aquarium.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_in_front_of_fountain {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_in_front_of_fountain.png');
|
||||
width: 68px;
|
||||
@@ -3040,6 +3125,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_inside_adventurers_hideout {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_inside_adventurers_hideout.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_inside_an_ornament {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_inside_an_ornament.png');
|
||||
width: 68px;
|
||||
@@ -3230,6 +3320,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_on_a_paddlewheel_boat {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_on_a_paddlewheel_boat.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_on_tree_branch {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/icon_background_on_tree_branch.png');
|
||||
width: 68px;
|
||||
@@ -18345,6 +18440,16 @@
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoireDiagonalRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoireDiagonalRainbowShirt.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_admiralsUniform {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_admiralsUniform.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_alchemistsRobe {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_alchemistsRobe.png');
|
||||
width: 114px;
|
||||
@@ -18455,6 +18560,11 @@
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_diagonalRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_diagonalRainbowShirt.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_doubletOfClubs {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_doubletOfClubs.png');
|
||||
width: 114px;
|
||||
@@ -18640,6 +18750,11 @@
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_paintersApron {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_paintersApron.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_pirateOutfit {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_pirateOutfit.png');
|
||||
width: 114px;
|
||||
@@ -18750,6 +18865,11 @@
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_stripedRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_stripedRainbowShirt.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_armoire_stripedSwimsuit {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_armoire_stripedSwimsuit.png');
|
||||
width: 90px;
|
||||
@@ -18835,6 +18955,11 @@
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.head_armoire_admiralsBicorne {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_admiralsBicorne.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.head_armoire_alchemistsHat {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_alchemistsHat.png');
|
||||
width: 114px;
|
||||
@@ -19130,6 +19255,11 @@
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.head_armoire_paintersBeret {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_paintersBeret.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.head_armoire_paperBag {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_armoire_paperBag.png');
|
||||
width: 90px;
|
||||
@@ -19470,6 +19600,11 @@
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.shield_armoire_paintersPalette {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_armoire_paintersPalette.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.shield_armoire_perchingFalcon {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_armoire_perchingFalcon.png');
|
||||
width: 90px;
|
||||
@@ -19615,6 +19750,11 @@
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.shop_armor_armoire_admiralsUniform {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_admiralsUniform.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_alchemistsRobe {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_alchemistsRobe.png');
|
||||
width: 68px;
|
||||
@@ -19725,6 +19865,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_diagonalRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_diagonalRainbowShirt.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_doubletOfClubs {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_doubletOfClubs.png');
|
||||
width: 68px;
|
||||
@@ -19910,6 +20055,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_paintersApron {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_paintersApron.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_pirateOutfit {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_pirateOutfit.png');
|
||||
width: 68px;
|
||||
@@ -20020,6 +20170,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_stripedRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_stripedRainbowShirt.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_armoire_stripedSwimsuit {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_armoire_stripedSwimsuit.png');
|
||||
width: 68px;
|
||||
@@ -20120,6 +20275,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_armoire_admiralsBicorne {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_admiralsBicorne.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_armoire_alchemistsHat {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_alchemistsHat.png');
|
||||
width: 68px;
|
||||
@@ -20415,6 +20575,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_armoire_paintersBeret {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_paintersBeret.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_armoire_paperBag {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_armoire_paperBag.png');
|
||||
width: 68px;
|
||||
@@ -20755,6 +20920,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_shield_armoire_paintersPalette {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_armoire_paintersPalette.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_shield_armoire_perchingFalcon {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_armoire_perchingFalcon.png');
|
||||
width: 68px;
|
||||
@@ -21200,6 +21370,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_armoire_paintbrush {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_armoire_paintbrush.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_armoire_paperCutter {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_armoire_paperCutter.png');
|
||||
width: 68px;
|
||||
@@ -21360,6 +21535,11 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.slim_armor_armoire_admiralsUniform {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_admiralsUniform.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_alchemistsRobe {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_alchemistsRobe.png');
|
||||
width: 114px;
|
||||
@@ -21470,6 +21650,11 @@
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_diagonalRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_diagonalRainbowShirt.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_doubletOfClubs {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_doubletOfClubs.png');
|
||||
width: 114px;
|
||||
@@ -21655,6 +21840,11 @@
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_paintersApron {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_paintersApron.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_pirateOutfit {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_pirateOutfit.png');
|
||||
width: 114px;
|
||||
@@ -21765,6 +21955,11 @@
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_stripedRainbowShirt {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_stripedRainbowShirt.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_armoire_stripedSwimsuit {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_armoire_stripedSwimsuit.png');
|
||||
width: 90px;
|
||||
@@ -22110,6 +22305,11 @@
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.weapon_armoire_paintbrush {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_armoire_paintbrush.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.weapon_armoire_paperCutter {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_armoire_paperCutter.png');
|
||||
width: 114px;
|
||||
@@ -27930,6 +28130,66 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.broad_armor_mystery_202306 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_mystery_202306.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.shop_armor_mystery_202306 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_mystery_202306.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_set_mystery_202306 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_set_mystery_202306.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_mystery_202306 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_mystery_202306.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.slim_armor_mystery_202306 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_mystery_202306.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.weapon_mystery_202306 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_mystery_202306.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_mystery_202307 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_mystery_202307.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.headAccessory_mystery_202307 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/headAccessory_mystery_202307.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.shop_armor_mystery_202307 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_mystery_202307.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_headAccessory_mystery_202307 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_headAccessory_mystery_202307.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_set_mystery_202307 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_set_mystery_202307.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.slim_armor_mystery_202307 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_mystery_202307.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.broad_armor_mystery_301404 {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_mystery_301404.png');
|
||||
width: 90px;
|
||||
@@ -30175,6 +30435,26 @@
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.broad_armor_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_special_summer2023Healer.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.broad_armor_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_special_summer2023Mage.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.broad_armor_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_special_summer2023Rogue.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.broad_armor_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_special_summer2023Warrior.png');
|
||||
width: 114px;
|
||||
height: 120px;
|
||||
}
|
||||
.broad_armor_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/broad_armor_special_summerHealer.png');
|
||||
width: 90px;
|
||||
@@ -30365,6 +30645,26 @@
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.head_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_special_summer2023Healer.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.head_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_special_summer2023Mage.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.head_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_special_summer2023Rogue.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.head_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_special_summer2023Warrior.png');
|
||||
width: 114px;
|
||||
height: 120px;
|
||||
}
|
||||
.head_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/head_special_summerHealer.png');
|
||||
width: 90px;
|
||||
@@ -30510,6 +30810,21 @@
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.shield_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_special_summer2023Healer.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.shield_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_special_summer2023Rogue.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.shield_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_special_summer2023Warrior.png');
|
||||
width: 114px;
|
||||
height: 120px;
|
||||
}
|
||||
.shield_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shield_special_summerHealer.png');
|
||||
width: 90px;
|
||||
@@ -30685,6 +31000,26 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_special_summer2023Healer.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_special_summer2023Mage.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_special_summer2023Rogue.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_special_summer2023Warrior.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_armor_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_armor_special_summerHealer.png');
|
||||
width: 68px;
|
||||
@@ -30905,6 +31240,26 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_special_summer2023Healer.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_special_summer2023Mage.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_special_summer2023Rogue.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_special_summer2023Warrior.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_head_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_head_special_summerHealer.png');
|
||||
width: 68px;
|
||||
@@ -31050,6 +31405,21 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_shield_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_special_summer2023Healer.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_shield_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_special_summer2023Rogue.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_shield_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_special_summer2023Warrior.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_shield_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_shield_special_summerHealer.png');
|
||||
width: 68px;
|
||||
@@ -31225,6 +31595,26 @@
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_special_summer2023Healer.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_special_summer2023Mage.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_special_summer2023Rogue.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_special_summer2023Warrior.png');
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.shop_weapon_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/shop_weapon_special_summerHealer.png');
|
||||
width: 68px;
|
||||
@@ -31405,6 +31795,26 @@
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.slim_armor_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_special_summer2023Healer.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.slim_armor_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_special_summer2023Mage.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.slim_armor_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_special_summer2023Rogue.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.slim_armor_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_special_summer2023Warrior.png');
|
||||
width: 114px;
|
||||
height: 120px;
|
||||
}
|
||||
.slim_armor_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/slim_armor_special_summerHealer.png');
|
||||
width: 90px;
|
||||
@@ -31585,6 +31995,26 @@
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.weapon_special_summer2023Healer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_special_summer2023Healer.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.weapon_special_summer2023Mage {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_special_summer2023Mage.png');
|
||||
width: 114px;
|
||||
height: 90px;
|
||||
}
|
||||
.weapon_special_summer2023Rogue {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_special_summer2023Rogue.png');
|
||||
width: 117px;
|
||||
height: 120px;
|
||||
}
|
||||
.weapon_special_summer2023Warrior {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_special_summer2023Warrior.png');
|
||||
width: 114px;
|
||||
height: 120px;
|
||||
}
|
||||
.weapon_special_summerHealer {
|
||||
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/weapon_special_summerHealer.png');
|
||||
width: 90px;
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
.icon-16 {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
.icon-10 {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.icon-12 {
|
||||
@@ -34,21 +34,26 @@
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.icon-16 {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.icon-24 {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.icon-32 {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-48 {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.icon-10 {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="b" d="m10,6h6V0h-2v2.72C12.49.99,10.3,0,8,0,3.59,0,0,3.59,0,8s3.59,8,8,8c2.69,0,5.2-1.35,6.68-3.6l-1.67-1.1c-1.11,1.69-2.99,2.71-5.01,2.7-3.31,0-6-2.69-6-6s2.69-6,6-6c1.72,0,3.33.74,4.46,2h-2.46v2Z" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 341 B |
@@ -17,10 +17,18 @@
|
||||
Payment schedule ("basic-earned" is monthly):
|
||||
<strong>{{ hero.purchased.plan.planId }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.purchased.plan.planId == 'group_plan_auto'">
|
||||
Group plan ID:
|
||||
<strong>{{ hero.purchased.plan.owner }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.purchased.plan.dateCreated">
|
||||
Creation date:
|
||||
<strong>{{ dateFormat(hero.purchased.plan.dateCreated) }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.purchased.plan.dateCurrentTypeCreated">
|
||||
Start date for current subscription type:
|
||||
<strong>{{ dateFormat(hero.purchased.plan.dateCurrentTypeCreated) }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
Termination date:
|
||||
<strong
|
||||
@@ -46,9 +54,16 @@
|
||||
Perk offset months:
|
||||
<strong>{{ hero.purchased.plan.consecutive.offset }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-inline">
|
||||
Perk month count:
|
||||
<strong>{{ hero.purchased.plan.perkMonthCount }}</strong>
|
||||
<input
|
||||
v-model="hero.purchased.plan.perkMonthCount"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
max="2"
|
||||
step="1"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
Next Mystic Hourglass:
|
||||
|
||||
@@ -183,10 +183,8 @@
|
||||
<div
|
||||
v-for="bg in backgroundShopSets[0].items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-2"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
@@ -195,6 +193,13 @@
|
||||
>
|
||||
<div class="small-rectangle"></div>
|
||||
</div>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -211,16 +216,21 @@
|
||||
<div
|
||||
v-for="bg in backgroundShopSets[2].items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
class="background"
|
||||
:class="`background_${bg.key}`"
|
||||
></div>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -236,10 +246,8 @@
|
||||
<div
|
||||
v-for="bg in backgroundShopSets[1].items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="!user.purchased.background[bg.key]
|
||||
? backgroundSelected(bg) : unlock('background.' + bg.key)"
|
||||
>
|
||||
@@ -270,6 +278,13 @@
|
||||
:pinned="isBackgroundPinned(bg)"
|
||||
/>
|
||||
</span>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -302,10 +317,8 @@
|
||||
<div
|
||||
v-for="bg in set.items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="!user.purchased.background[bg.key]
|
||||
? backgroundSelected(bg) : unlock('background.' + bg.key)"
|
||||
>
|
||||
@@ -336,6 +349,13 @@
|
||||
:pinned="isBackgroundPinned(bg)"
|
||||
/>
|
||||
</span>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="!ownsSet('background', set.items) && set.identifier !== 'incentiveBackgrounds'"
|
||||
@@ -358,16 +378,21 @@
|
||||
<div
|
||||
v-for="(bg) in ownedBackgrounds"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
class="background"
|
||||
:class="[`background_${bg.key}`, backgroundLockedStatus(bg.key)]"
|
||||
></div>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
<div class="quest_screen"></div>
|
||||
<div class="row heading">
|
||||
<div class="col-12 text-center pr-5 pl-5">
|
||||
<h2 v-once>
|
||||
<h1
|
||||
v-once
|
||||
class="mb-2"
|
||||
>
|
||||
{{ $t('playInPartyTitle') }}
|
||||
</h2>
|
||||
</h1>
|
||||
<p
|
||||
v-once
|
||||
class="mb-4"
|
||||
@@ -22,67 +25,91 @@
|
||||
</p>
|
||||
<button
|
||||
v-once
|
||||
class="btn btn-primary"
|
||||
class="btn btn-primary px-4 mb-2"
|
||||
@click="createParty()"
|
||||
>
|
||||
{{ $t('createParty') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<close-x
|
||||
@close="close()"
|
||||
/>
|
||||
</div>
|
||||
<div class="row grey-row">
|
||||
<div class="col-12 text-center">
|
||||
<div class="col-12 text-center px-0">
|
||||
<div class="join-party"></div>
|
||||
<h2 v-once>
|
||||
{{ $t('wantToJoinPartyTitle') }}
|
||||
</h2>
|
||||
<p v-html="$t('wantToJoinPartyDescription')"></p>
|
||||
<div
|
||||
class="form-group"
|
||||
@click="copyUsername"
|
||||
<h1
|
||||
v-once
|
||||
class="mb-2"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<label
|
||||
v-once
|
||||
class="mr-3"
|
||||
>{{ $t('username') }}</label>
|
||||
<div class="flex-grow-1">
|
||||
<div class="input-group-prepend input-group-text">
|
||||
@
|
||||
<div class="text">
|
||||
{{ user.auth.local.username }}
|
||||
</div>
|
||||
<div
|
||||
class="svg-icon copy-icon"
|
||||
v-html="icons.copy"
|
||||
></div>
|
||||
<div
|
||||
v-once
|
||||
class="small"
|
||||
>
|
||||
{{ $t('copy') }}
|
||||
</div>
|
||||
</div>
|
||||
{{ $t('wantToJoinPartyTitle') }}
|
||||
</h1>
|
||||
<p
|
||||
v-once
|
||||
class="mb-4"
|
||||
v-html="$t('partyFinderDescription')"
|
||||
>
|
||||
</p>
|
||||
<div
|
||||
v-if="seeking"
|
||||
>
|
||||
<div
|
||||
class="green-bar mb-3"
|
||||
>
|
||||
{{ $t('currentlyLookingForParty') }}
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div
|
||||
class="red-link"
|
||||
@click="seekParty()"
|
||||
>
|
||||
{{ $t('leave') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-primary px-4 mt-2 mb-1"
|
||||
@click="seekParty()"
|
||||
>
|
||||
{{ $t('lookForParty') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#create-party-modal .modal-body {
|
||||
padding: 0rem 0.75rem;
|
||||
}
|
||||
<style lang="scss">
|
||||
#create-party-modal {
|
||||
display: flex !important;
|
||||
overflow-y: hidden;
|
||||
|
||||
#create-party-modal .modal-dialog {
|
||||
width: 35.75rem;
|
||||
}
|
||||
@media (max-height: 770px) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#create-party-modal .modal-header {
|
||||
padding: 0;
|
||||
border-bottom: 0px;
|
||||
.modal-body {
|
||||
padding: 0rem 0.75rem;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 566px;
|
||||
margin: auto;
|
||||
|
||||
@media (max-height: 826px) {
|
||||
margin-top: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 0;
|
||||
border-bottom: 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -107,15 +134,27 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.green-bar {
|
||||
height: 32px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 1.71;
|
||||
text-align: center;
|
||||
color: $green-1;
|
||||
background-color: $green-100;
|
||||
border-radius: 2px;
|
||||
padding: 4px 0px 4px 0px;
|
||||
}
|
||||
|
||||
.grey-row {
|
||||
background-color: $gray-700;
|
||||
color: #4e4a57;
|
||||
padding: 2em;
|
||||
border-radius: 0px 0px 2px 2px;
|
||||
border-radius: 0px 0px 8px 8px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $gray-100;
|
||||
h1 {
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
.header-wrap {
|
||||
@@ -132,10 +171,6 @@
|
||||
border-radius: 2px 2px 0 0;
|
||||
image-rendering: optimizequality;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $purple-200;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
@@ -182,6 +217,21 @@
|
||||
margin: 0.75rem auto 0.75rem 0.25rem;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.red-link {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
text-align: center;
|
||||
color: $maroon-50;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.small {
|
||||
color: $gray-200;
|
||||
margin: auto 0.5rem auto 0.25rem;
|
||||
@@ -192,21 +242,29 @@
|
||||
import { mapState } from '@/libs/store';
|
||||
import * as Analytics from '@/libs/analytics';
|
||||
import notifications from '@/mixins/notifications';
|
||||
import closeX from '../ui/closeX';
|
||||
|
||||
import copyIcon from '@/assets/svg/copy.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
closeX,
|
||||
},
|
||||
mixins: [notifications],
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
copy: copyIcon,
|
||||
}),
|
||||
seeking: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({ user: 'user.data' }),
|
||||
},
|
||||
mounted () {
|
||||
this.seeking = Boolean(this.user.party.seeking);
|
||||
},
|
||||
methods: {
|
||||
async createParty () {
|
||||
const group = {
|
||||
@@ -223,7 +281,10 @@ export default {
|
||||
});
|
||||
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
this.$router.push('/party');
|
||||
await this.$router.push('/party');
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
},
|
||||
copyUsername () {
|
||||
if (navigator.clipboard) {
|
||||
@@ -238,6 +299,12 @@ export default {
|
||||
}
|
||||
this.text(this.$t('usernameCopied'));
|
||||
},
|
||||
seekParty () {
|
||||
this.$store.dispatch('user:set', {
|
||||
'party.seeking': !this.user.party.seeking ? new Date() : null,
|
||||
});
|
||||
this.seeking = !this.seeking;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -542,7 +542,8 @@ export default {
|
||||
await this.$store.dispatch('guilds:leave', data);
|
||||
|
||||
if (this.isParty) {
|
||||
this.$router.push({ name: 'tasks' });
|
||||
await this.$router.push({ name: 'tasks' });
|
||||
window.location.reload(true);
|
||||
}
|
||||
},
|
||||
upgradeGroup () {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<group-plan-creation-modal />
|
||||
<div>
|
||||
<div class="header">
|
||||
<h1 class="text-center">
|
||||
Need more for your Group?
|
||||
<h1 v-once class="text-center">
|
||||
{{ $t('groupPlanTitle') }}
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col-8 offset-2 text-center">
|
||||
<h2 class="sub-text">
|
||||
<h2 v-once class="sub-text">
|
||||
{{ $t('groupBenefitsDescription') }}
|
||||
</h2>
|
||||
</div>
|
||||
@@ -24,8 +24,8 @@
|
||||
src="~@/assets/images/group-plans/group-14@3x.png"
|
||||
>
|
||||
<hr>
|
||||
<h2>{{ $t('teamBasedTasks') }}</h2>
|
||||
<p>Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!</p><!-- eslint-disable-line max-len -->
|
||||
<h2 v-once> {{ $t('teamBasedTasks') }} </h2>
|
||||
<p v-once> {{ $t('teamBasedTasksListDesc') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
@@ -35,8 +35,8 @@
|
||||
src="~@/assets/images/group-plans/group-12@3x.png"
|
||||
>
|
||||
<hr>
|
||||
<h2>Group Management Controls</h2>
|
||||
<p>Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.</p><!-- eslint-disable-line max-len -->
|
||||
<h2 v-once> {{ $t('groupManagementControls') }} </h2>
|
||||
<p v-once> {{ $t('groupManagementControlsDesc') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
@@ -46,8 +46,8 @@
|
||||
src="~@/assets/images/group-plans/group-13@3x.png"
|
||||
>
|
||||
<hr>
|
||||
<h2>In-Game Benefits</h2>
|
||||
<p>Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.</p><!-- eslint-disable-line max-len -->
|
||||
<h2 v-once> {{ $t('inGameBenefits') }} </h2>
|
||||
<p v-once> {{ $t('inGameBenefitsDesc') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div
|
||||
v-if="seekers.length > 0"
|
||||
class="fit-content mx-auto mt-4"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<h1 v-once class="my-auto mr-auto"> {{ $t('findPartyMembers') }}</h1>
|
||||
<div
|
||||
class="btn btn-secondary btn-sync ml-auto my-auto pl-2 pr-3 d-flex"
|
||||
@click="refreshList()"
|
||||
>
|
||||
<div class="svg-icon icon-16 color my-auto mr-2" v-html="icons.sync"></div>
|
||||
<div class="ml-auto"> {{ $t('refreshList') }} </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap seeker-list">
|
||||
<div
|
||||
v-for="(seeker, index) in seekers"
|
||||
:key="seeker._id"
|
||||
class="seeker"
|
||||
>
|
||||
<div class="d-flex">
|
||||
<avatar
|
||||
:member="seeker"
|
||||
:hideClassBadge="true"
|
||||
@click.native="showMemberModal(seeker._id)"
|
||||
class="mr-3 mb-2"
|
||||
/>
|
||||
<div class="card-data">
|
||||
<user-link
|
||||
:user-id="seeker._id"
|
||||
:name="seeker.profile.name"
|
||||
:backer="seeker.backer"
|
||||
:contributor="seeker.contributor"
|
||||
/>
|
||||
<div class="small-with-border pb-2 mb-2">
|
||||
@{{ seeker.auth.local.username }} • {{ $t('level') }} {{ seeker.stats.lvl }}
|
||||
</div>
|
||||
<div
|
||||
class="d-flex"
|
||||
>
|
||||
<strong v-once> {{ $t('classLabel') }} </strong>
|
||||
<span
|
||||
class="svg-icon d-inline-block icon-16 my-auto mx-2"
|
||||
v-html="icons[seeker.stats.class]"
|
||||
>
|
||||
</span>
|
||||
<strong
|
||||
:class="`${seeker.stats.class}-color`"
|
||||
>
|
||||
{{ $t(seeker.stats.class) }}
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<strong v-once class="mr-2"> {{ $t('checkinsLabel') }} </strong>
|
||||
{{ seeker.loginIncentives }}
|
||||
</div>
|
||||
<div>
|
||||
<strong v-once class="mr-2"> {{ $t('languageLabel') }} </strong>
|
||||
{{ displayLanguage(seeker.preferences.language) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<strong
|
||||
v-if="!seeker.invited"
|
||||
@click="inviteUser(seeker._id, index)"
|
||||
class="btn btn-primary w-100"
|
||||
>
|
||||
{{ $t('inviteToParty') }}
|
||||
</strong>
|
||||
<div
|
||||
v-else
|
||||
@click="rescindInvite(seeker._id, index)"
|
||||
class="btn btn-success w-100"
|
||||
v-html="$t('invitedToYourParty')"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<mugen-scroll
|
||||
v-show="loading"
|
||||
:handler="infiniteScrollTrigger"
|
||||
:should-handle="!loading && canLoadMore"
|
||||
:threshold="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="seekers.length === 0 && !loading"
|
||||
class="d-flex flex-column empty-state text-center my-5"
|
||||
>
|
||||
<div class="gray-circle mb-3 mx-auto d-flex">
|
||||
<div
|
||||
class="svg-icon icon-32 color m-auto"
|
||||
v-html="icons.users"
|
||||
>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<strong class="mb-1"> {{ $t('findMorePartyMembers') }} </strong>
|
||||
<div v-html="$t('noOneLooking')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<h2
|
||||
v-show="loading"
|
||||
class="loading"
|
||||
:class="seekers.length === 0 ? 'mt-3' : 'mt-0'"
|
||||
>
|
||||
{{ $t('loading') }}
|
||||
</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
h1 {
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
strong {
|
||||
line-height: 1.71;
|
||||
}
|
||||
.avatar {
|
||||
background-color: $gray-600;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
box-shadow: none;
|
||||
color: $green-1;
|
||||
font-weight: normal;
|
||||
|
||||
&:not(:disabled):not(.disabled):active {
|
||||
color: $green-1;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-sync {
|
||||
min-width: 128px;
|
||||
max-height: 32px;
|
||||
|
||||
.svg-icon {
|
||||
color: $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
.card-data {
|
||||
width: 267px;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
color: $gray-100;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.fit-content {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.gray-circle {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
color: $gray-600;
|
||||
background-color: $gray-200;
|
||||
border-radius: 100px;
|
||||
|
||||
.icon-32 {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
.seeker-list {
|
||||
max-width: 920px;
|
||||
|
||||
@media (max-width: 962px) {
|
||||
max-width: 464px;
|
||||
};
|
||||
|
||||
.seeker {
|
||||
width: 448px;
|
||||
margin-bottom: 24px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px 0 rgba(26, 24, 29, 0.12), 0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 963px) {
|
||||
&:nth-child(2) {
|
||||
margin-top: 24px;
|
||||
}
|
||||
&:nth-child(even) {
|
||||
margin-left: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.small-with-border {
|
||||
border-bottom: 1px solid $gray-500;
|
||||
color: $gray-100;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
.healer-color {
|
||||
color: $yellow-10;
|
||||
}
|
||||
|
||||
.rogue-color {
|
||||
color: $purple-200;
|
||||
}
|
||||
|
||||
.warrior-color {
|
||||
color: $red-50;
|
||||
}
|
||||
|
||||
.wizard-color {
|
||||
color: $blue-10;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce';
|
||||
import MugenScroll from 'vue-mugen-scroll';
|
||||
import Avatar from '../avatar';
|
||||
import userLink from '../userLink';
|
||||
import { mapState } from '@/libs/store';
|
||||
|
||||
import syncIcon from '@/assets/svg/sync-2.svg';
|
||||
import usersIcon from '@/assets/svg/users.svg';
|
||||
import warriorIcon from '@/assets/svg/warrior.svg';
|
||||
import rogueIcon from '@/assets/svg/rogue.svg';
|
||||
import healerIcon from '@/assets/svg/healer.svg';
|
||||
import wizardIcon from '@/assets/svg/wizard.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Avatar,
|
||||
MugenScroll,
|
||||
userLink,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
canLoadMore: true,
|
||||
loading: true,
|
||||
page: 0,
|
||||
party: {},
|
||||
seekers: [],
|
||||
icons: Object.freeze({
|
||||
warrior: warriorIcon,
|
||||
rogue: rogueIcon,
|
||||
healer: healerIcon,
|
||||
sync: syncIcon,
|
||||
users: usersIcon,
|
||||
wizard: wizardIcon,
|
||||
}),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
availableLanguages: 'i18n.availableLanguages',
|
||||
user: 'user.data',
|
||||
}),
|
||||
},
|
||||
async mounted () {
|
||||
try {
|
||||
this.party = await this.$store.dispatch('guilds:getGroup', { groupId: this.user.party._id });
|
||||
} catch {
|
||||
this.$router.push('/');
|
||||
}
|
||||
if (!this.party._id || this.party.leader._id !== this.user._id) {
|
||||
this.$router.push('/');
|
||||
} else {
|
||||
this.$store.dispatch('common:setTitle', {
|
||||
section: this.$t('lookingForPartyTitle'),
|
||||
});
|
||||
this.seekers = await this.$store.dispatch('party:lookingForParty');
|
||||
this.canLoadMore = this.seekers.length === 30;
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
displayLanguage (languageCode) {
|
||||
const language = this.availableLanguages.find(lang => lang.code === languageCode);
|
||||
if (language) {
|
||||
return language.name;
|
||||
}
|
||||
return languageCode;
|
||||
},
|
||||
infiniteScrollTrigger () {
|
||||
if (this.canLoadMore) {
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
this.loadMore();
|
||||
},
|
||||
async inviteUser (userId, index) {
|
||||
await this.$store.dispatch('guilds:invite', {
|
||||
invitationDetails: {
|
||||
inviter: this.user.profile.name,
|
||||
uuids: [userId],
|
||||
},
|
||||
groupId: this.party._id,
|
||||
});
|
||||
this.seekers[index].invited = true;
|
||||
},
|
||||
loadMore: debounce(async function loadMoreDebounce () {
|
||||
this.page += 1;
|
||||
const addlSeekers = await this.$store.dispatch('party:lookingForParty', { page: this.page });
|
||||
this.seekers = this.seekers.concat(addlSeekers);
|
||||
this.canLoadMore = this.seekers.length % 30 === 0;
|
||||
this.loading = false;
|
||||
}, 1000),
|
||||
async refreshList () {
|
||||
this.loading = true;
|
||||
this.page = 0;
|
||||
this.seekers = await this.$store.dispatch('party:lookingForParty');
|
||||
this.canLoadMore = this.seekers.length === 30;
|
||||
this.loading = false;
|
||||
},
|
||||
async rescindInvite (userId, index) {
|
||||
await this.$store.dispatch('members:removeMember', {
|
||||
memberId: userId,
|
||||
groupId: this.party._id,
|
||||
});
|
||||
this.seekers[index].invited = false;
|
||||
},
|
||||
showMemberModal (userId) {
|
||||
this.$router.push({ name: 'userProfile', params: { userId } });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="sidebar px-4">
|
||||
<div>
|
||||
<div class="buttons-wrapper">
|
||||
<div class="button-container button-with-menu-row">
|
||||
<div class="button-container d-flex">
|
||||
<button
|
||||
v-if="!isMember"
|
||||
class="btn btn-success btn-success"
|
||||
@@ -203,10 +203,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.button-with-menu-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.menuIcon {
|
||||
width: 4px;
|
||||
height: 1rem;
|
||||
|
||||
@@ -258,13 +258,22 @@
|
||||
:key="hero._id"
|
||||
>
|
||||
<td>
|
||||
<user-link
|
||||
<div
|
||||
v-if="hasPermission(hero, 'userSupport')"
|
||||
:user="hero"
|
||||
:popover="$t('gamemaster')"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
/>
|
||||
class="width-content"
|
||||
>
|
||||
<user-link
|
||||
:id="hero._id"
|
||||
:user="hero"
|
||||
/>
|
||||
<b-popover
|
||||
:target="hero._id"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('gamemaster')"
|
||||
/>
|
||||
</div>
|
||||
<user-link
|
||||
v-else
|
||||
:user="hero"
|
||||
@@ -302,6 +311,10 @@
|
||||
h4.expand-toggle::after {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.width-content {
|
||||
width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -51,20 +51,20 @@
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="no-party d-none d-md-flex justify-content-center text-center mr-4"
|
||||
class="no-party d-none d-md-flex justify-content-center text-center mr-4"
|
||||
>
|
||||
<div class="align-self-center">
|
||||
<h3>{{ $t('battleWithFriends') }}</h3>
|
||||
<h3>{{ user.party._id ? $t('questWithOthers') : $t('battleWithFriends') }}</h3>
|
||||
<span
|
||||
class="small-text"
|
||||
v-html="$t('inviteFriendsParty')"
|
||||
v-html="user.party._id ? $t('inviteFriendsParty') : $t('startPartyDetail')"
|
||||
></span>
|
||||
<br>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="createOrInviteParty()"
|
||||
>
|
||||
{{ user.party._id ? $t('inviteFriends') : $t('startAParty') }}
|
||||
{{ user.party._id ? $t('findPartyMembers') : $t('getStarted') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,6 +122,7 @@
|
||||
|
||||
<script>
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import * as Analytics from '@/libs/analytics';
|
||||
import { mapGetters, mapActions } from '@/libs/store';
|
||||
import MemberDetails from '../memberDetails';
|
||||
import createPartyModal from '../groups/createPartyModal';
|
||||
@@ -232,10 +233,24 @@ export default {
|
||||
this.expandedMember = memberId;
|
||||
}
|
||||
},
|
||||
createOrInviteParty () {
|
||||
async createOrInviteParty () {
|
||||
if (this.user.party._id) {
|
||||
this.$root.$emit('inviteModal::inviteToGroup', this.user.party);
|
||||
await Analytics.track({
|
||||
eventName: 'Header Party CTA',
|
||||
eventAction: 'Header Party CTA',
|
||||
eventCategory: 'behavior',
|
||||
hitType: 'event',
|
||||
state: 'Find Party Members',
|
||||
});
|
||||
this.$router.push('/looking-for-party');
|
||||
} else {
|
||||
await Analytics.track({
|
||||
eventName: 'Header Party CTA',
|
||||
eventAction: 'Header Party CTA',
|
||||
eventCategory: 'behavior',
|
||||
hitType: 'event',
|
||||
state: 'Get Started',
|
||||
});
|
||||
this.$root.$emit('bv::show::modal', 'create-party-modal');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<b-nav-item
|
||||
v-if="user.party._id"
|
||||
v-if="user.party._id && user._id !== partyLeaderId"
|
||||
class="topbar-item"
|
||||
:class="{'active': $route.path.startsWith('/party')}"
|
||||
tag="li"
|
||||
@@ -156,6 +156,36 @@
|
||||
>
|
||||
{{ $t('party') }}
|
||||
</b-nav-item>
|
||||
<li
|
||||
v-if="user.party._id && user._id === partyLeaderId"
|
||||
class="topbar-item droppable"
|
||||
:class="{'active': $route.path.startsWith('/party')}"
|
||||
>
|
||||
<div
|
||||
class="chevron rotate"
|
||||
@click="dropdownMobile($event)"
|
||||
>
|
||||
<div
|
||||
v-once
|
||||
class="chevron-icon-down"
|
||||
v-html="icons.chevronDown"
|
||||
></div>
|
||||
</div>
|
||||
<router-link
|
||||
class="nav-link"
|
||||
:to="{name: 'party'}"
|
||||
>
|
||||
{{ $t('party') }}
|
||||
</router-link>
|
||||
<div class="topbar-dropdown">
|
||||
<router-link
|
||||
class="topbar-dropdown-item dropdown-item"
|
||||
:to="{name: 'lookingForParty'}"
|
||||
>
|
||||
{{ $t('lookingForPartyTitle') }}
|
||||
</router-link>
|
||||
</div>
|
||||
</li>
|
||||
<b-nav-item
|
||||
v-if="!user.party._id"
|
||||
class="topbar-item"
|
||||
@@ -768,6 +798,7 @@ export default {
|
||||
return {
|
||||
isUserDropdownOpen: false,
|
||||
menuIsOpen: false,
|
||||
partyLeaderId: null,
|
||||
icons: Object.freeze({
|
||||
gem: gemIcon,
|
||||
gold: goldIcon,
|
||||
@@ -796,8 +827,9 @@ export default {
|
||||
};
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.getUserGroupPlans();
|
||||
async mounted () {
|
||||
await this.getUserGroupPlans();
|
||||
await this.getUserParty();
|
||||
Array.from(document.getElementById('menu_collapse').getElementsByTagName('a')).forEach(link => {
|
||||
link.addEventListener('click', this.closeMenu);
|
||||
});
|
||||
@@ -805,6 +837,9 @@ export default {
|
||||
link.addEventListener('mouseenter', this.dropdownDesktop);
|
||||
link.addEventListener('mouseleave', this.dropdownDesktop);
|
||||
});
|
||||
this.$root.$on('update-party', () => {
|
||||
this.getUserParty();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
modForm () {
|
||||
@@ -816,6 +851,12 @@ export default {
|
||||
async getUserGroupPlans () {
|
||||
await this.$store.dispatch('guilds:getGroupPlans');
|
||||
},
|
||||
async getUserParty () {
|
||||
if (this.user.party._id) {
|
||||
await this.$store.dispatch('party:getParty');
|
||||
this.partyLeaderId = this.$store.state.party.data.leader._id;
|
||||
}
|
||||
},
|
||||
openPartyModal () {
|
||||
this.$root.$emit('bv::show::modal', 'create-party-modal');
|
||||
},
|
||||
|
||||
@@ -34,11 +34,13 @@
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
import { mapState } from '@/libs/store';
|
||||
import sync from '@/mixins/sync';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
mixins: [sync],
|
||||
props: {
|
||||
notification: {
|
||||
type: Object,
|
||||
@@ -73,6 +75,7 @@ export default {
|
||||
}
|
||||
|
||||
await this.$store.dispatch('guilds:join', { groupId: group.id, type: 'party' });
|
||||
this.sync();
|
||||
this.$router.push('/party');
|
||||
},
|
||||
reject () {
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
<!-- the word "total" -->
|
||||
<div class="buy-gem-total">
|
||||
{{ $t('sendGiftTotal') }}
|
||||
{{ $t('sendTotal') }}
|
||||
</div>
|
||||
|
||||
<!-- the actual dollar amount -->
|
||||
|
||||
@@ -128,7 +128,10 @@
|
||||
<hr>
|
||||
</div>
|
||||
<div>
|
||||
<div class="checkbox">
|
||||
<div
|
||||
class="checkbox"
|
||||
id="preferenceAdvancedCollapsed"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.advancedCollapsed"
|
||||
@@ -136,33 +139,22 @@
|
||||
class="mr-2"
|
||||
@change="set('advancedCollapsed')"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('startAdvCollapsedPop')"
|
||||
>{{ $t('startAdvCollapsed') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.dailyDueDefaultView"
|
||||
type="checkbox"
|
||||
class="mr-2"
|
||||
@change="set('dailyDueDefaultView')"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('dailyDueDefaultViewPop')"
|
||||
>{{ $t('dailyDueDefaultView') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('startAdvCollapsed') }}
|
||||
</span>
|
||||
<b-popover
|
||||
target="preferenceAdvancedCollapsed"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('startAdvCollapsedPop')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="party.memberCount === 1"
|
||||
class="checkbox"
|
||||
id="preferenceDisplayInviteAtOneMember"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
@@ -171,12 +163,9 @@
|
||||
class="mr-2"
|
||||
@change="set('displayInviteToPartyWhenPartyIs1')"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('displayInviteToPartyWhenPartyIs1')"
|
||||
>{{ $t('displayInviteToPartyWhenPartyIs1') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('displayInviteToPartyWhenPartyIs1') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
@@ -217,32 +206,47 @@
|
||||
</div>
|
||||
<hr>
|
||||
<button
|
||||
id="buttonShowBailey"
|
||||
class="btn btn-primary mr-2 mb-2"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('showBaileyPop')"
|
||||
@click="showBailey()"
|
||||
>
|
||||
{{ $t('showBailey') }}
|
||||
<b-popover
|
||||
target="buttonShowBailey"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('showBaileyPop')"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
id="buttonFCV"
|
||||
class="btn btn-primary mr-2 mb-2"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('fixValPop')"
|
||||
@click="openRestoreModal()"
|
||||
>
|
||||
{{ $t('fixVal') }}
|
||||
<b-popover
|
||||
target="buttonFCV"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('fixValPop')"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
v-if="user.preferences.disableClasses == true"
|
||||
id="buttonEnableClasses"
|
||||
class="btn btn-primary mb-2"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('enableClassPop')"
|
||||
@click="changeClassForUser(false)"
|
||||
>
|
||||
{{ $t('enableClass') }}
|
||||
<b-popover
|
||||
target="buttonEnableClasses"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('enableClassPop')"
|
||||
/>
|
||||
</button>
|
||||
<hr>
|
||||
<day-start-adjustment />
|
||||
@@ -532,6 +536,10 @@
|
||||
input {
|
||||
color: $gray-50;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: fit-content;
|
||||
}
|
||||
.usersettings h5 {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="item-cost">
|
||||
<span
|
||||
class="cost"
|
||||
:class="getPriceClass()"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
@import '~@/assets/scss/mixins.scss';
|
||||
|
||||
.item-cost {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.cost {
|
||||
height: 40px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
vertical-align: middle;
|
||||
|
||||
&.gems {
|
||||
color: $gems-color;
|
||||
border-radius: 20px;
|
||||
padding: 8px 20px 8px 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: rgba(36, 204, 143, 0.15);
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $gold-color;
|
||||
border-radius: 20px;
|
||||
padding: 8px 20px 8px 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
border-radius: 20px;
|
||||
padding: 8px 20px 8px 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: rgba(41, 149, 205, 0.15);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import svgClose from '@/assets/svg/close.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close: svgClose,
|
||||
gold: svgGold,
|
||||
gems: svgGem,
|
||||
}),
|
||||
selectedAmountToBuy: 1,
|
||||
selectedAmount: 1,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPriceClass () {
|
||||
if (this.priceType && this.icons[this.priceType]) {
|
||||
return this.priceType;
|
||||
} if (this.item.currency && this.icons[this.item.currency]) {
|
||||
return this.item.currency;
|
||||
}
|
||||
return 'gold';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div class="d-flex flex-row align-items-center justify-content-center number-increment">
|
||||
<!-- buy modal -->
|
||||
<div
|
||||
class="gray-circle"
|
||||
@click="quantity <= 0
|
||||
? quantity = 0
|
||||
: quantity--"
|
||||
>
|
||||
<div
|
||||
class="icon-negative"
|
||||
v-html="icons.svgNegative"
|
||||
></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="align-items-center">
|
||||
</div>
|
||||
<input
|
||||
v-model="quantity"
|
||||
class="form-control alignment"
|
||||
step="1"
|
||||
type="number"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="gray-circle"
|
||||
@click="quantity++"
|
||||
>
|
||||
<div
|
||||
class="icon-positive"
|
||||
v-html="icons.svgPositive"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.number-increment {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.alignment {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
width: 94px;
|
||||
height: 32px;
|
||||
width: 48px;
|
||||
margin: 0px 16px 0px 16px;
|
||||
padding: 0;
|
||||
border-radius: 2px;
|
||||
border: solid 1px $gray-400;
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
.gray-circle {
|
||||
border-radius: 100%;
|
||||
border: solid 2px $gray-300;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-color: $purple-300;
|
||||
}
|
||||
}
|
||||
|
||||
.gray-circle:hover{
|
||||
.icon-positive, .icon-negative {
|
||||
& ::v-deep svg path {
|
||||
fill: $purple-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-positive, .icon-negative {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 4px auto;
|
||||
|
||||
& ::v-deep svg path {
|
||||
fill: $gray-300;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// icons
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
svgGem,
|
||||
svgGold,
|
||||
svgPositive,
|
||||
svgNegative,
|
||||
}),
|
||||
item: { },
|
||||
quantity: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
quantity () {
|
||||
this.$emit('updateQuantity', this.quantity);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setDefaults () {
|
||||
this.input = 1;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
@@ -22,10 +22,11 @@
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
span {
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</span>
|
||||
<div>
|
||||
<span
|
||||
class="svg-icon icon-12 close-icon"
|
||||
class="svg-icon close-icon icon-16 color"
|
||||
aria-hidden="true"
|
||||
tabindex="0"
|
||||
@click="hideDialog()"
|
||||
@@ -45,6 +45,13 @@
|
||||
:sprites-margin="'0px auto 0px -24px'"
|
||||
/>
|
||||
</div>
|
||||
<item
|
||||
v-else-if="item.key === 'gem'"
|
||||
class="flat bordered-item"
|
||||
:item="item"
|
||||
:item-content-class="item.class"
|
||||
:show-popover="false"
|
||||
/>
|
||||
<item
|
||||
v-else-if="item.key != 'gem'"
|
||||
class="flat bordered-item"
|
||||
@@ -53,10 +60,20 @@
|
||||
:show-popover="false"
|
||||
/>
|
||||
</slot>
|
||||
<div
|
||||
v-if="!showAvatar && user.items[item.purchaseType]"
|
||||
class="owned"
|
||||
:class="totalOwned"
|
||||
>
|
||||
<!-- eslint-disable-next-line max-len -->
|
||||
<span class="owned-text">{{ $t('owned') }}: <span class="user-amount">{{ totalOwned }}</span></span>
|
||||
</div>
|
||||
<h4 class="title">
|
||||
{{ itemText }}
|
||||
</h4>
|
||||
<div v-html="itemNotes"></div>
|
||||
<div class="item-notes">
|
||||
{{ itemNotes }}
|
||||
</div>
|
||||
<slot
|
||||
name="additionalInfo"
|
||||
:item="item"
|
||||
@@ -69,60 +86,61 @@
|
||||
/>
|
||||
</slot>
|
||||
<div
|
||||
v-if="item.value > 0"
|
||||
v-if="item.value > 0 && !(item.key === 'gem' && gemsLeft < 1)"
|
||||
class="purchase-amount"
|
||||
>
|
||||
<div
|
||||
v-if="showAmountToBuy(item)"
|
||||
class="how-many-to-buy"
|
||||
>
|
||||
<strong>{{ $t('howManyToBuy') }}</strong>
|
||||
</div>
|
||||
<div v-if="showAmountToBuy(item)">
|
||||
<div class="box">
|
||||
<input
|
||||
v-model.number="selectedAmountToBuy"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
>
|
||||
</div>
|
||||
<span :class="{'notEnough': notEnoughCurrency}">
|
||||
<!-- this is where the pretty item cost element lives -->
|
||||
<div class="item-cost">
|
||||
<span
|
||||
class="cost"
|
||||
:class="getPriceClass()"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-32"
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
></span>
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="cost"
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="d-flex align-items-middle"
|
||||
v-if="showAmountToBuy(item)"
|
||||
class="how-many-to-buy"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-32 ml-auto my-auto"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
></span>
|
||||
<span
|
||||
class="cost mr-auto my-auto"
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value }}</span>
|
||||
{{ $t('howManyToBuy') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="showAmountToBuy(item)"
|
||||
>
|
||||
<number-increment
|
||||
class="number-increment"
|
||||
@updateQuantity="selectedAmountToBuy = $event"
|
||||
/>
|
||||
<div
|
||||
:class="{'notEnough': notEnoughCurrency}"
|
||||
class="total"
|
||||
>
|
||||
<span class="total-text">{{ $t('sendTotal') }}</span>
|
||||
<span
|
||||
class="svg-icon total icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
></span>
|
||||
<span
|
||||
class="total-text"
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value * selectedAmountToBuy }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="item.key === 'gem'"
|
||||
class="gems-left"
|
||||
v-if="item.key === 'gem' && gemsLeft < 1"
|
||||
class="no-more-gems"
|
||||
>
|
||||
<strong v-if="gemsLeft > 0">{{ gemsLeft }} {{ $t('gemsRemaining') }}</strong>
|
||||
<strong v-if="gemsLeft === 0">{{ $t('maxBuyGems') }}</strong>
|
||||
</div>
|
||||
<div v-if="attemptingToPurchaseMoreGemsThanAreLeft">
|
||||
{{ $t('notEnoughGemsToBuy') }}
|
||||
</div>
|
||||
<div
|
||||
@@ -147,7 +165,7 @@
|
||||
{{ $t('viewSubscriptions') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
v-else-if="!(item.key === 'gem' && gemsLeft < 1)"
|
||||
class="btn btn-primary"
|
||||
:disabled="item.key === 'gem' && gemsLeft === 0 ||
|
||||
attemptingToPurchaseMoreGemsThanAreLeft || numberInvalid || item.locked ||
|
||||
@@ -165,6 +183,7 @@
|
||||
<countdown-banner
|
||||
v-if="item.event && item.owned == null"
|
||||
:end-date="endDate"
|
||||
class="limitedTime available"
|
||||
/>
|
||||
<div
|
||||
v-if="item.key === 'rebirth_orb' && item.value > 0 && user.stats.lvl >= 100"
|
||||
@@ -179,12 +198,31 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
slot="modal-footer"
|
||||
class="d-flex"
|
||||
v-if="item.key === 'gem'"
|
||||
class="d-flex justify-content-center align-items-center"
|
||||
>
|
||||
<span class="balance mr-auto">{{ $t('yourBalance') }}</span>
|
||||
<div
|
||||
v-if="gemsLeft > 0"
|
||||
class="gems-left d-flex justify-content-center align-items-center"
|
||||
>
|
||||
<strong>{{ $t('monthlyGems') }} </strong>
|
||||
{{ gemsLeft }} / {{ totalGems }} {{ $t('gemsRemaining') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="gemsLeft === 0"
|
||||
class="out-of-gems-banner d-flex justify-content-center align-items-center"
|
||||
>
|
||||
<strong>{{ $t('monthlyGems') }} </strong>
|
||||
{{ gemsLeft }} / {{ totalGems }} {{ $t('gemsRemaining') }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
slot="modal-footer"
|
||||
class="clearfix"
|
||||
>
|
||||
<span class="user-balance float-left">{{ $t('yourBalance') }}</span>
|
||||
<balanceInfo
|
||||
class="ml-auto"
|
||||
class="currency-totals"
|
||||
:currency-needed="getPriceClass()"
|
||||
:amount-needed="item.value"
|
||||
/>
|
||||
@@ -200,11 +238,47 @@
|
||||
@include centeredModal();
|
||||
|
||||
.modal-body {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
margin: 24px 0 0 0;
|
||||
padding: 16px 24px;
|
||||
align-content: center;
|
||||
|
||||
.user-balance {
|
||||
width: 150px;
|
||||
height: 16px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.currency-totals {
|
||||
margin-right: -8px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 330px;
|
||||
width: 448px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.badge-dialog {
|
||||
left: -8px;
|
||||
top: -8px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@@ -212,8 +286,71 @@
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.owned {
|
||||
height: 32px;
|
||||
width: 141px;
|
||||
margin-top: -36px;
|
||||
margin-left: 153px;
|
||||
padding-top: 6px;
|
||||
background-color: $gray-600;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.owned-text {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.user-amount {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
transform: scale(1.45, 1.45);
|
||||
top: -25.67px;
|
||||
left: 1px;
|
||||
|
||||
&.shop_gem {
|
||||
transform: scale(1.45, 1.45);
|
||||
top: -2px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 28px;
|
||||
color: $gray-10;
|
||||
font-size: 1.25rem;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.item-notes {
|
||||
margin-top: 8px;
|
||||
padding-left: 48.5px;
|
||||
padding-right: 48.5px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
width: 448px;
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
@@ -221,15 +358,22 @@
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
margin: 33px auto auto;
|
||||
width: 282px;
|
||||
margin: 32px auto auto;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.purchase-amount {
|
||||
margin-top: 24px;
|
||||
margin-top: 0px;
|
||||
|
||||
.how-many-to-buy {
|
||||
margin-bottom: 16px;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.number-increment {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.box {
|
||||
@@ -255,31 +399,105 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-more-gems {
|
||||
color: $yellow-5;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.33;
|
||||
margin: 16px 48px 0 48px;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
||||
// for cost icon of a single item
|
||||
span.svg-icon.inline.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
// for the total user cost
|
||||
span.svg-icon.total.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-left: 6px;
|
||||
margin-right: 8px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
vertical-align: middle;
|
||||
span.svg-icon.icon-16 {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
color: $gray-200;
|
||||
stroke-width: 0px;
|
||||
|
||||
&:hover {
|
||||
color: $gray-100;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-group {
|
||||
margin: 32px;
|
||||
border-radius: 4px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875;
|
||||
}
|
||||
|
||||
.attributesGrid {
|
||||
margin-top: 28px;
|
||||
border-radius: 2px;
|
||||
background-color: $gray-500;
|
||||
}
|
||||
|
||||
.item-cost {
|
||||
display: inline-flex;
|
||||
margin: 16px 0;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.cost {
|
||||
width: 28px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
|
||||
vertical-align: middle;
|
||||
padding: 6px 20px;
|
||||
line-height: 1.4;
|
||||
border-radius: 20px;
|
||||
|
||||
&.gems {
|
||||
color: $gems-color;
|
||||
color: $green-10;
|
||||
background-color: rgba(36, 204, 143, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $gold-color;
|
||||
color: $yellow-5;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
background-color: rgba(41, 149, 205, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.total {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
padding-top: 2px;
|
||||
margin-top: 4px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
@@ -287,62 +505,84 @@
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
color: $gray-50;
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
min-width: 6rem;
|
||||
margin-top: 16px;
|
||||
padding: 4px 16px;
|
||||
height: 32px;
|
||||
|
||||
&:focus {
|
||||
border: 2px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
.balance {
|
||||
width: 74px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
}
|
||||
.notEnough {
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
}
|
||||
.free-rebirth {
|
||||
background-color: $yellow-5;
|
||||
color: $white;
|
||||
height: 2rem;
|
||||
line-height: 16px;
|
||||
margin: auto -1rem -1rem;
|
||||
}
|
||||
|
||||
.notEnough {
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
// .pt-015 {
|
||||
// padding-top: 0.15rem;
|
||||
// }
|
||||
|
||||
.attributesGrid {
|
||||
margin-top: 8px;
|
||||
border-radius: 2px;
|
||||
background-color: $gray-500;
|
||||
|
||||
margin: 10px 0 24px;
|
||||
}
|
||||
|
||||
.gems-left {
|
||||
margin-top: .5em;
|
||||
height: 32px;
|
||||
background-color: $green-100;
|
||||
font-size: 0.75rem;
|
||||
margin-top: 24px;
|
||||
color: $green-1;
|
||||
width: 100%;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
|
||||
.free-rebirth {
|
||||
background-color: $yellow-5;
|
||||
.out-of-gems-banner {
|
||||
height: 32px;
|
||||
font-size: 0.75rem;
|
||||
margin-top: 24px;
|
||||
background-color: $yellow-100;
|
||||
color: $yellow-1;
|
||||
width: 100%;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
|
||||
.limitedTime {
|
||||
height: 32px;
|
||||
width: 446px;
|
||||
font-size: 0.75rem;
|
||||
margin: 24px 0 0 0;
|
||||
background-color: $purple-300;
|
||||
color: $white;
|
||||
height: 2rem;
|
||||
line-height: 16px;
|
||||
margin: auto -1rem -1rem;
|
||||
}
|
||||
|
||||
.pt-015 {
|
||||
padding-top: 0.15rem;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -370,6 +610,8 @@ import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgHourglasses from '@/assets/svg/hourglass.svg';
|
||||
import svgClock from '@/assets/svg/clock.svg';
|
||||
import svgWhiteClock from '@/assets/svg/clock-white.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
import BalanceInfo from './balanceInfo.vue';
|
||||
import PinBadge from '@/components/ui/pinBadge';
|
||||
@@ -377,6 +619,7 @@ import CountdownBanner from './countdownBanner';
|
||||
import currencyMixin from './_currencyMixin';
|
||||
import notifications from '@/mixins/notifications';
|
||||
import buyMixin from '@/mixins/buy';
|
||||
import numberIncrement from '@/components/shared/numberIncrement';
|
||||
|
||||
import { mapState } from '@/libs/store';
|
||||
|
||||
@@ -407,14 +650,17 @@ export default {
|
||||
Avatar,
|
||||
PinBadge,
|
||||
CountdownBanner,
|
||||
numberIncrement,
|
||||
},
|
||||
mixins: [buyMixin, currencyMixin, notifications, numberInvalid, spellsMixin],
|
||||
props: {
|
||||
// eslint-disable-next-line vue/require-default-prop
|
||||
item: {
|
||||
type: Object,
|
||||
},
|
||||
priceType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
withPin: {
|
||||
type: Boolean,
|
||||
@@ -433,10 +679,14 @@ export default {
|
||||
hourglasses: svgHourglasses,
|
||||
clock: svgClock,
|
||||
whiteClock: svgWhiteClock,
|
||||
positive: svgPositive,
|
||||
negative: svgNegative,
|
||||
}),
|
||||
|
||||
selectedAmountToBuy: 1,
|
||||
selectedAmount: 1,
|
||||
isPinned: false,
|
||||
quantity: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -474,6 +724,11 @@ export default {
|
||||
return planGemLimits.convCap
|
||||
+ this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
|
||||
},
|
||||
totalGems () {
|
||||
if (!this.user.purchased.plan) return 0;
|
||||
return planGemLimits.convCap
|
||||
+ this.user.purchased.plan.consecutive.gemCapExtra;
|
||||
},
|
||||
attemptingToPurchaseMoreGemsThanAreLeft () {
|
||||
if (this.item && this.item.key && this.item.key === 'gem' && this.selectedAmountToBuy > this.gemsLeft) return true;
|
||||
return false;
|
||||
@@ -490,6 +745,9 @@ export default {
|
||||
endDate () {
|
||||
return moment(this.item.event.end);
|
||||
},
|
||||
totalOwned () {
|
||||
return this.user.items[this.item.purchaseType][this.item.key] || 0;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
item: function itemChanged () {
|
||||
@@ -500,7 +758,9 @@ export default {
|
||||
methods: {
|
||||
onChange ($event) {
|
||||
this.$emit('change', $event);
|
||||
this.selectedAmountToBuy = 1;
|
||||
},
|
||||
|
||||
buyItem () {
|
||||
// @TODO: I think we should buying to the items.
|
||||
// Turn the items into classes, and use polymorphism
|
||||
@@ -597,6 +857,7 @@ export default {
|
||||
}
|
||||
},
|
||||
hideDialog () {
|
||||
this.selectedAmountToBuy = 1;
|
||||
this.$root.$emit('bv::hide::modal', 'buy-modal');
|
||||
},
|
||||
getPriceClass () {
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
.limitedTime {
|
||||
height: 32px;
|
||||
width: calc(100% + 30px);
|
||||
margin: 0 -15px; // the modal content has its own padding
|
||||
|
||||
font-size: 12px;
|
||||
line-height: 1.33;
|
||||
text-align: center;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
:hide-header="true"
|
||||
@change="onChange($event)"
|
||||
>
|
||||
<div class="close">
|
||||
<div>
|
||||
<span
|
||||
class="svg-icon inline icon-10"
|
||||
class="svg-icon close-icon icon-16 color"
|
||||
aria-hidden="true"
|
||||
@click="hideDialog()"
|
||||
v-html="icons.close"
|
||||
@@ -14,60 +14,73 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="item"
|
||||
class="content"
|
||||
class="content bordered-item"
|
||||
>
|
||||
<div class="inner-content">
|
||||
<item
|
||||
class="flat"
|
||||
class="flat bordered-item"
|
||||
:item="item"
|
||||
:item-content-class="itemContextToSell.itemClass"
|
||||
:show-popover="false"
|
||||
>
|
||||
<countBadge
|
||||
slot="itemBadge"
|
||||
:show="true"
|
||||
:count="itemContextToSell.itemCount"
|
||||
/>
|
||||
</item>
|
||||
/>
|
||||
<span class="owned">
|
||||
{{ $t('owned') }}: <span class="user-amount">{{ itemContextToSell.itemCount }}</span>
|
||||
</span>
|
||||
<h4 class="title">
|
||||
{{ itemContextToSell.itemName }}
|
||||
</h4>
|
||||
<div v-if="item.key === 'Saddle'">
|
||||
<div class="text">
|
||||
<div class="item-notes">
|
||||
{{ item.sellWarningNote() }}
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
<div class="text">
|
||||
<div class="item-notes">
|
||||
{{ item.notes() }}
|
||||
</div>
|
||||
<div>
|
||||
<b class="how-many-to-sell">{{ $t('howManyToSell') }}</b>
|
||||
<div class="item-cost">
|
||||
<span class="cost gold">
|
||||
<span
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons.gold"
|
||||
></span>
|
||||
<span>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<b-input
|
||||
v-model="selectedAmountToSell"
|
||||
class="itemsToSell"
|
||||
type="number"
|
||||
:max="itemContextToSell.itemCount"
|
||||
min="1"
|
||||
step="1"
|
||||
@keyup.native="preventNegative($event)"
|
||||
/>
|
||||
<span
|
||||
class="svg-icon inline icon-32"
|
||||
class="how-many-to-sell"
|
||||
>
|
||||
{{ $t('howManyToSell') }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<number-increment
|
||||
@updateQuantity="selectedAmountToSell = $event"
|
||||
/>
|
||||
</div>
|
||||
<div class="total-row">
|
||||
<span class="total-text">
|
||||
{{ $t('sendTotal') }}
|
||||
</span>
|
||||
<span
|
||||
class="svg-icon total icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons.gold"
|
||||
></span>
|
||||
<span class="value">{{ item.value }}</span>
|
||||
<span class="total-text gold">
|
||||
{{ item.value * selectedAmountToSell }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:disabled="selectedAmountToSell > itemContextToSell.itemCount"
|
||||
@click="sellItems()"
|
||||
>
|
||||
{{ $t('sell') }}
|
||||
{{ $t('sellItems') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,8 +90,10 @@
|
||||
slot="modal-footer"
|
||||
class="clearfix"
|
||||
>
|
||||
<span class="balance float-left">{{ $t('yourBalance') }}</span>
|
||||
<balanceInfo class="float-right" />
|
||||
<span class="user-balance float-left">{{ $t('yourBalance') }}</span>
|
||||
<balanceInfo
|
||||
class="float-right currency-totals"
|
||||
/>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
@@ -95,51 +110,13 @@
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 330px;
|
||||
width: 448px;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
.inner-content {
|
||||
margin: 33px auto auto;
|
||||
width: 282px;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
||||
margin-left: 24px;
|
||||
margin-right: 8px;
|
||||
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.value {
|
||||
width: 28px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: #df911e;
|
||||
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.balance {
|
||||
width: 74px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
.modal-body {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
@@ -148,29 +125,215 @@
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
margin: 24px 0 0;
|
||||
padding: 16px 24px;
|
||||
align-content: center;
|
||||
|
||||
.user-balance {
|
||||
width: 150px;
|
||||
height: 16px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.currency-totals {
|
||||
margin-right: -8px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.how-many-to-sell {
|
||||
margin-bottom: 16px;
|
||||
.content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
margin: 33px auto auto;
|
||||
width: 282px;
|
||||
}
|
||||
|
||||
.owned {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
background-color: $gray-600;
|
||||
padding: 8px 8px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
display: block;
|
||||
width: 141px;
|
||||
margin-left: 71px;
|
||||
margin-top: -48px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.user-amount {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
cursor: default;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
transform: scale(1.45, 1.45);
|
||||
top: -25px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $gray-10;
|
||||
font-size: 1.25rem;
|
||||
margin-top: 26px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.item-notes {
|
||||
margin-top: 12px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
// for cost icon of a single item
|
||||
span.svg-icon.inline.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
// for the total user cost
|
||||
span.svg-icon.total.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-left: 6px;
|
||||
margin-right: 8px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
span.svg-icon.icon-16 {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
color: $gray-200;
|
||||
stroke-width: 0px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $gray-100;
|
||||
}
|
||||
}
|
||||
|
||||
.item-cost {
|
||||
display: inline-flex;
|
||||
margin: 16px 0;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.cost {
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
padding: 6px 20px;
|
||||
line-height: 1.4;
|
||||
border-radius: 20px;
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.how-many-to-sell {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.number-increment {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 16px;
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
color: $gray-50;
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 16px;
|
||||
padding: 4px 16px;
|
||||
height: 32px;
|
||||
|
||||
&:focus {
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
.balance {
|
||||
width: 74px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import svgClose from '@/assets/svg/close.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
import BalanceInfo from '../balanceInfo.vue';
|
||||
import Item from '@/components/inventory/item';
|
||||
import CountBadge from '@/components/ui/countBadge';
|
||||
import numberIncrement from '@/components/shared/numberIncrement';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BalanceInfo,
|
||||
Item,
|
||||
CountBadge,
|
||||
numberIncrement,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -181,6 +344,8 @@ export default {
|
||||
close: svgClose,
|
||||
gold: svgGold,
|
||||
gem: svgGem,
|
||||
svgPositive,
|
||||
svgNegative,
|
||||
}),
|
||||
};
|
||||
},
|
||||
@@ -211,6 +376,10 @@ export default {
|
||||
this.selectedAmountToSell = 0;
|
||||
}
|
||||
},
|
||||
maxOwned () {
|
||||
const maxOwned = this.itemContextToSell.itemCount;
|
||||
return maxOwned;
|
||||
},
|
||||
sellItems () {
|
||||
if (!Number.isInteger(Number(this.selectedAmountToSell))) {
|
||||
this.selectedAmountToSell = 0;
|
||||
|
||||
@@ -33,6 +33,22 @@
|
||||
v-if="!item.locked"
|
||||
class="purchase-amount"
|
||||
>
|
||||
<div class="item-cost">
|
||||
<span
|
||||
class="cost"
|
||||
:class="priceType"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[priceType]"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
:class="priceType"
|
||||
>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="how-many-to-buy">
|
||||
<strong>{{ $t('howManyToBuy') }}</strong>
|
||||
</div>
|
||||
@@ -42,24 +58,25 @@
|
||||
>
|
||||
{{ item.addlNotes }}
|
||||
</div>
|
||||
<div class="box">
|
||||
<input
|
||||
v-model.number="selectedAmountToBuy"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
>
|
||||
<div>
|
||||
<number-increment
|
||||
@updateQuantity="selectedAmountToBuy = $event"
|
||||
/>
|
||||
</div>
|
||||
<div class="total-row">
|
||||
<span class="total-text">
|
||||
{{ $t('sendTotal') }}
|
||||
</span>
|
||||
<span
|
||||
class="svg-icon inline icon-20"
|
||||
aria-hidden="true"
|
||||
v-html="currencyIcon"
|
||||
></span>
|
||||
<span
|
||||
class="total"
|
||||
:class="priceType"
|
||||
>{{ item.value * selectedAmountToBuy }}</span>
|
||||
</div>
|
||||
<span
|
||||
class="svg-icon inline icon-32"
|
||||
aria-hidden="true"
|
||||
v-html="currencyIcon"
|
||||
></span>
|
||||
<span
|
||||
class="value"
|
||||
:class="priceType"
|
||||
>{{ item.value }}</span>
|
||||
</div>
|
||||
<button
|
||||
v-if="priceType === 'gems'
|
||||
@@ -72,7 +89,7 @@
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-primary"
|
||||
class="btn btn-primary mb-4"
|
||||
:class="{'notEnough': !enoughCurrency(priceType, item.value * selectedAmountToBuy)}"
|
||||
:disabled="numberInvalid"
|
||||
@click="buyItem()"
|
||||
@@ -112,6 +129,39 @@
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
padding: 16px 24px;
|
||||
align-content: center;
|
||||
|
||||
.user-balance {
|
||||
width: 150px;
|
||||
height: 16px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.currency-totals {
|
||||
margin-right: -8px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
margin-top: 8%;
|
||||
width: 448px !important;
|
||||
@@ -129,8 +179,13 @@
|
||||
margin: 33px auto auto;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-bottom: 0px;
|
||||
.item-notes {
|
||||
height: 48px;
|
||||
margin-top: 8px;
|
||||
padding-left: 48.5px;
|
||||
padding-right: 48.5px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.questInfo {
|
||||
@@ -152,16 +207,14 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
margin-top: 14px;
|
||||
padding: 4px 16px;
|
||||
height: 32px;
|
||||
|
||||
&:focus {
|
||||
border: 2px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
.balance {
|
||||
@@ -173,19 +226,6 @@
|
||||
color: $gray-200;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
padding: 1rem 1.5rem;
|
||||
|
||||
&> * {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.notEnough {
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
@@ -198,30 +238,108 @@
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.box {
|
||||
display: inline-block;
|
||||
width: 74px;
|
||||
height: 40px;
|
||||
border-radius: 2px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
margin-right: 24px;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
.item-cost {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
input::-webkit-contacts-auto-fill-button {
|
||||
visibility: hidden;
|
||||
display: none !important;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.cost {
|
||||
height: 40px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
padding: 8px 20px 8px 20px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
background-color: rgba(36, 204, 143, 0.15);
|
||||
line-height: 1.4;
|
||||
margin: 0 0 0 -4px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
line-height: 1.4;
|
||||
margin: 0 0 0 -4px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
background-color: rgba(41, 149, 205, 0.15);
|
||||
line-height: 1.4;
|
||||
margin: 0 0 0 -4px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.total {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 16px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
color: $gray-50;
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
height: 24px;
|
||||
line-height: 1.71;
|
||||
padding-right: 4px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-20 {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-24 {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.modal-dialog {
|
||||
max-width: 80%;
|
||||
@@ -234,9 +352,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<!-- <style lang="scss" scoped>
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.value {
|
||||
@@ -260,7 +379,7 @@
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style> -->
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
@@ -272,6 +391,8 @@ import svgExperience from '@/assets/svg/experience.svg';
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgHourglasses from '@/assets/svg/hourglass.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
import BalanceInfo from '../balanceInfo.vue';
|
||||
import currencyMixin from '../_currencyMixin';
|
||||
@@ -280,6 +401,7 @@ import buyMixin from '@/mixins/buy';
|
||||
import numberInvalid from '@/mixins/numberInvalid';
|
||||
import PinBadge from '@/components/ui/pinBadge';
|
||||
import CountdownBanner from '../countdownBanner';
|
||||
import numberIncrement from '@/components/shared/numberIncrement';
|
||||
|
||||
import questDialogContent from './questDialogContent';
|
||||
import QuestRewards from './questRewards';
|
||||
@@ -293,6 +415,7 @@ export default {
|
||||
PinBadge,
|
||||
questDialogContent,
|
||||
CountdownBanner,
|
||||
numberIncrement,
|
||||
},
|
||||
mixins: [buyMixin, currencyMixin, notifications, numberInvalid],
|
||||
props: {
|
||||
@@ -301,6 +424,7 @@ export default {
|
||||
},
|
||||
priceType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
withPin: {
|
||||
type: Boolean,
|
||||
@@ -312,9 +436,11 @@ export default {
|
||||
clock: svgClock,
|
||||
close: svgClose,
|
||||
experience: svgExperience,
|
||||
gem: svgGem,
|
||||
gems: svgGem,
|
||||
gold: svgGold,
|
||||
hourglass: svgHourglasses,
|
||||
hourglasses: svgHourglasses,
|
||||
positive: svgPositive,
|
||||
negative: svgNegative,
|
||||
}),
|
||||
|
||||
isPinned: false,
|
||||
@@ -339,8 +465,8 @@ export default {
|
||||
},
|
||||
currencyIcon () {
|
||||
if (this.priceType === 'gold') return this.icons.gold;
|
||||
if (this.priceType === 'hourglasses') return this.icons.hourglass;
|
||||
return this.icons.gem;
|
||||
if (this.priceType === 'hourglasses') return this.icons.hourglasses;
|
||||
return this.icons.gems;
|
||||
},
|
||||
endDate () {
|
||||
return moment(this.item.event.end);
|
||||
|
||||
@@ -33,17 +33,17 @@
|
||||
|
||||
h3 {
|
||||
color: $gray-10;
|
||||
margin-bottom: 0.25rem;
|
||||
margin-bottom: 4pxrem;
|
||||
}
|
||||
|
||||
.quest-image {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 16px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-bottom: 1rem;
|
||||
margin: 16px 16px;
|
||||
overflow-y: auto;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -54,10 +54,10 @@
|
||||
line-height: 1.71;
|
||||
color: $gray-50;
|
||||
text-align: center;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-bottom: 8px;
|
||||
|
||||
::v-deep .user-label {
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,9 +177,6 @@ export default {
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.quest-rewards {
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
|
||||
background-color: $gray-700;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,19 @@
|
||||
<br>
|
||||
<p class="text-center">
|
||||
<button
|
||||
id="buttonClearBrowserData"
|
||||
class="btn btn-lg btn-danger"
|
||||
popover-trigger="mouseover"
|
||||
:popover="$t('localStorageClearExplanation')"
|
||||
@click="clearLocalStorage()"
|
||||
>
|
||||
{{ $t('localStorageClear') }}
|
||||
</button>
|
||||
<b-popover
|
||||
target="buttonClearBrowserData"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('localStorageClearExplanation')"
|
||||
/>
|
||||
</p>
|
||||
<br>
|
||||
<p v-html="$t('localStorageTryNext', localStorageTryNext) "></p>
|
||||
|
||||
@@ -17,6 +17,19 @@
|
||||
class="faq-question"
|
||||
>
|
||||
<h2
|
||||
v-once
|
||||
v-if="index === 0"
|
||||
>
|
||||
{{ $t('general') }}
|
||||
</h2>
|
||||
<h2
|
||||
v-once
|
||||
v-if="entry.heading === 'party-with-friends'"
|
||||
id="parties"
|
||||
>
|
||||
{{ $t('parties') }}
|
||||
</h2>
|
||||
<h3
|
||||
v-once
|
||||
v-b-toggle="entry.heading"
|
||||
role="tab"
|
||||
@@ -24,7 +37,7 @@
|
||||
@click="handleClick($event)"
|
||||
>
|
||||
{{ entry.question }}
|
||||
</h2>
|
||||
</h3>
|
||||
<b-collapse
|
||||
:id="entry.heading"
|
||||
:visible="isVisible(entry.heading)"
|
||||
@@ -49,25 +62,36 @@
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.card-body {
|
||||
margin-bottom: 1em;
|
||||
h2 {
|
||||
color: #34313a;
|
||||
border-bottom: 1px solid #e1e0e3;
|
||||
margin-top: 24px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.faq-question h2 {
|
||||
cursor: pointer;
|
||||
}
|
||||
.faq-question {
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #4F2A93;
|
||||
}
|
||||
|
||||
.faq-question .card-body {
|
||||
padding: 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
line-height: 1.75;
|
||||
cursor: pointer;
|
||||
|
||||
.static-wrapper .faq-question h2 {
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.faq-question a {
|
||||
text-decoration: none;
|
||||
color: #4F2A93;
|
||||
.card-body {
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
|
||||
@@ -198,10 +198,6 @@
|
||||
color: $purple-200;
|
||||
}
|
||||
|
||||
li, p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.media img {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
@@ -521,7 +521,12 @@ export default {
|
||||
// Get Category Filter Labels
|
||||
this.typeFilters = getFilterLabels(this.type, this.challenge);
|
||||
// Set default filter for task column
|
||||
this.activateFilter(this.type);
|
||||
|
||||
if (this.challenge) {
|
||||
this.activateFilter(this.type);
|
||||
} else {
|
||||
this.activateFilter(this.type, this.user.preferences.tasks.activeFilter[this.type], true);
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.setColumnBackgroundVisibility();
|
||||
@@ -661,7 +666,7 @@ export default {
|
||||
taskSummary (task) {
|
||||
this.$emit('taskSummary', task);
|
||||
},
|
||||
activateFilter (type, filter = '') {
|
||||
activateFilter (type, filter = '', skipSave = false) {
|
||||
// Needs a separate API call as this data may not reside in store
|
||||
if (type === 'todo' && filter === 'complete2') {
|
||||
if (this.group && this.group._id) {
|
||||
@@ -677,14 +682,16 @@ export default {
|
||||
// as default filter for daily
|
||||
// and set the filter as 'due' only when the component first
|
||||
// loads and not on subsequent reloads.
|
||||
if (
|
||||
type === 'daily' && filter === '' && !this.challenge
|
||||
&& this.user.preferences.dailyDueDefaultView
|
||||
) {
|
||||
if (type === 'daily' && filter === '' && !this.challenge) {
|
||||
filter = 'due'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
this.activeFilter = getActiveFilter(type, filter, this.challenge);
|
||||
|
||||
if (!skipSave && !this.challenge) {
|
||||
const propertyToUpdate = `preferences.tasks.activeFilter.${type}`;
|
||||
this.$store.dispatch('user:set', { [propertyToUpdate]: filter });
|
||||
}
|
||||
},
|
||||
setColumnBackgroundVisibility () {
|
||||
this.$nextTick(() => {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'groupTask': task.group.id,
|
||||
'task-not-editable': !teamManagerAccess,
|
||||
'task-not-scoreable': showTaskLockIcon,
|
||||
'link-exempt': !isChallengeTask && !isGroupTask,
|
||||
}, `type_${task.type}`
|
||||
]"
|
||||
@click="castEnd($event, task)"
|
||||
@@ -31,6 +32,9 @@
|
||||
'task-not-scoreable': showTaskLockIcon,
|
||||
}, controlClass.up.inner]"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-label="$t('scoreUp')"
|
||||
:aria-disabled="showTaskLockIcon || (!task.up && !showTaskLockIcon)"
|
||||
@click="score('up')"
|
||||
@keypress.enter="score('up')"
|
||||
>
|
||||
@@ -62,6 +66,7 @@
|
||||
controlClass.inner,
|
||||
]"
|
||||
tabindex="0"
|
||||
role="checkbox"
|
||||
@click="score(showCheckIcon ? 'down' : 'up' )"
|
||||
@keypress.enter="score(showCheckIcon ? 'down' : 'up' )"
|
||||
>
|
||||
@@ -240,7 +245,7 @@
|
||||
>
|
||||
<div
|
||||
v-b-tooltip.hover.bottom="$t('dueDate')"
|
||||
class="svg-icon calendar"
|
||||
class="svg-icon calendar my-auto"
|
||||
v-html="icons.calendar"
|
||||
></div>
|
||||
<span>{{ formatDueDate() }}</span>
|
||||
@@ -358,6 +363,9 @@
|
||||
'task-not-scoreable': showTaskLockIcon,
|
||||
}, controlClass.down.inner]"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-label="$t('scoreDown')"
|
||||
:aria-disabled="showTaskLockIcon || (!task.down && !showTaskLockIcon)"
|
||||
@click="score('down')"
|
||||
@keypress.enter="score('down')"
|
||||
>
|
||||
@@ -700,7 +708,7 @@
|
||||
|
||||
.icons {
|
||||
margin-top: 4px;
|
||||
color: $gray-300;
|
||||
color: $gray-100;
|
||||
font-style: normal;
|
||||
|
||||
&-right {
|
||||
@@ -759,7 +767,7 @@
|
||||
}
|
||||
|
||||
.due-overdue {
|
||||
color: $red-50;
|
||||
color: $maroon-10;
|
||||
}
|
||||
|
||||
.calendar.svg-icon {
|
||||
@@ -898,7 +906,7 @@
|
||||
}
|
||||
</style>
|
||||
<!-- eslint-enable max-len -->
|
||||
|
||||
<!-- eslint-disable-next-line vue/component-tags-order -->
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
@@ -1125,13 +1133,13 @@ export default {
|
||||
return moment.duration(endOfDueDate.diff(endOfToday));
|
||||
},
|
||||
checkIfOverdue () {
|
||||
return this.calculateTimeTillDue().asDays() <= 0;
|
||||
return this.calculateTimeTillDue().asDays() < 0;
|
||||
},
|
||||
formatDueDate () {
|
||||
const timeTillDue = this.calculateTimeTillDue();
|
||||
const dueIn = timeTillDue.asDays() === 0 ? this.$t('today') : timeTillDue.humanize(true);
|
||||
|
||||
return this.task.date && this.$t('dueIn', { dueIn });
|
||||
if (moment().isSame(this.task.date, 'day')) {
|
||||
return this.$t('today');
|
||||
}
|
||||
return moment(this.task.date).format(this.user.preferences.dateFormat.toUpperCase());
|
||||
},
|
||||
edit (e, task) {
|
||||
if (this.isRunningYesterdailies) return;
|
||||
|
||||
@@ -110,7 +110,9 @@ export default {
|
||||
};
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
window.setTimeout(() => {
|
||||
this.handleExternalLinks();
|
||||
}, 500);
|
||||
},
|
||||
computed: {
|
||||
...mapState({ user: 'user.data' }),
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div
|
||||
class="modal-close"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<div
|
||||
class="svg-icon svg-close color"
|
||||
v-html="icons.close"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
cursor: pointer;
|
||||
|
||||
.svg-close {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
vertical-align: middle;
|
||||
opacity: 0.75;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import close from '@/assets/svg/close.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close,
|
||||
}),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -2,13 +2,13 @@
|
||||
<router-link
|
||||
v-if="displayName"
|
||||
v-b-tooltip.hover.top="tierTitle"
|
||||
class="leader user-link"
|
||||
class="leader user-link d-flex"
|
||||
:to="{'name': 'userProfile', 'params': {'userId': id}}"
|
||||
:class="levelStyle()"
|
||||
>
|
||||
{{ displayName }}
|
||||
<div
|
||||
class="svg-icon"
|
||||
class="svg-icon icon-12"
|
||||
v-html="tierIcon()"
|
||||
></div>
|
||||
</router-link>
|
||||
@@ -37,10 +37,15 @@
|
||||
color: $gray-50;
|
||||
}
|
||||
|
||||
&[class*="tier"] .svg-icon {
|
||||
margin-top: 5px;
|
||||
}
|
||||
&.npc .svg-icon {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
margin-left: .5em;
|
||||
margin-left: 6px;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
|
||||
@@ -190,14 +190,10 @@
|
||||
class="col-12 col-md-6"
|
||||
>
|
||||
<div class="row col-12 stats-column">
|
||||
<div class="col-12 col-md-4 attribute-label">
|
||||
<span
|
||||
class="hint"
|
||||
:popover-title="$t(statInfo.title)"
|
||||
popover-placement="right"
|
||||
:popover="$t(statInfo.popover)"
|
||||
popover-trigger="mouseenter"
|
||||
></span>
|
||||
<div
|
||||
:id="`${stat}-information`"
|
||||
class="col-12 col-md-4 attribute-label"
|
||||
>
|
||||
<div
|
||||
class="stat-title"
|
||||
:class="stat"
|
||||
@@ -206,6 +202,13 @@
|
||||
</div>
|
||||
<strong class="number">{{ totalStatPoints(stat) | floorWholeNumber }}</strong>
|
||||
</div>
|
||||
<b-popover
|
||||
:target="`${stat}-information`"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t(statInfo.popover)"
|
||||
/>
|
||||
<div class="col-12 col-md-6">
|
||||
<ul class="bonus-stats">
|
||||
<li>
|
||||
@@ -355,7 +358,7 @@ export default {
|
||||
},
|
||||
|
||||
allocateStatsList: {
|
||||
str: { title: 'allocateStr', popover: 'strengthText', allocatepop: 'allocateStrPop' },
|
||||
str: { title: 'allocateStr', popover: 'strText', allocatepop: 'allocateStrPop' },
|
||||
int: { title: 'allocateInt', popover: 'intText', allocatepop: 'allocateIntPop' },
|
||||
con: { title: 'allocateCon', popover: 'conText', allocatepop: 'allocateConPop' },
|
||||
per: { title: 'allocatePer', popover: 'perText', allocatepop: 'allocatePerPop' },
|
||||
@@ -364,7 +367,7 @@ export default {
|
||||
stats: {
|
||||
str: {
|
||||
title: 'strength',
|
||||
popover: 'strengthText',
|
||||
popover: 'strText',
|
||||
},
|
||||
int: {
|
||||
title: 'intelligence',
|
||||
|
||||
@@ -146,17 +146,19 @@
|
||||
:key="stat"
|
||||
class="row"
|
||||
>
|
||||
<div class="col-4">
|
||||
<span
|
||||
class="hint"
|
||||
:popover-title="$t(statInfo.title)"
|
||||
popover-placement="right"
|
||||
:popover="$t(statInfo.popover)"
|
||||
popover-trigger="mouseenter"
|
||||
>
|
||||
<strong>{{ $t(statInfo.title) }}</strong>
|
||||
</span>
|
||||
<div
|
||||
class="col-4"
|
||||
:id="statInfo.title"
|
||||
>
|
||||
<strong> {{ $t(statInfo.title)}} </strong>
|
||||
<strong>: {{ statsComputed[stat] }}</strong>
|
||||
<b-popover
|
||||
:target="statInfo.title"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t(statInfo.popover)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<ul class="bonus-stats">
|
||||
@@ -183,27 +185,38 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="user.stats.buffs.stealth">
|
||||
<div
|
||||
v-if="user.stats.buffs.stealth"
|
||||
id="stealthBuff"
|
||||
>
|
||||
<strong
|
||||
v-once
|
||||
class="hint"
|
||||
:popover-title="$t('stealth')"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('stealthNewDay')"
|
||||
>{{ $t('stealth') }}</strong>
|
||||
<strong>: {{ user.stats.buffs.stealth }} </strong>
|
||||
<b-popover
|
||||
target="stealthBuff"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('stealthNewDay')"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="user.stats.buffs.streaks">
|
||||
<div
|
||||
v-if="user.stats.buffs.streaks"
|
||||
id="streaksFrozenBuff"
|
||||
>
|
||||
<div>
|
||||
<strong
|
||||
class="hint"
|
||||
popover-title="$t('streaksFrozen')"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('streaksFrozenText')"
|
||||
></strong>
|
||||
{{ $t('streaksFrozen') }}
|
||||
<strong>
|
||||
{{ $t('streaksFrozen') }}
|
||||
</strong>
|
||||
<b-popover
|
||||
target="streaksFrozenBuff"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('streaksFrozenText')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -237,19 +250,27 @@
|
||||
>
|
||||
{{ $t('noMoreAllocate') }}
|
||||
</p>
|
||||
<p v-if="user.stats.points || userLevel100Plus">
|
||||
<p
|
||||
v-if="user.stats.points || userLevel100Plus"
|
||||
id="pointAllocation"
|
||||
>
|
||||
<strong class="inline">{{ user.stats.points }} </strong>
|
||||
<strong
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('levelPopover')"
|
||||
>{{ $t('unallocated') }}</strong>
|
||||
<strong> {{ $t('unallocated') }} </strong>
|
||||
<b-popover
|
||||
target="pointAllocation"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('levelPopover')"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<fieldset class="auto-allocate">
|
||||
<div class="checkbox">
|
||||
<div
|
||||
id="preferenceAutomaticAllocation"
|
||||
class="checkbox"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.automaticAllocation"
|
||||
@@ -259,19 +280,24 @@
|
||||
'preferences.allocationMode': 'taskbased'
|
||||
})"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('autoAllocationPop')"
|
||||
>{{ $t('autoAllocation') }}</span>
|
||||
<b-popover
|
||||
target="preferenceAutomaticAllocation"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('autoAllocationPop')"
|
||||
/>
|
||||
{{ $t('autoAllocation') }}
|
||||
</label>
|
||||
</div>
|
||||
<form
|
||||
v-if="user.preferences.automaticAllocation"
|
||||
style="margin-left:1em"
|
||||
>
|
||||
<div class="radio">
|
||||
<div
|
||||
id="optionFlatAllocation"
|
||||
class="radio"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.allocationMode"
|
||||
@@ -280,15 +306,22 @@
|
||||
value="flat"
|
||||
@change="set({'preferences.allocationMode': 'flat'})"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('evenAllocationPop')"
|
||||
>{{ $t('evenAllocation') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('evenAllocation') }}
|
||||
</span>
|
||||
<b-popover
|
||||
target="optionFlatAllocation"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('evenAllocationPop')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<div
|
||||
id="optionClassAllocation"
|
||||
class="radio"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.allocationMode"
|
||||
@@ -297,47 +330,63 @@
|
||||
value="classbased"
|
||||
@change="set({'preferences.allocationMode': 'classbased'})"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('classAllocationPop')"
|
||||
>{{ $t('classAllocation') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('classAllocation') }}
|
||||
</span>
|
||||
<b-popover
|
||||
target="optionClassAllocation"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('classAllocationPop')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<div
|
||||
id="optionTaskAllocation"
|
||||
class="radio"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.allocationMode"
|
||||
type="radio"
|
||||
name="allocationMode"
|
||||
value="taskbased"
|
||||
value="classbased"
|
||||
@change="set({'preferences.allocationMode': 'taskbased'})"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('taskAllocationPop')"
|
||||
>{{ $t('taskAllocation') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('taskAllocation') }}
|
||||
</span>
|
||||
<b-popover
|
||||
target="optionTaskAllocation"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('taskAllocationPop')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
v-if="user.preferences.automaticAllocation
|
||||
&& !(user.preferences.allocationMode === 'taskbased') && (user.stats.points > 0)"
|
||||
id="buttonDistributePoints"
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary btn-xs"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('distributePointsPop')"
|
||||
@click="allocateNow({})"
|
||||
>
|
||||
<span class="glyphicon glyphicon-download"></span>
|
||||
|
||||
{{ $t('distributePoints') }}
|
||||
</button>
|
||||
<b-popover
|
||||
target="buttonDistributePoints"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('distributePointsPop')"
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@@ -346,28 +395,35 @@
|
||||
:key="stat"
|
||||
class="row"
|
||||
>
|
||||
<div class="col-8">
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t(statInfo.popover)"
|
||||
></span>
|
||||
<div
|
||||
:id="`${stat}-info`"
|
||||
class="col-8"
|
||||
>
|
||||
{{ $t(statInfo.title) + user.stats[stat] }}
|
||||
<b-popover
|
||||
:target="`${stat}-info`"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t(statInfo.popover)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="user.stats.points"
|
||||
:id="`${stat}-allocate`"
|
||||
class="col-4"
|
||||
@click="allocate(stat)"
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t(statInfo.allocatepop)"
|
||||
>
|
||||
<button class="btn btn-primary">
|
||||
+
|
||||
</button>
|
||||
<b-popover
|
||||
:target="`${stat}-allocate`"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t(statInfo.allocatePop)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,7 @@ export default {
|
||||
}
|
||||
|
||||
if ((link.classList.value.indexOf('external-link') === -1)
|
||||
&& (!link.offsetParent || link.offsetParent.classList.value.indexOf('link-exempt') === -1)
|
||||
&& domainIndex !== 1
|
||||
&& !some(TRUSTED_DOMAINS.split(','), domain => link.href.indexOf(domain) === domainIndex)) {
|
||||
link.classList.add('external-link');
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
export default {
|
||||
computed: {
|
||||
numberInvalid () {
|
||||
return this.selectedAmountToBuy < 1 || !Number.isInteger(this.selectedAmountToBuy);
|
||||
const inputNumber = Number(this.selectedAmountToBuy);
|
||||
return inputNumber < 1
|
||||
|| !Number.isInteger(inputNumber);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -114,7 +114,7 @@ export default {
|
||||
this.castCancel();
|
||||
|
||||
// the selected member doesn't have the flags property which sets `cardReceived`
|
||||
if (spell.pinType !== 'card') {
|
||||
if (spell.pinType !== 'card' && spell.bulk !== true) {
|
||||
try {
|
||||
spell.cast(this.user, target, {});
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import * as Analytics from '@/libs/analytics';
|
||||
import getStore from '@/store';
|
||||
import handleRedirect from './handleRedirect';
|
||||
|
||||
@@ -72,13 +73,14 @@ const ItemsPage = () => import(/* webpackChunkName: "inventory" */'@/components/
|
||||
const EquipmentPage = () => import(/* webpackChunkName: "inventory" */'@/components/inventory/equipment/index');
|
||||
const StablePage = () => import(/* webpackChunkName: "inventory" */'@/components/inventory/stable/index');
|
||||
|
||||
// Guilds
|
||||
// Guilds & Parties
|
||||
const GuildIndex = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/index');
|
||||
const TavernPage = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/tavern');
|
||||
const MyGuilds = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/myGuilds');
|
||||
const GuildsDiscoveryPage = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/discovery');
|
||||
const GroupPage = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/group');
|
||||
const GroupPlansAppPage = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/groupPlan');
|
||||
const LookingForParty = () => import(/* webpackChunkName: "guilds" */ '@/components/groups/lookingForParty');
|
||||
|
||||
// Group Plans
|
||||
const GroupPlanIndex = () => import(/* webpackChunkName: "group-plans" */ '@/components/group-plans/index');
|
||||
@@ -157,6 +159,7 @@ const router = new VueRouter({
|
||||
],
|
||||
},
|
||||
{ name: 'party', path: '/party', component: GroupPage },
|
||||
{ name: 'lookingForParty', path: '/looking-for-party', component: LookingForParty },
|
||||
{ name: 'groupPlan', path: '/group-plans', component: GroupPlansAppPage },
|
||||
{
|
||||
name: 'groupPlanDetail',
|
||||
@@ -433,6 +436,19 @@ router.beforeEach(async (to, from, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (to.name === 'party') {
|
||||
router.app.$root.$emit('update-party');
|
||||
}
|
||||
|
||||
if (to.name === 'lookingForParty') {
|
||||
Analytics.track({
|
||||
hitType: 'event',
|
||||
eventName: 'View Find Members',
|
||||
eventAction: 'View Find Members',
|
||||
eventCategory: 'behavior',
|
||||
}, { trackOnClient: true });
|
||||
}
|
||||
|
||||
// Redirect old guild urls
|
||||
if (to.hash.indexOf('#/options/groups/guilds/') !== -1) {
|
||||
const splits = to.hash.split('/');
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import axios from 'axios';
|
||||
import { loadAsyncResource } from '@/libs/asyncResource';
|
||||
|
||||
export function getMembers (store, forceLoad = false) {
|
||||
@@ -23,3 +24,14 @@ export function getParty (store, forceLoad = false) {
|
||||
forceLoad,
|
||||
});
|
||||
}
|
||||
|
||||
export async function lookingForParty (store, payload) {
|
||||
let response;
|
||||
if (payload && payload.page) {
|
||||
response = await axios.get(`api/v4/looking-for-party?page=${payload.page}`);
|
||||
} else {
|
||||
response = await axios.get('api/v4/looking-for-party');
|
||||
}
|
||||
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,18 @@ describe('Task Column', () => {
|
||||
getters: {
|
||||
'tasks:getFilteredTaskList': () => [],
|
||||
},
|
||||
|
||||
state: {
|
||||
user: {
|
||||
data: {
|
||||
preferences: {
|
||||
tasks: {
|
||||
activeFilter: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mocks,
|
||||
stubs,
|
||||
@@ -76,7 +88,20 @@ describe('Task Column', () => {
|
||||
'tasks:getFilteredTaskList': () => () => habits,
|
||||
};
|
||||
|
||||
const store = new Store({ getters });
|
||||
const store = new Store({
|
||||
getters,
|
||||
state: {
|
||||
user: {
|
||||
data: {
|
||||
preferences: {
|
||||
tasks: {
|
||||
activeFilter: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
wrapper = makeWrapper({ store });
|
||||
});
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import moment from 'moment';
|
||||
|
||||
import Task from '@/components/tasks/task.vue';
|
||||
import Store from '@/libs/store';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Store);
|
||||
|
||||
describe('Task', () => {
|
||||
let wrapper;
|
||||
|
||||
function makeWrapper (additionalTaskData = {}, additionalUserData = {}) {
|
||||
return shallowMount(Task, {
|
||||
propsData: {
|
||||
task: {
|
||||
group: {},
|
||||
...additionalTaskData,
|
||||
},
|
||||
},
|
||||
store: {
|
||||
state: {
|
||||
user: {
|
||||
data: {
|
||||
preferences: {},
|
||||
...additionalUserData,
|
||||
},
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
'tasks:getTaskClasses': () => ({}),
|
||||
'tasks:canEdit': () => ({}),
|
||||
'tasks:canDelete': () => ({}),
|
||||
},
|
||||
},
|
||||
mocks: { $t: (key, params) => key + (params ? JSON.stringify(params) : '') },
|
||||
directives: { 'b-tooltip': {} },
|
||||
localVue,
|
||||
});
|
||||
}
|
||||
|
||||
it('returns a vue instance', () => {
|
||||
wrapper = makeWrapper();
|
||||
expect(wrapper.isVueInstance()).to.be.true;
|
||||
});
|
||||
|
||||
describe('Due date calculation', () => {
|
||||
let clock;
|
||||
|
||||
function setClockTo (time) {
|
||||
const now = moment(time);
|
||||
clock = sinon.useFakeTimers(now.toDate());
|
||||
return now;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
it('formats due date to today if due today', () => {
|
||||
const now = setClockTo('2019-09-17T17:57:00+02:00');
|
||||
wrapper = makeWrapper({ date: now });
|
||||
|
||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"today"}');
|
||||
});
|
||||
|
||||
it('formats due date to tomorrow if due tomorrow', () => {
|
||||
const now = setClockTo('2012-06-12T14:17:28Z');
|
||||
wrapper = makeWrapper({ date: now.add(1, 'day') });
|
||||
|
||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"in a day"}');
|
||||
});
|
||||
|
||||
it('formats due date to 5 days if due in 5 days', () => {
|
||||
const now = setClockTo();
|
||||
wrapper = makeWrapper({ date: now.add(5, 'days') });
|
||||
|
||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"in 5 days"}');
|
||||
});
|
||||
|
||||
it('formats due date to tomorrow if today but before dayStart', () => {
|
||||
const now = setClockTo('2019-06-12T04:23:37+02:00');
|
||||
wrapper = makeWrapper({ date: now.add(8, 'hours') }, { preferences: { dayStart: 7 } });
|
||||
|
||||
expect(wrapper.vm.formatDueDate()).to.equal('dueIn{"dueIn":"in a day"}');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"settings": "Settings",
|
||||
"language": "Language",
|
||||
"settings": "Налады",
|
||||
"language": "Мова",
|
||||
"americanEnglishGovern": "In the event of a discrepancy in the translations, the American English version governs.",
|
||||
"helpWithTranslation": "Would you like to help with the translation of Habitica? Great! Then visit <a href=\"/groups/guild/7732f64c-33ee-4cce-873c-fc28f147a6f7\">the Aspiring Linguists Guild</a>!",
|
||||
"stickyHeader": "Sticky header",
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -144,5 +144,11 @@
|
||||
"achievementBoneToPickText": "Hat alle klassischen und Quest-Skeletthaustiere ausgebrütet!",
|
||||
"achievementPolarProText": "Hat alle Standardfarben der Polar-Haustiere ausgebrütet: Bär, Fuchs, Pinguin, Wal und Wolf!",
|
||||
"achievementPolarPro": "Polar-Profi",
|
||||
"achievementPolarProModalText": "Du hast alle Polar-Haustiere gesammelt!"
|
||||
"achievementPolarProModalText": "Du hast alle Polar-Haustiere gesammelt!",
|
||||
"achievementPlantParent": "Pflanzenzüchter",
|
||||
"achievementPlantParentModalText": "Du hast alle Pflanzen-Haustiere gesammelt!",
|
||||
"achievementPlantParentText": "Hat alle Standardfarben der Pflanzen-Haustiere ausgebrütet: Kaktus und Baumchen!",
|
||||
"achievementDinosaurDynastyText": "Hat alle Standardfarben der Vogel- und Dinosaurier-Haustiere ausgebrütet: Falke, Eule, Papagei, Pinguin, Hahn, Flugfinger, T-Rex, Triceratops, und Velociraptor!",
|
||||
"achievementDinosaurDynastyModalText": "Du hast alle Vogel- und Dinosaurier-Haustiere gesammelt!",
|
||||
"achievementDinosaurDynasty": "Dinosaurier Dynastie"
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@
|
||||
"backgroundMysticalObservatoryNotes": "Deine Bestimmung steht in den Sternen; vom Mystischen Observatorium aus kannst Du sie lesen.",
|
||||
"backgroundMysticalObservatoryText": "Mystisches Observatorium",
|
||||
"backgrounds112020": "Set 78: Veröffentlicht im November 2020",
|
||||
"backgroundHolidayHearthNotes": "Entspanne, trockne und wärme Deine Glieder an einem Feierlichen Feuer.",
|
||||
"backgroundHolidayHearthNotes": "Entspanne, wärme und trockne deine Körperteile an einem Feierlichen Feuer.",
|
||||
"backgroundHolidayHearthText": "Feierliches Feuer",
|
||||
"backgroundInsideAnOrnamentNotes": "Lasse Deine Festtagsstimmung aus dem Inneren dieses Baumschmuckes erstrahlen.",
|
||||
"backgroundInsideAnOrnamentText": "Im Baumschmuck",
|
||||
@@ -756,5 +756,43 @@
|
||||
"backgroundSnowyTempleText": "Verschneiter Tempel",
|
||||
"backgroundSnowyTempleNotes": "Einen ruhigen verschneiten Tempel anschauen.",
|
||||
"backgroundSnowyVillageText": "Verschneites Dorf",
|
||||
"backgroundSnowyVillageNotes": "Ein verschneites Dorf bewundern."
|
||||
"backgroundSnowyVillageNotes": "Ein verschneites Dorf bewundern.",
|
||||
"backgroundOldTimeyBasketballCourtText": "Altmodischer Basketballplatz",
|
||||
"backgroundOldTimeyBasketballCourtNotes": "Wirf Körbe auf einem altmodischen Basketballplatz.",
|
||||
"backgroundJungleWateringHoleText": "Dschungel-Wasserstelle",
|
||||
"backgroundJungleWateringHoleNotes": "Halte inne, um von der Dschungelwasserstelle zu trinken.",
|
||||
"backgroundMangroveForestText": "Mangrovenwald",
|
||||
"backgroundMangroveForestNotes": "Erkunde den Rand des Mangrovenwaldes.",
|
||||
"backgrounds052023": "Set 108: Veröffentlicht im Mai 2023",
|
||||
"backgroundInAPaintingText": "In einem Gemälde",
|
||||
"backgroundInAPaintingNotes": "Genieße die kreative Aktivität in einem Gemälde.",
|
||||
"backgroundFlyingOverHedgeMazeText": "Fliegen über Heckenlabyrinth",
|
||||
"backgroundFlyingOverHedgeMazeNotes": "Staune beim Fliegen über ein Heckenlabyrinth.",
|
||||
"backgroundCretaceousForestNotes": "Erlebe das uralte Grün eines Kreidewaldes.",
|
||||
"backgroundCretaceousForestText": "Kreidewald",
|
||||
"backgrounds042023": "Set 107: Veröffentlicht im April 2023",
|
||||
"backgroundLeafyTreeTunnelText": "Blättriger Baumtunnel",
|
||||
"backgroundSpringtimeShowerText": "Frühlingsschauer",
|
||||
"backgroundSpringtimeShowerNotes": "Sieh einen blühenden Frühlingsschauer.",
|
||||
"backgroundUnderWisteriaText": "Unter der Glyzinize",
|
||||
"backgroundUnderWisteriaNotes": "Entspanne unter der Glyzinie.",
|
||||
"backgroundInFrontOfFountainText": "Vor einem Sprinnbrunnen",
|
||||
"backgroundInFrontOfFountainNotes": "Schnlendere vor einem Springbrunnen.",
|
||||
"backgroundFancyBedroomText": "Schickes Schlafzimmer",
|
||||
"backgroundWinterLakeWithSwansNotes": "Genieße die Natur am winterlichen See mit Schwänen.",
|
||||
"backgroundWinterLakeWithSwansText": "winterlicher See mit Schwänen",
|
||||
"backgrounds062023": "Set 109: Veröffentlicht im Juni 2023",
|
||||
"backgroundInAnAquariumNotes": "Schwimme ein paar friedliche Runden mit den Fischen im Aquarium.",
|
||||
"backgroundInsideAdventurersHideoutText": "Das Versteck eines Abenteurers",
|
||||
"backgroundCraterLakeText": "Kratersee",
|
||||
"backgroundCraterLakeNotes": "Bewundere einen schönen Kratersee.",
|
||||
"backgroundInsideACrystalText": "In einem Kristall",
|
||||
"backgroundFancyBedroomNotes": "Schwelge in einem schicken Schlafzimmer.",
|
||||
"backgroundLeafyTreeTunnelNotes": "Wandere durch den bläätrigen Baumtunnel.",
|
||||
"backgroundInAnAquariumText": "In einem Aquarium",
|
||||
"backgroundInsideAdventurersHideoutNotes": "Plane eine Reise in ein Abenteurerversteck.",
|
||||
"backgroundBirthdayBashNotes": "Habitica feiert eine Geburtstagsparty und alle sind eingeladen!",
|
||||
"eventBackgrounds": "Ereignis-Hintergründe",
|
||||
"backgroundBirthdayBashText": "Geburtstagsparty",
|
||||
"backgroundInsideACrystalNotes": "Schaue aus einem Kristall hinaus."
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
"commGuideHeadingWelcome": "Willkommen in Habitica!",
|
||||
"commGuidePara001": "Sei gegrüßt, Abenteurer! Willkommen in Habitica, dem Land der Produktivität, des gesunden Lebens und des gelegentlich randalierenden Greifs. Wir sind eine fröhliche Gemeinschaft voller hilfreicher Menschen, die sich auf ihrem Weg der persönlichen Entwicklung gegenseitig unterstützen. Alles was dazu gehört, ist eine positive Einstellung, ein respektvoller Umgang miteinander und etwas Verständnis dafür, dass jeder unterschiedliche Fähigkeiten und Grenzen hat - auch Du! Habiticaner gehen geduldig miteinander um und versuchen zu helfen, wo immer sie können.",
|
||||
"commGuidePara002": "Damit sich hier jeder sicher fühlen, glücklich und produktiv sein kann, gibt es ein paar Richtlinien. Wir haben uns große Mühe gegeben, sie möglichst nett und leicht verständlich zu formulieren. Bitte nimm Dir die Zeit, sie durchzulesen, bevor Du anfängst zu chatten.",
|
||||
"commGuidePara003": "Diese Regeln gelten an allen sozialen Orten, die wir verwenden, bezogen (aber nicht unbedingt eingeschränkt) auf Trello, GitHub, Weblate und dem Habitica Wiki auf Fandom. Wenn Gemeinschaften wachsen und sich verändern, passen sich manchmal ihre Regeln von Zeit zu Zeit an. Wenn es wesentliche Änderungen dieser Richtlinien gibt, wirst Du dies durch eine Bailey-Ankündigung und/oder in unseren sozialen Medien hören!",
|
||||
"commGuidePara003": "Diese Regeln gelten an allen sozialen Orten, die wir verwenden, einschließlich (aber nicht nur) Trello, GitHub, Weblate und des Habitica Wiki auf Fandom. Wenn Gemeinschaften wachsen und sich verändern, können sich ihre Regeln von Zeit zu Zeit ändern. Bei wesentlichen Änderungen dieser Richtlinien wirst Du durch eine Bailey-Ankündigung und/oder in unseren sozialen Medien davon erfahren!",
|
||||
"commGuideHeadingInteractions": "Interaktionen in Habitica",
|
||||
"commGuidePara015": "Habitica hat zwei Arten sozialer Orte: öffentliche und private. Öffentliche Orte sind die Taverne, öffentliche Gilden, GitHub, Trello und das Wiki. Private Orte sind private Gilden, der Partychat und private Nachrichten. Alle Anzeigenamen und @Usernamen müssen den Community-Richtlinien für öffentliche Orte entsprechen. Um Deinen Anzeigenamen oder @Usernamen zu ändern, wähle in der mobilen App Menü > Einstellungen > Profil. Und wähle auf der Webseite Benutzer Icon > Profil und klicke auf den \"Bearbeiten\"-Knopf.",
|
||||
"commGuidePara016": "Wenn Du Dich durch die öffentlichen Orte in Habitica bewegst, gibt es ein paar allgemeine Regeln, damit jeder sicher und glücklich ist.",
|
||||
"commGuideList02A": "<strong>Respektiert einander</strong>. Sei höflich, freundlich und hilfsbereit. Vergiss nicht: Habiticaner kommen aus den verschiedensten Hintergründen und haben sehr unterschiedliche Erfahrungen gemacht. Das macht Habitica so eigenartig! Es ist wichtig, dass man beim Aufbauen einer Community seine Unterschiede und Ähnlichkeiten respektieren, aber natürlich auch feiern kann.",
|
||||
"commGuideList02B": "<strong>Halte Dich an die <a href='/static/terms' target='_blank'>allgemeinen Geschäftsbedingungen</a></strong>, sowohl in öffentlichen als auch in privaten Umgebungen.",
|
||||
"commGuideList02B": "<strong>Halte Dich an die <a href='/static/terms' target='_blank'>allgemeinen Geschäftsbedingungen</a></strong>, sowohl in öffentlichen als auch in privaten Bereichen.",
|
||||
"commGuideList02C": "<strong>Poste keine Bilder oder Texte, die Gewalt darstellen, andere einschüchtern, oder eindeutig/indirekt sexuell sind, die Diskriminierung, Fanatismus, Rassismus, Sexismus, Hass, Belästigungen oder Hetze gegen jedwede Individuen oder Gruppen beinhalten.</strong> Auch nicht als Scherz oder Meme. Das bezieht sowohl Sprüche als auch Stellungnahmen mit ein. Nicht jeder hat den gleichen Humor, etwas, was Du als Witz wahrnimmst, kann für jemand anderen verletzend sein.",
|
||||
"commGuideList02D": "<strong>Halte die Diskussionen für alle Altersgruppen angemessen</strong>. Das heißt, Erwachsenenthemen in öffentlichen Bereichen zu vermeiden. Viele junge Habiticaner und Menschen mit verschiedenen Hintergründen nutzen diese Seite. Wir wollen unsere Gemeinschaft so angenehm und inklusiv wie möglich gestalten.",
|
||||
"commGuideList02E": "<strong>Vermeide vulgäre Ausdrücke. Dazu gehören auch mildere, religiöse Ausdrücke, die anderswo möglicherweise akzeptiert werden, oder verschleierte Schimpfwörter</strong>. Unter uns sind Menschen aus allen religiösen und kulturellen Hintergründen und wir wollen, dass sich alle im öffentlichen Raum wohl fühlen. <strong>Wenn Dir ein Moderator oder Mitarbeiter mitteilt, dass ein bestimmter Ausdruck in Habitica nicht erlaubt ist, selbst wenn er Dir vielleicht nicht problematisch vorkommt, ist diese Entscheidung endgültig</strong>. Zusätzlich werden verbale Angriffe jeder Art strenge Konsequenzen haben, da sie auch unsere Nutzungsbedingungen verletzen.",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -312,7 +312,7 @@
|
||||
"teamBasedTasksList": "Team-Based Task List",
|
||||
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
|
||||
"groupManagementControls": "Group Management Controls",
|
||||
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
|
||||
"inGameBenefits": "In-Game Benefits",
|
||||
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
|
||||
"inspireYourParty": "Inspire your party, gamify life together.",
|
||||
|
||||
@@ -147,5 +147,8 @@
|
||||
"achievementPolarProModalText": "You collected all the Polar Pets!",
|
||||
"achievementPlantParent": "Plant Parent",
|
||||
"achievementPlantParentText": "Has hatched all standard colors of Plant pets: Cactus and Treeling!",
|
||||
"achievementPlantParentModalText": "You collected all the Plant Pets!"
|
||||
"achievementPlantParentModalText": "You collected all the Plant Pets!",
|
||||
"achievementDinosaurDynasty": "Dinosaur Dynasty",
|
||||
"achievementDinosaurDynastyText": "Has hatched all standard colors of bird and dinosaur pets: Falcon, Owl, Parrot, Peacock, Penguin, Rooster, Pterodactyl, T-Rex, Triceratops, and Velociraptor!",
|
||||
"achievementDinosaurDynastyModalText": "You collected all the bird and dinosaur pets!"
|
||||
}
|
||||
|
||||
@@ -875,6 +875,30 @@
|
||||
"backgroundUnderWisteriaText": "Under Wisteria",
|
||||
"backgroundUnderWisteriaNotes": "Relax Under Wisteria.",
|
||||
|
||||
"backgrounds052023": "SET 108: Released May 2023",
|
||||
"backgroundInAPaintingText": "In A Painting",
|
||||
"backgroundInAPaintingNotes": "Enjoy creative pursuits Inside a Painting.",
|
||||
"backgroundFlyingOverHedgeMazeText": "Flying Over Hedge Maze",
|
||||
"backgroundFlyingOverHedgeMazeNotes": "Marvel while Flying over a Hedge Maze.",
|
||||
"backgroundCretaceousForestText": "Cretaceous Forest",
|
||||
"backgroundCretaceousForestNotes": "Take in the ancient greenery of a Cretaceous Forest.",
|
||||
|
||||
"backgrounds062023": "SET 109: Released June 2023",
|
||||
"backgroundInAnAquariumText": "In an Aquarium",
|
||||
"backgroundInAnAquariumNotes": "Take a peaceful swim with the fish In an Aquarium.",
|
||||
"backgroundInsideAdventurersHideoutText": "Inside an Adventurer's Hideout",
|
||||
"backgroundInsideAdventurersHideoutNotes": "Plan a journey inside an Adventurer's Hideout.",
|
||||
"backgroundCraterLakeText": "Crater Lake",
|
||||
"backgroundCraterLakeNotes": "Admire a lovely Crater Lake.",
|
||||
|
||||
"backgrounds072023": "SET 110: Released July 2023",
|
||||
"backgroundOnAPaddlewheelBoatText": "On a Paddlewheel Boat",
|
||||
"backgroundOnAPaddlewheelBoatNotes": "Ride on a Paddlewheel Boat.",
|
||||
"backgroundColorfulCoralText": "Colorful Coral",
|
||||
"backgroundColorfulCoralNotes": "Dive among Colorful Coral.",
|
||||
"backgroundBoardwalkIntoSunsetText": "Boardwalk into the Sunset",
|
||||
"backgroundBoardwalkIntoSunsetNotes": "Stroll on a Boardwalk into the Sunset.",
|
||||
|
||||
"timeTravelBackgrounds": "Steampunk Backgrounds",
|
||||
"backgroundAirshipText": "Airship",
|
||||
"backgroundAirshipNotes": "Become a sky sailor on board your very own Airship.",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user