Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 07e5bf1437 | |||
| d2ca738256 | |||
| f7983f39eb | |||
| 82d0e737a6 | |||
| f8213aaf1b | |||
| 2335ad4167 | |||
| 88f28188a1 | |||
| fce5be2e8f | |||
| 1d68cbfaa2 | |||
| a44222a350 | |||
| 4d2510e322 | |||
| 3b5ed33e03 | |||
| 0a6bf92b6b | |||
| 05ae40bc2e | |||
| 57e96ea092 | |||
| ea49b5b8e0 | |||
| 11a5de714a | |||
| f74b4d3e73 | |||
| ab6fdb99af | |||
| e3efa557dd | |||
| a6cea47789 | |||
| 5a200a88bd | |||
| 545499ea0b | |||
| 3e7f4229ec | |||
| 56d5f77b6e | |||
| efdf5a2e16 | |||
| add3a2887f | |||
| 0ed7c7596a | |||
| 55a452694f | |||
| cd4d5f83ff | |||
| 8220199e49 | |||
| bd1f6918ba | |||
| 5b21e62647 | |||
| 5e76d6df21 | |||
| 7348145b7d | |||
| ba2832d21f | |||
| 688f5084a1 | |||
| d5955b8889 | |||
| 01fd17ee3f | |||
| 979497dd35 | |||
| 1d3db244ba | |||
| 80ca074352 | |||
| 6d4f9e0759 | |||
| d096695559 | |||
| a2c8b8b05c | |||
| 8750701c08 | |||
| 900676bf0a | |||
| e219daf44c | |||
| 1b12a6b51f | |||
| 8441b0a3d6 | |||
| 0667695390 | |||
| 4d322c1bf6 | |||
| a855ddacc7 | |||
| 9d48ef7322 | |||
| 2991f7acfb | |||
| 9dbfb565bb | |||
| f42e22b58f | |||
| 95f3315796 | |||
| 18ab57eb91 | |||
| 0dcbd8ccb8 | |||
| ed82b46f7b | |||
| dcc3044685 | |||
| 5cd62d7052 | |||
| 5e232d8c9f | |||
| 13793f8b3c | |||
| 55f875f95a | |||
| 14576be374 | |||
| 4cb2c26475 | |||
| b66a0b76ef | |||
| dd313b17b5 | |||
| bb01475e02 | |||
| 757959529b | |||
| 71ad1957b1 | |||
| 3ba5ea1d2d | |||
| 902da35f2b | |||
| aaa16a9527 | |||
| b98e95ee45 | |||
| 757160d6b7 | |||
| 4cf68eb018 | |||
| e91d5e5664 | |||
| b9e12aca3e | |||
| 53ca9475ee | |||
| e212842b50 | |||
| d2f7cba43d | |||
| 84558f79d6 | |||
| 178e59f287 | |||
| 7acccc0763 | |||
| 8ac21d2fd4 | |||
| 7873800f87 | |||
| 727041f020 | |||
| de0c62a37f | |||
| 68f420991e | |||
| f211ebeb0a | |||
| b91ef9f539 | |||
| ac0601630e | |||
| 3239491144 | |||
| c3b0a73507 | |||
| b218eb2c00 | |||
| 37d9f76fea | |||
| 7f2e12ba23 | |||
| 2cbd78b139 | |||
| cc751960ac | |||
| 433c73c9d3 | |||
| 680c2162a7 | |||
| 1815d2b6d3 | |||
| 14cba76ba8 | |||
| 3d757c7814 | |||
| fd700f92ae | |||
| f41665f5a9 | |||
| 8b385c0b7b | |||
| 282f8db933 | |||
| 662b08c242 | |||
| b7e601be16 | |||
| 395676fcb1 | |||
| cc4df1c995 | |||
| 48eada2c37 |
@@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '8'
|
||||
- '10'
|
||||
services:
|
||||
- mongodb
|
||||
cache:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:8
|
||||
FROM node:10
|
||||
|
||||
ENV ADMIN_EMAIL admin@habitica.com
|
||||
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:8
|
||||
FROM node:10
|
||||
|
||||
# Install global packages
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
@@ -1,116 +1,81 @@
|
||||
{
|
||||
"PORT":3000,
|
||||
"ENABLE_CONSOLE_LOGS_IN_PROD":"false",
|
||||
"IP":"0.0.0.0",
|
||||
"WEB_CONCURRENCY":1,
|
||||
"BASE_URL":"http://localhost:3000",
|
||||
"FACEBOOK_KEY":"123456789012345",
|
||||
"FACEBOOK_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"GOOGLE_CLIENT_ID":"123456789012345",
|
||||
"GOOGLE_CLIENT_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API": {
|
||||
"CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"ACCESS_TOKEN":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"REFRESH_TOKEN":"aaaabbbbccccddddeeeeffff00001111"
|
||||
},
|
||||
"NODE_DB_URI":"mongodb://localhost/habitrpg",
|
||||
"TEST_DB_URI":"mongodb://localhost/habitrpg_test",
|
||||
"NODE_ENV":"development",
|
||||
"ENABLE_CONSOLE_LOGS_IN_TEST": "false",
|
||||
"CRON_SAFE_MODE":"false",
|
||||
"CRON_SEMI_SAFE_MODE":"false",
|
||||
"MAINTENANCE_MODE": "false",
|
||||
"SESSION_SECRET":"YOUR SECRET HERE",
|
||||
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
||||
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
||||
"ADMIN_EMAIL": "you@example.com",
|
||||
"SMTP_USER":"user@example.com",
|
||||
"SMTP_PASS":"password",
|
||||
"SMTP_SERVICE":"Gmail",
|
||||
"SMTP_HOST":"example.com",
|
||||
"SMTP_PORT": 587,
|
||||
"SMTP_TLS": true,
|
||||
"STRIPE_API_KEY":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"STRIPE_PUB_KEY":"22223333444455556666777788889999",
|
||||
"NEW_RELIC_LICENSE_KEY":"NEW_RELIC_LICENSE_KEY",
|
||||
"NEW_RELIC_NO_CONFIG_FILE":"true",
|
||||
"NEW_RELIC_APPLICATION_ID":"NEW_RELIC_APPLICATION_ID",
|
||||
"NEW_RELIC_API_KEY":"NEW_RELIC_API_KEY",
|
||||
"GA_ID": "GA_ID",
|
||||
"AMPLITUDE_KEY": "AMPLITUDE_KEY",
|
||||
"AMPLITUDE_SECRET": "AMPLITUDE_SECRET",
|
||||
"AMAZON_PAYMENTS": {
|
||||
"SELLER_ID": "SELLER_ID",
|
||||
"CLIENT_ID": "CLIENT_ID",
|
||||
"MWS_KEY": "",
|
||||
"MWS_SECRET": "",
|
||||
"MODE": "sandbox"
|
||||
},
|
||||
"FLAG_REPORT_EMAIL": "email@mod.com,email2@mod.com",
|
||||
"EMAIL_SERVER": {
|
||||
"url": "http://example.com",
|
||||
"authUser": "user",
|
||||
"authPassword": "password"
|
||||
},
|
||||
"S3":{
|
||||
"bucket":"bucket",
|
||||
"accessKeyId":"accessKeyId",
|
||||
"secretAccessKey":"secretAccessKey"
|
||||
},
|
||||
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
||||
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
||||
"PAYPAL":{
|
||||
"billing_plans": {
|
||||
"basic_earned":"basic_earned",
|
||||
"basic_3mo":"basic_3mo",
|
||||
"basic_6mo":"basic_6mo",
|
||||
"google_6mo":"google_6mo",
|
||||
"basic_12mo":"basic_12mo"
|
||||
},
|
||||
"mode":"sandbox",
|
||||
"client_id":"client_id",
|
||||
"client_secret":"client_secret",
|
||||
"experience_profile_id": ""
|
||||
},
|
||||
"IAP_GOOGLE_KEYDIR": "/path/to/google/public/key/dir/",
|
||||
"LOGGLY_TOKEN": "token",
|
||||
"LOGGLY_CLIENT_TOKEN": "token",
|
||||
"LOGGLY_ACCOUNT": "account",
|
||||
"PUSH_CONFIGS": {
|
||||
"GCM_SERVER_API_KEY": "",
|
||||
"APN_ENABLED": "false",
|
||||
"APN_KEY_ID": "xxxxxxxxxx",
|
||||
"APN_KEY": "xxxxxxxxxx",
|
||||
"APN_TEAM_ID": "aaabbbcccd",
|
||||
"FCM_SERVER_API_KEY": ""
|
||||
},
|
||||
"SITE_HTTP_AUTH": {
|
||||
"ENABLED": "false",
|
||||
"USERNAME": "admin",
|
||||
"PASSWORD": "password"
|
||||
},
|
||||
"SLACK": {
|
||||
"FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||
"SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id"
|
||||
},
|
||||
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"EMAILS" : {
|
||||
"COMMUNITY_MANAGER_EMAIL" : "admin@habitica.com",
|
||||
"TECH_ASSISTANCE_EMAIL" : "admin@habitica.com",
|
||||
"PRESS_ENQUIRY_EMAIL" : "admin@habitica.com"
|
||||
},
|
||||
"LOGGLY" : {
|
||||
"TOKEN" : "example-token",
|
||||
"SUBDOMAIN" : "exmaple-subdomain"
|
||||
},
|
||||
"KAFKA": {
|
||||
"GROUP_ID": "",
|
||||
"CLOUDKARAFKA_BROKERS": "",
|
||||
"CLOUDKARAFKA_USERNAME": "",
|
||||
"CLOUDKARAFKA_PASSWORD": "",
|
||||
"CLOUDKARAFKA_TOPIC_PREFIX": ""
|
||||
},
|
||||
"MIGRATION_CONNECT_STRING": "mongodb://localhost:27017/habitrpg?auto_reconnect=true"
|
||||
"ADMIN_EMAIL": "you@example.com",
|
||||
"AMAZON_PAYMENTS_CLIENT_ID": "CLIENT_ID",
|
||||
"AMAZON_PAYMENTS_MODE": "sandbox",
|
||||
"AMAZON_PAYMENTS_MWS_KEY": "MWS_KEY",
|
||||
"AMAZON_PAYMENTS_MWS_SECRET": "MWS_SECRET",
|
||||
"AMAZON_PAYMENTS_SELLER_ID": "SELLER_ID",
|
||||
"AMPLITUDE_KEY": "AMPLITUDE_KEY",
|
||||
"AMPLITUDE_SECRET": "AMPLITUDE_SECRET",
|
||||
"BASE_URL": "http://localhost:3000",
|
||||
"CRON_SAFE_MODE": "false",
|
||||
"CRON_SEMI_SAFE_MODE": "false",
|
||||
"DISABLE_REQUEST_LOGGING": "true",
|
||||
"EMAILS_COMMUNITY_MANAGER_EMAIL": "admin@habitica.com",
|
||||
"EMAILS_PRESS_ENQUIRY_EMAIL": "admin@habitica.com",
|
||||
"EMAILS_TECH_ASSISTANCE_EMAIL": "admin@habitica.com",
|
||||
"EMAIL_SERVER_AUTH_PASSWORD": "password",
|
||||
"EMAIL_SERVER_AUTH_USER": "user",
|
||||
"EMAIL_SERVER_URL": "http://example.com",
|
||||
"ENABLE_CONSOLE_LOGS_IN_PROD": "false",
|
||||
"ENABLE_CONSOLE_LOGS_IN_TEST": "false",
|
||||
"FACEBOOK_KEY": "123456789012345",
|
||||
"FACEBOOK_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"FLAG_REPORT_EMAIL": "email@example.com, email2@example.com",
|
||||
"GA_ID": "GA_ID",
|
||||
"GOOGLE_CLIENT_ID": "123456789012345",
|
||||
"GOOGLE_CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"IAP_GOOGLE_KEYDIR": "/path/to/google/public/key/dir/",
|
||||
"IGNORE_REDIRECT": "true",
|
||||
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"LOGGLY_CLIENT_TOKEN": "token",
|
||||
"LOGGLY_SUBDOMAIN": "example-subdomain",
|
||||
"LOGGLY_TOKEN": "example-token",
|
||||
"MAINTENANCE_MODE": "false",
|
||||
"NODE_DB_URI": "mongodb://localhost/habitrpg",
|
||||
"NODE_ENV": "development",
|
||||
"PATH": "bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin",
|
||||
"PAYPAL_BILLING_PLANS_basic_12mo": "basic_12mo",
|
||||
"PAYPAL_BILLING_PLANS_basic_3mo": "basic_3mo",
|
||||
"PAYPAL_BILLING_PLANS_basic_6mo": "basic_6mo",
|
||||
"PAYPAL_BILLING_PLANS_basic_earned": "basic_earned",
|
||||
"PAYPAL_BILLING_PLANS_google_6mo": "google_6mo",
|
||||
"PAYPAL_CLIENT_ID": "client_id",
|
||||
"PAYPAL_CLIENT_SECRET": "client_secret",
|
||||
"PAYPAL_EXPERIENCE_PROFILE_ID": "xp_profile_id",
|
||||
"PAYPAL_MODE": "sandbox",
|
||||
"PLAY_API_ACCESS_TOKEN": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API_CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API_CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API_REFRESH_TOKEN": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PORT": 3000,
|
||||
"PUSH_CONFIGS_APN_ENABLED": "false",
|
||||
"PUSH_CONFIGS_APN_KEY": "xxxxxxxxxx",
|
||||
"PUSH_CONFIGS_APN_KEY_ID": "xxxxxxxxxx",
|
||||
"PUSH_CONFIGS_APN_TEAM_ID": "aaabbbcccd",
|
||||
"PUSH_CONFIGS_FCM_SERVER_API_KEY": "aaabbbcccd",
|
||||
"S3_ACCESS_KEY_ID": "accessKeyId",
|
||||
"S3_BUCKET": "bucket",
|
||||
"S3_SECRET_ACCESS_KEY": "secretAccessKey",
|
||||
"SESSION_SECRET": "YOUR SECRET HERE",
|
||||
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
||||
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
||||
"SITE_HTTP_AUTH_ENABLED": "false",
|
||||
"SITE_HTTP_AUTH_PASSWORD": "password",
|
||||
"SITE_HTTP_AUTH_USERNAME": "admin",
|
||||
"SLACK_FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||
"SLACK_FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"SLACK_SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
||||
"SMTP_HOST": "example.com",
|
||||
"SMTP_PASS": "password",
|
||||
"SMTP_PORT": 587,
|
||||
"SMTP_SERVICE": "Gmail",
|
||||
"SMTP_TLS": "true",
|
||||
"SMTP_USER": "user@example.com",
|
||||
"STRIPE_API_KEY": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"STRIPE_PUB_KEY": "22223333444455556666777788889999",
|
||||
"TEST_DB_URI": "mongodb://localhost/habitrpg_test",
|
||||
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
||||
"WEB_CONCURRENCY": 1
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', (cb) => {
|
||||
|
||||
gulp.task('test:api:unit', (done) => {
|
||||
let runner = exec(
|
||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
||||
testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
||||
(err) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
@@ -180,12 +180,12 @@ gulp.task('test:api:unit', (done) => {
|
||||
});
|
||||
|
||||
gulp.task('test:api:unit:watch', () => {
|
||||
return gulp.watch(['website/server/libs/*', 'test/api/v3/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done()));
|
||||
return gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done()));
|
||||
});
|
||||
|
||||
gulp.task('test:api-v3:integration', (done) => {
|
||||
let runner = exec(
|
||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||
testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||
{maxBuffer: 500 * 1024},
|
||||
(err) => {
|
||||
if (err) {
|
||||
@@ -217,7 +217,7 @@ gulp.task('test:api-v3:integration:separate-server', (done) => {
|
||||
|
||||
gulp.task('test:api-v4:integration', (done) => {
|
||||
let runner = exec(
|
||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
|
||||
testBin('istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
|
||||
{maxBuffer: 500 * 1024},
|
||||
(err) => {
|
||||
if (err) {
|
||||
@@ -254,4 +254,4 @@ gulp.task('test:api-v3', gulp.series(
|
||||
'test:api:unit',
|
||||
'test:api-v3:integration',
|
||||
done => done()
|
||||
));
|
||||
));
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20181231_nye';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
import mongoose from 'mongoose';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {'flags.newStuff': true};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.head_special_nye2017 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2018'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2018',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2017'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2017',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2016'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2016',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2015'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2015',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2014'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2014',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else {
|
||||
set['items.gear.owned.head_special_nye'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
};
|
||||
|
||||
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],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -17,7 +17,7 @@ function setUpServer () {
|
||||
setUpServer();
|
||||
|
||||
// Replace this with your migration
|
||||
const processUsers = require('./users/20181122_turkey_day.js');
|
||||
const processUsers = require('./archive/2018/20181231_nye.js');
|
||||
processUsers()
|
||||
.then(function success () {
|
||||
process.exit(0);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* eslint-disable no-console */
|
||||
import { sendTxn } from '../../../website/server/libs/email';
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
import moment from 'moment';
|
||||
import nconf from 'nconf';
|
||||
const BASE_URL = nconf.get('BASE_URL');
|
||||
const EMAIL_SLUG = 'mandrill-email-slug'; // Set email template to send
|
||||
const MIGRATION_NAME = 'bulk-email';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
sendTxn(
|
||||
user,
|
||||
EMAIL_SLUG,
|
||||
[{name: 'BASE_URL', content: BASE_URL}] // Add variables from template
|
||||
);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: {migration: MIGRATION_NAME}}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: moment().subtract(2, 'weeks').toDate()}, // customize or remove to target different populations
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
auth: 1,
|
||||
preferences: 1,
|
||||
profile: 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],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = 'mystery_items_201811';
|
||||
const MYSTERY_ITEMS = ['head_mystery_201811', 'weapon_mystery_201811'];
|
||||
const MIGRATION_NAME = 'mystery_items_201812';
|
||||
const MYSTERY_ITEMS = ['headAccessory_mystery_201812', 'back_mystery_201812'];
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
import { model as UserNotification } from '../../website/server/models/userNotification';
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20181203_take_this';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.back_special_takeThis !== 'undefined') {
|
||||
push = false;
|
||||
} else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.back_special_takeThis'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.back_special_takeThis', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.body_special_takeThis'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_takeThis', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.head_special_takeThis'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_takeThis', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_takeThis'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_takeThis', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.weapon_special_takeThis'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', _id: uuid()}};
|
||||
} else {
|
||||
set['items.gear.owned.shield_special_takeThis'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.shield_special_takeThis', _id: uuid()}};
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (push) {
|
||||
return await User.update({_id: user._id}, {$set: set, $push: push}).exec();
|
||||
} else {
|
||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
challenges: '00708425-d477-41a5-bf27-6270466e7976',
|
||||
};
|
||||
|
||||
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],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "4.74.3",
|
||||
"version": "4.78.0",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@slack/client": "^3.8.1",
|
||||
@@ -33,7 +33,7 @@
|
||||
"compression": "^1.7.2",
|
||||
"cookie-session": "^1.2.0",
|
||||
"coupon-code": "^0.4.5",
|
||||
"cross-env": "^5.1.5",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^0.28.11",
|
||||
"csv-stringify": "^4.3.1",
|
||||
"cwait": "^1.1.1",
|
||||
@@ -80,7 +80,7 @@
|
||||
"ps-tree": "^1.0.0",
|
||||
"pug": "^2.0.3",
|
||||
"rimraf": "^2.4.3",
|
||||
"sass-loader": "^7.0.0",
|
||||
"sass-loader": "^7.0.3",
|
||||
"shelljs": "^0.8.2",
|
||||
"short-uuid": "^3.0.0",
|
||||
"smartbanner.js": "^1.9.1",
|
||||
@@ -90,7 +90,7 @@
|
||||
"svg-url-loader": "^2.3.2",
|
||||
"svgo": "^1.0.5",
|
||||
"svgo-loader": "^2.1.0",
|
||||
"universal-analytics": "^0.4.16",
|
||||
"universal-analytics": "^0.4.17",
|
||||
"update": "^0.7.4",
|
||||
"upgrade": "^1.1.0",
|
||||
"url-loader": "^1.0.0",
|
||||
@@ -107,15 +107,15 @@
|
||||
"vuedraggable": "^2.15.0",
|
||||
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",
|
||||
"webpack": "^3.12.0",
|
||||
"webpack-merge": "^4.0.0",
|
||||
"winston": "^2.4.2",
|
||||
"webpack-merge": "^4.1.3",
|
||||
"winston": "^2.4.3",
|
||||
"winston-loggly-bulk": "^2.0.2",
|
||||
"xml2js": "^0.4.4"
|
||||
},
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "^8.9.4",
|
||||
"npm": "^5.6.0"
|
||||
"node": "^10",
|
||||
"npm": "^6"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js,.vue .",
|
||||
@@ -144,13 +144,13 @@
|
||||
"apidoc": "gulp apidoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/test-utils": "^1.0.0-beta.16",
|
||||
"@vue/test-utils": "^1.0.0-beta.19",
|
||||
"babel-plugin-istanbul": "^4.1.6",
|
||||
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chalk": "^2.4.1",
|
||||
"chromedriver": "^2.38.3",
|
||||
"chromedriver": "^2.40.0",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"coveralls": "^3.0.1",
|
||||
"cross-spawn": "^6.0.5",
|
||||
@@ -164,7 +164,7 @@
|
||||
"expect.js": "^0.3.1",
|
||||
"http-proxy-middleware": "^0.19.0",
|
||||
"istanbul": "^1.1.0-alpha.1",
|
||||
"karma": "^3.0.0",
|
||||
"karma": "^3.1.3",
|
||||
"karma-babel-preprocessor": "^7.0.0",
|
||||
"karma-chai-plugins": "^0.9.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
@@ -180,7 +180,7 @@
|
||||
"mocha": "^5.1.1",
|
||||
"monk": "^6.0.6",
|
||||
"nightwatch": "^0.9.21",
|
||||
"puppeteer": "^1.4.0",
|
||||
"puppeteer": "^1.5.0",
|
||||
"require-again": "^2.0.0",
|
||||
"selenium-server": "^3.12.0",
|
||||
"sinon": "^6.3.5",
|
||||
@@ -190,8 +190,5 @@
|
||||
"webpack-dev-middleware": "^2.0.5",
|
||||
"webpack-hot-middleware": "^2.22.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"memwatch-next": "^0.3.0",
|
||||
"node-rdkafka": "^2.3.0"
|
||||
}
|
||||
"optionalDependencies": {}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,13 @@ async function _deleteAmplitudeData (userId, email) {
|
||||
if (response) console.log(`${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
async function _deleteHabiticaData (user) {
|
||||
async function _deleteHabiticaData (user, email) {
|
||||
await User.update(
|
||||
{_id: user._id},
|
||||
{$set: {
|
||||
'auth.local.passwordHashMethod': 'bcrypt',
|
||||
'auth.local.email': email,
|
||||
'auth.local.hashed_password': '$2a$10$QDnNh1j1yMPnTXDEOV38xOePEWFd4X8DSYwAM8XTmqmacG5X0DKjW',
|
||||
'auth.local.passwordHashMethod': 'bcrypt',
|
||||
}}
|
||||
);
|
||||
const response = await axios.delete(
|
||||
@@ -75,7 +76,7 @@ async function _processEmailAddress (email) {
|
||||
} else {
|
||||
for (const user of users) {
|
||||
await _deleteAmplitudeData(user._id, email); // eslint-disable-line no-await-in-loop
|
||||
await _deleteHabiticaData(user); // eslint-disable-line no-await-in-loop
|
||||
await _deleteHabiticaData(user, email); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,28 +12,27 @@ const nconf = require('nconf');
|
||||
const _ = require('lodash');
|
||||
const paypal = require('paypal-rest-sdk');
|
||||
const blocks = require('../website/common').content.subscriptionBlocks;
|
||||
const live = nconf.get('PAYPAL:mode') === 'live';
|
||||
const live = nconf.get('PAYPAL_MODE') === 'live';
|
||||
|
||||
nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json')));
|
||||
|
||||
let OP = 'create'; // list create update remove
|
||||
let OP = 'create'; // list get update create create-webprofile
|
||||
|
||||
paypal.configure({
|
||||
mode: nconf.get('PAYPAL:mode'), // sandbox or live
|
||||
client_id: nconf.get('PAYPAL:client_id'),
|
||||
client_secret: nconf.get('PAYPAL:client_secret'),
|
||||
mode: nconf.get('PAYPAL_MODE'), // sandbox or live
|
||||
client_id: nconf.get('PAYPAL_CLIENT_ID'),
|
||||
client_secret: nconf.get('PAYPAL_CLIENT_SECRET'),
|
||||
});
|
||||
|
||||
// https://developer.paypal.com/docs/api/#billing-plans-and-agreements
|
||||
let billingPlanTitle = 'Habitica Subscription';
|
||||
let billingPlanAttributes = {
|
||||
name: billingPlanTitle,
|
||||
description: billingPlanTitle,
|
||||
type: 'INFINITE',
|
||||
merchant_preferences: {
|
||||
auto_bill_amount: 'yes',
|
||||
cancel_url: live ? 'https://habitica.com' : 'http://localhost:3000',
|
||||
return_url: `${live ? 'https://habitica.com' : 'http://localhost:3000' }/paypal/subscribe/success`,
|
||||
return_url: `${live ? 'https://habitica.com' : 'http://localhost:3000'}/paypal/subscribe/success`,
|
||||
},
|
||||
payment_definitions: [{
|
||||
type: 'REGULAR',
|
||||
@@ -45,7 +44,7 @@ let billingPlanAttributes = {
|
||||
_.each(blocks, (block) => {
|
||||
block.definition = _.cloneDeep(billingPlanAttributes);
|
||||
_.merge(block.definition.payment_definitions[0], {
|
||||
name: `${billingPlanTitle } ($${block.price} every ${block.months} months, recurring)`,
|
||||
name: `${billingPlanTitle} ($${block.price} every ${block.months} months, recurring)`,
|
||||
frequency_interval: `${block.months}`,
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
@@ -63,7 +62,7 @@ switch (OP) {
|
||||
});
|
||||
break;
|
||||
case 'get':
|
||||
paypal.billingPlan.get(nconf.get('PAYPAL:billing_plans:12'), (err, plan) => {
|
||||
paypal.billingPlan.get(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), (err, plan) => {
|
||||
console.log({err, plan});
|
||||
});
|
||||
break;
|
||||
@@ -75,7 +74,7 @@ switch (OP) {
|
||||
cancel_url: 'https://habitica.com',
|
||||
},
|
||||
};
|
||||
paypal.billingPlan.update(nconf.get('PAYPAL:billing_plans:12'), updatePayload, (err, res) => {
|
||||
paypal.billingPlan.update(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), updatePayload, (err, res) => {
|
||||
console.log({err, plan: res});
|
||||
});
|
||||
break;
|
||||
@@ -101,9 +100,6 @@ switch (OP) {
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case 'remove': break;
|
||||
|
||||
case 'create-webprofile':
|
||||
let webexpinfo = {
|
||||
name: 'HabiticaProfile',
|
||||
@@ -116,4 +112,4 @@ switch (OP) {
|
||||
console.log(error, result);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ describe('payments/index', () => {
|
||||
await api.createSubscription(data);
|
||||
let msg = '\`Hello recipient, sender has sent you 3 months of subscription!\`';
|
||||
|
||||
expect(user.sendMessage).to.be.calledOnce;
|
||||
expect(user.sendMessage).to.be.calledTwice;
|
||||
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
|
||||
});
|
||||
|
||||
@@ -247,6 +247,77 @@ describe('payments/index', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
context('Winter 2018-19 Gift-1-Get-1 Promotion', async () => {
|
||||
it('creates a gift subscription for purchaser and recipient if none exist', async () => {
|
||||
await api.createSubscription(data);
|
||||
|
||||
expect(user.items.pets['Jackalope-RoyalPurple']).to.eql(5);
|
||||
expect(user.purchased.plan.customerId).to.eql('Gift');
|
||||
expect(user.purchased.plan.dateTerminated).to.exist;
|
||||
expect(user.purchased.plan.dateUpdated).to.exist;
|
||||
expect(user.purchased.plan.dateCreated).to.exist;
|
||||
|
||||
expect(recipient.items.pets['Jackalope-RoyalPurple']).to.eql(5);
|
||||
expect(recipient.purchased.plan.customerId).to.eql('Gift');
|
||||
expect(recipient.purchased.plan.dateTerminated).to.exist;
|
||||
expect(recipient.purchased.plan.dateUpdated).to.exist;
|
||||
expect(recipient.purchased.plan.dateCreated).to.exist;
|
||||
});
|
||||
|
||||
it('adds extraMonths to existing subscription for purchaser and creates a gift subscription for recipient without sub', async () => {
|
||||
user.purchased.plan = plan;
|
||||
|
||||
expect(user.purchased.plan.extraMonths).to.eql(0);
|
||||
|
||||
await api.createSubscription(data);
|
||||
|
||||
expect(user.purchased.plan.extraMonths).to.eql(3);
|
||||
|
||||
expect(recipient.items.pets['Jackalope-RoyalPurple']).to.eql(5);
|
||||
expect(recipient.purchased.plan.customerId).to.eql('Gift');
|
||||
expect(recipient.purchased.plan.dateTerminated).to.exist;
|
||||
expect(recipient.purchased.plan.dateUpdated).to.exist;
|
||||
expect(recipient.purchased.plan.dateCreated).to.exist;
|
||||
});
|
||||
|
||||
it('adds extraMonths to existing subscription for recipient and creates a gift subscription for purchaser without sub', async () => {
|
||||
recipient.purchased.plan = plan;
|
||||
|
||||
expect(recipient.purchased.plan.extraMonths).to.eql(0);
|
||||
|
||||
await api.createSubscription(data);
|
||||
|
||||
expect(recipient.purchased.plan.extraMonths).to.eql(3);
|
||||
|
||||
expect(user.items.pets['Jackalope-RoyalPurple']).to.eql(5);
|
||||
expect(user.purchased.plan.customerId).to.eql('Gift');
|
||||
expect(user.purchased.plan.dateTerminated).to.exist;
|
||||
expect(user.purchased.plan.dateUpdated).to.exist;
|
||||
expect(user.purchased.plan.dateCreated).to.exist;
|
||||
});
|
||||
|
||||
it('adds extraMonths to existing subscriptions for purchaser and recipient', async () => {
|
||||
user.purchased.plan = plan;
|
||||
recipient.purchased.plan = plan;
|
||||
|
||||
expect(user.purchased.plan.extraMonths).to.eql(0);
|
||||
expect(recipient.purchased.plan.extraMonths).to.eql(0);
|
||||
|
||||
await api.createSubscription(data);
|
||||
|
||||
expect(user.purchased.plan.extraMonths).to.eql(3);
|
||||
expect(recipient.purchased.plan.extraMonths).to.eql(3);
|
||||
});
|
||||
|
||||
it('sends a private message about the promotion', async () => {
|
||||
await api.createSubscription(data);
|
||||
let msg = '\`Hello sender, you received 3 months of subscription as part of our holiday gift-giving promotion!\`';
|
||||
|
||||
expect(user.sendMessage).to.be.calledTwice;
|
||||
expect(user.sendMessage).to.be.calledWith(user, { senderMsg: msg });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Purchasing a subscription for self', () => {
|
||||
|
||||
@@ -15,6 +15,7 @@ describe('checkout', () => {
|
||||
|
||||
function getPaypalCreateOptions (description, amount) {
|
||||
return {
|
||||
experience_profile_id: 'xp_profile_id',
|
||||
intent: 'sale',
|
||||
payer: { payment_method: 'Paypal' },
|
||||
redirect_urls: {
|
||||
|
||||
@@ -110,7 +110,7 @@ describe('slack', () => {
|
||||
});
|
||||
|
||||
it('noops if no flagging url is provided', () => {
|
||||
sandbox.stub(nconf, 'get').withArgs('SLACK:FLAGGING_URL').returns('');
|
||||
sandbox.stub(nconf, 'get').withArgs('SLACK_FLAGGING_URL').returns('');
|
||||
sandbox.stub(logger, 'error');
|
||||
let reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('messageCannotFlagSystemMessages', {communityManagerEmail: config.EMAILS.COMMUNITY_MANAGER_EMAIL}),
|
||||
message: t('messageCannotFlagSystemMessages', {communityManagerEmail: config.EMAILS_COMMUNITY_MANAGER_EMAIL}),
|
||||
});
|
||||
// let messages = await members[0].get(`/groups/${group._id}/chat`);
|
||||
// expect(messages[0].id).to.eql(skillMsg.id);
|
||||
|
||||
@@ -333,7 +333,7 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('inviteLimitReached', {techAssistanceEmail: nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL')}),
|
||||
message: t('inviteLimitReached', {techAssistanceEmail: nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL')}),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('POST /user/auth/local/login', () => {
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('accountSuspended', { communityManagerEmail: nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL'), userId: user._id }),
|
||||
message: t('accountSuspended', { communityManagerEmail: nconf.get('EMAILS_COMMUNITY_MANAGER_EMAIL'), userId: user._id }),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ describe('PUT /user/auth/update-email', () => {
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('cannotFulfillReq', { techAssistanceEmail: nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL') }),
|
||||
message: t('cannotFulfillReq', { techAssistanceEmail: nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL') }),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ setupNconf(configFile);
|
||||
// @TODO: Do we need? const CLIENT_VARS = ['language', 'isStaticPage', 'availableLanguages', 'translations',
|
||||
// 'FACEBOOK_KEY', 'GOOGLE_CLIENT_ID', 'NODE_ENV', 'BASE_URL', 'GA_ID',
|
||||
// 'AMAZON_PAYMENTS', 'STRIPE_PUB_KEY', 'AMPLITUDE_KEY',
|
||||
// 'worldDmg', 'mods', 'IS_MOBILE', 'PUSHER:KEY', 'PUSHER:ENABLED'];
|
||||
// 'worldDmg', 'mods', 'IS_MOBILE'];
|
||||
|
||||
const AMAZON_SELLER_ID = nconf.get('AMAZON_PAYMENTS:SELLER_ID') || nconf.get('AMAZON_PAYMENTS_SELLER_ID');
|
||||
const AMAZON_CLIENT_ID = nconf.get('AMAZON_PAYMENTS:CLIENT_ID') || nconf.get('AMAZON_PAYMENTS_CLIENT_ID');
|
||||
const AMAZON_MODE = nconf.get('AMAZON_PAYMENTS:MODE') || nconf.get('AMAZON_PAYMENTS_MODE');
|
||||
const AMAZON_SELLER_ID = nconf.get('AMAZON_PAYMENTS_SELLER_ID');
|
||||
const AMAZON_CLIENT_ID = nconf.get('AMAZON_PAYMENTS_CLIENT_ID');
|
||||
const AMAZON_MODE = nconf.get('AMAZON_PAYMENTS_MODE');
|
||||
|
||||
let env = {
|
||||
NODE_ENV: '"production"',
|
||||
@@ -30,13 +30,13 @@ let env = {
|
||||
MODE: `"${AMAZON_MODE}"`,
|
||||
},
|
||||
EMAILS: {
|
||||
COMMUNITY_MANAGER_EMAIL: `"${nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL')}"`,
|
||||
TECH_ASSISTANCE_EMAIL: `"${nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL')}"`,
|
||||
PRESS_ENQUIRY_EMAIL: `"${nconf.get('EMAILS:PRESS_ENQUIRY_EMAIL')}"`,
|
||||
COMMUNITY_MANAGER_EMAIL: `"${nconf.get('EMAILS_COMMUNITY_MANAGER_EMAIL')}"`,
|
||||
TECH_ASSISTANCE_EMAIL: `"${nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL')}"`,
|
||||
PRESS_ENQUIRY_EMAIL: `"${nconf.get('EMAILS_PRESS_ENQUIRY_EMAIL')}"`,
|
||||
},
|
||||
};
|
||||
|
||||
'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY GOOGLE_CLIENT_ID AMPLITUDE_KEY PUSHER:KEY PUSHER:ENABLED LOGGLY_CLIENT_TOKEN'
|
||||
'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY GOOGLE_CLIENT_ID AMPLITUDE_KEY LOGGLY_CLIENT_TOKEN'
|
||||
.split(' ')
|
||||
.forEach(key => {
|
||||
env[key] = `"${nconf.get(key)}"`;
|
||||
|
||||
@@ -11,22 +11,29 @@ div
|
||||
#app(:class='{"casting-spell": castingSpell}')
|
||||
banned-account-modal
|
||||
amazon-payments-modal(v-if='!isStaticPage')
|
||||
payments-success-modal
|
||||
snackbars
|
||||
router-view(v-if="!isUserLoggedIn || isStaticPage")
|
||||
template(v-else)
|
||||
template(v-if="isUserLoaded")
|
||||
div.resting-banner(v-show="showRestingBanner", ref="restingBanner")
|
||||
.resting-banner(v-show="showRestingBanner", ref="restingBanner")
|
||||
span.content
|
||||
span.label.d-inline.d-sm-none {{ $t('innCheckOutBannerShort') }}
|
||||
span.label.d-none.d-sm-inline {{ $t('innCheckOutBanner') }}
|
||||
span.separator |
|
||||
span.resume(@click="resumeDamage()") {{ $t('resumeDamage') }}
|
||||
div.closepadding(@click="hideBanner()")
|
||||
.closepadding(@click="hideBanner()")
|
||||
span.svg-icon.inline.icon-10(aria-hidden="true", v-html="icons.close")
|
||||
.g1g1-banner.d-flex.justify-content-center.align-items-center(v-if="!giftingHidden")
|
||||
.svg-icon.svg-gifts.left-gift(v-html="icons.gifts")
|
||||
router-link(:to="{name: 'subscription'}") {{ $t('g1g1Announcement') }}
|
||||
.svg-icon.svg-gifts.right-gift(v-html="icons.gifts")
|
||||
.closepadding(@click="hideGiftingBanner()")
|
||||
span.svg-icon.inline.icon-10(aria-hidden="true", v-html="icons.close")
|
||||
notifications-display
|
||||
app-menu(:class='{"restingInn": showRestingBanner}' :style="{ marginTop: bannerHeight + 'px' }")
|
||||
app-menu
|
||||
.container-fluid
|
||||
app-header(:class='{"restingInn": showRestingBanner}')
|
||||
app-header
|
||||
buyModal(
|
||||
:item="selectedItemToBuy || {}",
|
||||
:withPin="true",
|
||||
@@ -49,6 +56,13 @@ div
|
||||
<style lang='scss' scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
#app {
|
||||
height: calc(100% - 56px); /* 56px is the menu */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#loading-screen-inapp {
|
||||
#melior {
|
||||
margin: 0 auto;
|
||||
@@ -78,6 +92,46 @@ div
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
overflow-x: hidden;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.g1g1-banner {
|
||||
width: 100%;
|
||||
min-height: 2.5rem;
|
||||
background-color: #34b5c1;
|
||||
|
||||
a {
|
||||
color: $white;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.closepadding {
|
||||
margin: 11px 24px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.left-gift {
|
||||
margin: auto 1rem auto auto;
|
||||
}
|
||||
|
||||
.right-gift {
|
||||
margin: auto auto auto 1rem;
|
||||
filter: FlipH;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.svg-gifts {
|
||||
width: 4.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.notification {
|
||||
border-radius: 1000px;
|
||||
background-color: $green-10;
|
||||
@@ -88,42 +142,10 @@ div
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
overflow-x: hidden;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: calc(100% - 56px); /* 56px is the menu */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang='scss'>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
/* @TODO: The modal-open class is not being removed. Let's try this for now */
|
||||
.modal {
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
.modal-backdrop.show {
|
||||
opacity: .9 !important;
|
||||
background-color: $purple-100 !important;
|
||||
}
|
||||
|
||||
/* Push progress bar above modals */
|
||||
#nprogress .bar {
|
||||
z-index: 1600 !important; /* Must stay above nav bar */
|
||||
}
|
||||
|
||||
.resting-banner {
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
background-color: $blue-10;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 1300;
|
||||
display: flex;
|
||||
@@ -139,14 +161,10 @@ div
|
||||
.closepadding {
|
||||
margin: 11px 24px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
position: relative;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
|
||||
span svg path {
|
||||
stroke: $blue-500;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
@@ -169,6 +187,30 @@ div
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang='scss'>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.closepadding span svg path {
|
||||
stroke: #FFF;
|
||||
opacity: 0.48;
|
||||
}
|
||||
|
||||
/* @TODO: The modal-open class is not being removed. Let's try this for now */
|
||||
.modal {
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
.modal-backdrop.show {
|
||||
opacity: .9 !important;
|
||||
background-color: $purple-100 !important;
|
||||
}
|
||||
|
||||
/* Push progress bar above modals */
|
||||
#nprogress .bar {
|
||||
z-index: 1600 !important; /* Must stay above nav bar */
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import { loadProgressBar } from 'axios-progress-bar';
|
||||
@@ -185,8 +227,12 @@ import SelectMembersModal from 'client/components/selectMembersModal.vue';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
import { setup as setupPayments } from 'client/libs/payments';
|
||||
import amazonPaymentsModal from 'client/components/payments/amazonModal';
|
||||
import spellsMixin from 'client/mixins/spells';
|
||||
import paymentsSuccessModal from 'client/components/payments/successModal';
|
||||
|
||||
import spellsMixin from 'client/mixins/spells';
|
||||
import { CONSTANTS, getLocalSetting, removeLocalSetting, setLocalSetting } from 'client/libs/userlocalManager';
|
||||
|
||||
import gifts from 'assets/svg/gifts.svg';
|
||||
import svgClose from 'assets/svg/close.svg';
|
||||
import bannedAccountModal from 'client/components/bannedAccountModal';
|
||||
|
||||
@@ -205,11 +251,13 @@ export default {
|
||||
SelectMembersModal,
|
||||
amazonPaymentsModal,
|
||||
bannedAccountModal,
|
||||
paymentsSuccessModal,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close: svgClose,
|
||||
gifts,
|
||||
}),
|
||||
selectedItemToBuy: null,
|
||||
selectedSpellToBuy: null,
|
||||
@@ -221,6 +269,7 @@ export default {
|
||||
currentTipNumber: 0,
|
||||
bannerHidden: false,
|
||||
bannerHeight: 0,
|
||||
giftingHidden: getLocalSetting(CONSTANTS.keyConstants.GIFTING_BANNER_DISPLAY) === 'dismissed',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -418,14 +467,6 @@ export default {
|
||||
|
||||
this.hideLoadingScreen();
|
||||
|
||||
window.addEventListener('resize', this.setBannerOffset);
|
||||
// Adjust the positioning of the header banners
|
||||
this.$watch('showRestingBanner', () => {
|
||||
this.$nextTick(() => {
|
||||
this.setBannerOffset();
|
||||
});
|
||||
}, {immediate: true});
|
||||
|
||||
// Adjust the timezone offset
|
||||
if (this.user.preferences.timezoneOffset !== this.browserTimezoneOffset) {
|
||||
this.$store.dispatch('user:set', {
|
||||
@@ -433,6 +474,14 @@ export default {
|
||||
});
|
||||
}
|
||||
|
||||
let appState = getLocalSetting(CONSTANTS.savedAppStateValues.SAVED_APP_STATE);
|
||||
if (appState) {
|
||||
appState = JSON.parse(appState);
|
||||
if (appState.paymentCompleted) {
|
||||
removeLocalSetting(CONSTANTS.savedAppStateValues.SAVED_APP_STATE);
|
||||
this.$root.$emit('habitica:payment-success', appState);
|
||||
}
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
// Load external scripts after the app has been rendered
|
||||
setupPayments();
|
||||
@@ -452,7 +501,6 @@ export default {
|
||||
this.$root.$off('bv::show::modal');
|
||||
this.$root.$off('buyModal::showItem');
|
||||
this.$root.$off('selectMembersModal::showItem');
|
||||
window.removeEventListener('resize', this.setBannerOffset);
|
||||
},
|
||||
mounted () {
|
||||
// Remove the index.html loading screen and now show the inapp loading
|
||||
@@ -611,22 +659,14 @@ export default {
|
||||
},
|
||||
hideBanner () {
|
||||
this.bannerHidden = true;
|
||||
this.setBannerOffset();
|
||||
},
|
||||
hideGiftingBanner () {
|
||||
setLocalSetting(CONSTANTS.keyConstants.GIFTING_BANNER_DISPLAY, 'dismissed');
|
||||
this.giftingHidden = true;
|
||||
},
|
||||
resumeDamage () {
|
||||
this.$store.dispatch('user:sleep');
|
||||
},
|
||||
setBannerOffset () {
|
||||
let contentPlacement = 0;
|
||||
if (this.showRestingBanner && this.$refs.restingBanner !== undefined) {
|
||||
contentPlacement = this.$refs.restingBanner.clientHeight;
|
||||
}
|
||||
this.bannerHeight = contentPlacement;
|
||||
let smartBanner = document.getElementsByClassName('smartbanner')[0];
|
||||
if (smartBanner !== undefined) {
|
||||
smartBanner.style.top = `${contentPlacement}px`;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.achievement-costumeContest6x {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1136px -148px;
|
||||
background-position: -994px -233px;
|
||||
width: 144px;
|
||||
height: 156px;
|
||||
}
|
||||
@@ -10,65 +10,83 @@
|
||||
width: 480px;
|
||||
height: 360px;
|
||||
}
|
||||
.promo_animal_tails {
|
||||
.promo_armoire_backgrounds_201812 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -994px 0px;
|
||||
width: 141px;
|
||||
height: 441px;
|
||||
}
|
||||
.promo_armoire_backgrounds_201811 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -481px -420px;
|
||||
background-position: -481px -387px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_frost_potions {
|
||||
.promo_bird_buddies_bundle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -421px -723px;
|
||||
width: 417px;
|
||||
background-position: 0px -723px;
|
||||
width: 420px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_g1g1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -241px -871px;
|
||||
width: 237px;
|
||||
height: 150px;
|
||||
}
|
||||
.promo_ios {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -361px;
|
||||
width: 375px;
|
||||
height: 361px;
|
||||
}
|
||||
.promo_mystery_201811 {
|
||||
.promo_mystery_201812 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -839px -723px;
|
||||
width: 282px;
|
||||
height: 147px;
|
||||
background-position: -481px -209px;
|
||||
width: 393px;
|
||||
height: 177px;
|
||||
}
|
||||
.promo_oddballs_bundle {
|
||||
.promo_npc_alex {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -481px -568px;
|
||||
background-position: -994px -529px;
|
||||
width: 162px;
|
||||
height: 138px;
|
||||
}
|
||||
.promo_nye_card {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -994px -668px;
|
||||
width: 117px;
|
||||
height: 123px;
|
||||
}
|
||||
.promo_seasonal_shop {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -994px -390px;
|
||||
width: 162px;
|
||||
height: 138px;
|
||||
}
|
||||
.promo_snow_potions {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -481px -535px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_piyo {
|
||||
.promo_studying {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1136px 0px;
|
||||
width: 279px;
|
||||
height: 147px;
|
||||
background-position: -994px 0px;
|
||||
width: 220px;
|
||||
height: 232px;
|
||||
}
|
||||
.promo_take_this {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1281px -148px;
|
||||
background-position: -1112px -668px;
|
||||
width: 96px;
|
||||
height: 69px;
|
||||
}
|
||||
.promo_turkey_day_2018 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -723px;
|
||||
width: 420px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_veteran_pets {
|
||||
.promo_todos {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -871px;
|
||||
width: 363px;
|
||||
height: 141px;
|
||||
width: 240px;
|
||||
height: 195px;
|
||||
}
|
||||
.promo_winter_wonderland_2019 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -421px -723px;
|
||||
width: 402px;
|
||||
height: 147px;
|
||||
}
|
||||
.scene_nametag {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
@@ -76,15 +94,3 @@
|
||||
width: 512px;
|
||||
height: 208px;
|
||||
}
|
||||
.scene_sleep {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -481px -209px;
|
||||
width: 390px;
|
||||
height: 210px;
|
||||
}
|
||||
.scene_veteran_pets {
|
||||
background-image: url('~assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -1136px -305px;
|
||||
width: 242px;
|
||||
height: 62px;
|
||||
}
|
||||
|
||||
@@ -1,78 +1,144 @@
|
||||
.quest_TEMPLATE_FOR_MISSING_IMAGE {
|
||||
.quest_alligator {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -251px -1519px;
|
||||
width: 221px;
|
||||
height: 39px;
|
||||
}
|
||||
.quest_cow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -175px;
|
||||
width: 174px;
|
||||
background-position: -1540px -1079px;
|
||||
width: 201px;
|
||||
height: 213px;
|
||||
}
|
||||
.quest_dilatory {
|
||||
.quest_armadillo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px 0px;
|
||||
background-position: -1320px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatoryDistress1 {
|
||||
.quest_atom1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px -1085px;
|
||||
width: 210px;
|
||||
height: 210px;
|
||||
}
|
||||
.quest_dilatoryDistress2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -959px;
|
||||
width: 150px;
|
||||
background-position: -1094px -1332px;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_dilatoryDistress3 {
|
||||
.quest_atom2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -642px -1519px;
|
||||
width: 207px;
|
||||
height: 138px;
|
||||
}
|
||||
.quest_atom3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -211px -1519px;
|
||||
width: 216px;
|
||||
height: 180px;
|
||||
}
|
||||
.quest_axolotl {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_badger {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatory_derby {
|
||||
.quest_basilist {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1320px -660px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
background-position: -191px -1706px;
|
||||
width: 189px;
|
||||
height: 141px;
|
||||
}
|
||||
.quest_dustbunnies {
|
||||
.quest_beetle {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
background-position: -1322px -1112px;
|
||||
width: 204px;
|
||||
height: 201px;
|
||||
}
|
||||
.quest_egg {
|
||||
.quest_bunny {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -751px;
|
||||
width: 165px;
|
||||
height: 207px;
|
||||
background-position: 0px -1519px;
|
||||
width: 210px;
|
||||
height: 186px;
|
||||
}
|
||||
.quest_evilsanta {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1562px -1332px;
|
||||
width: 118px;
|
||||
height: 131px;
|
||||
}
|
||||
.quest_evilsanta2 {
|
||||
.quest_butterfly {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_falcon {
|
||||
.quest_cheetah {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_cow {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px 0px;
|
||||
width: 174px;
|
||||
height: 213px;
|
||||
}
|
||||
.quest_dilatory {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatoryDistress1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px -868px;
|
||||
width: 210px;
|
||||
height: 210px;
|
||||
}
|
||||
.quest_dilatoryDistress2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -573px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_dilatoryDistress3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dilatory_derby {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_dustbunnies {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_egg {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -214px;
|
||||
width: 165px;
|
||||
height: 207px;
|
||||
}
|
||||
.quest_evilsanta {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -724px;
|
||||
width: 118px;
|
||||
height: 131px;
|
||||
}
|
||||
.quest_evilsanta2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_falcon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_ferret {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px -452px;
|
||||
background-position: -1100px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
@@ -84,19 +150,19 @@
|
||||
}
|
||||
.quest_ghost_stag {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px -220px;
|
||||
background-position: 0px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_goldenknight1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px -440px;
|
||||
background-position: -220px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_goldenknight2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1311px -1332px;
|
||||
background-position: -1345px -1332px;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
}
|
||||
@@ -108,19 +174,19 @@
|
||||
}
|
||||
.quest_gryphon {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1322px -1112px;
|
||||
background-position: -660px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_guineapig {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px -672px;
|
||||
background-position: -1100px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_harpy {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px -672px;
|
||||
background-position: -1320px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
@@ -132,109 +198,109 @@
|
||||
}
|
||||
.quest_hippo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px -220px;
|
||||
background-position: -220px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_horse {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px -440px;
|
||||
background-position: -1320px -660px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_kangaroo {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px -660px;
|
||||
background-position: -1320px -880px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_kraken {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -877px -1332px;
|
||||
background-position: -443px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_lostMasterclasser1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -892px;
|
||||
background-position: -220px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_lostMasterclasser2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px -892px;
|
||||
background-position: -440px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_lostMasterclasser3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px -892px;
|
||||
background-position: -660px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_mayhemMistiflying1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -1261px;
|
||||
background-position: -1757px -422px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_mayhemMistiflying2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px -892px;
|
||||
background-position: -1100px -660px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_mayhemMistiflying3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1320px 0px;
|
||||
background-position: -880px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_monkey {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1320px -220px;
|
||||
background-position: -880px -440px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moon1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px -217px;
|
||||
background-position: -1540px -434px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
.quest_moon2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px 0px;
|
||||
background-position: -660px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moon3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1320px -880px;
|
||||
background-position: -660px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moonstone1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: 0px -1112px;
|
||||
background-position: -880px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moonstone2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -1112px;
|
||||
background-position: 0px -1112px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_moonstone3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px -1112px;
|
||||
background-position: -1320px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_nudibranch {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px -868px;
|
||||
background-position: -1540px 0px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
@@ -246,73 +312,73 @@
|
||||
}
|
||||
.quest_owl {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px -1112px;
|
||||
background-position: -440px -892px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_peacock {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px 0px;
|
||||
background-position: -1540px -217px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
.quest_penguin {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -567px;
|
||||
background-position: 0px -1706px;
|
||||
width: 190px;
|
||||
height: 183px;
|
||||
}
|
||||
.quest_pterodactyl {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1320px -440px;
|
||||
background-position: -660px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_rat {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px -892px;
|
||||
background-position: 0px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_rock {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px -434px;
|
||||
background-position: -1540px -651px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
.quest_rooster {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px 0px;
|
||||
background-position: -428px -1519px;
|
||||
width: 213px;
|
||||
height: 174px;
|
||||
}
|
||||
.quest_sabretooth {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: 0px -892px;
|
||||
background-position: 0px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_seaserpent {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1100px 0px;
|
||||
background-position: -660px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_sheep {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -440px -672px;
|
||||
background-position: -660px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_slime {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: 0px -672px;
|
||||
background-position: 0px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_sloth {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -880px 0px;
|
||||
background-position: -440px 0px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
@@ -324,79 +390,7 @@
|
||||
}
|
||||
.quest_snake {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px -1332px;
|
||||
background-position: -877px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_spider {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: 0px -1519px;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_squirrel {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: 0px -452px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_stoikalmCalamity1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -1412px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_stoikalmCalamity2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -660px -220px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_stoikalmCalamity3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_taskwoodsTerror1 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -1110px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.quest_taskwoodsTerror2 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1540px -651px;
|
||||
width: 216px;
|
||||
height: 216px;
|
||||
}
|
||||
.quest_taskwoodsTerror3 {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: 0px -232px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
.quest_treeling {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1094px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_trex {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -1757px -389px;
|
||||
width: 204px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_trex_undead {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -443px -1332px;
|
||||
width: 216px;
|
||||
height: 177px;
|
||||
}
|
||||
.quest_triceratops {
|
||||
background-image: url('~assets/images/sprites/spritesmith-main-11.png');
|
||||
background-position: -220px -672px;
|
||||
width: 219px;
|
||||
height: 219px;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 447 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 546 KiB After Width: | Height: | Size: 537 KiB |
|
Before Width: | Height: | Size: 500 KiB After Width: | Height: | Size: 519 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 394 KiB |
|
Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 270 KiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 185 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 120 KiB |
@@ -2,8 +2,8 @@
|
||||
// possible values are: normal, fall, habitoween, thanksgiving, winter, nye, birthday, valentines, spring, summer
|
||||
// more to be added on future seasons
|
||||
|
||||
$npc_market_flavor: 'normal';
|
||||
$npc_quests_flavor: 'normal';
|
||||
$npc_seasonal_flavor: 'normal';
|
||||
$npc_timetravelers_flavor: 'normal';
|
||||
$npc_tavern_flavor: 'normal';
|
||||
$npc_market_flavor: 'nye';
|
||||
$npc_quests_flavor: 'nye';
|
||||
$npc_seasonal_flavor: 'nye';
|
||||
$npc_timetravelers_flavor: 'winter';
|
||||
$npc_tavern_flavor: 'nye';
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="73" height="27" viewBox="0 0 73 27">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#8EEDF6" d="M4.333 9.757l2.166-.554-1.742-1.401-.554-2.166-1.401 1.742-2.166.554 1.742 1.4.554 2.167zM70.333 5.757l2.166-.554-1.742-1.401-.554-2.166-1.401 1.742-2.166.554 1.742 1.4.554 2.167zM37.147 5.518l2.573.428-1.202-2.315.428-2.574-2.315 1.202-2.574-.427 1.202 2.315-.427 2.573zM68.735 22.132l2.367 1.812.03-2.981 1.812-2.368-2.981-.03-2.368-1.812-.03 2.982-1.812 2.367zM33.676 23.656l1.839.305-.859-1.653.305-1.839-1.653.859-1.839-.305.859 1.653-.305 1.839zM10.695 25.362l.805 1.68.862-1.651 1.68-.804-1.651-.862-.804-1.681-.862 1.652-1.681.804z"/>
|
||||
<path fill="#F8F9F9" d="M21.862 9.542l5.914-1.585 2.219 8.28-5.914 1.584z"/>
|
||||
<path fill="#DDF3F3" d="M15.949 11.126l5.913-1.584 2.219 8.28-5.914 1.584z"/>
|
||||
<path fill="#FFA624" d="M20.68 9.859l1.182-.317 2.219 8.28-1.183.316z"/>
|
||||
<path fill="#FFBE5D" d="M21.862 9.542l1.183-.317 2.219 8.28-1.183.316z"/>
|
||||
<path fill="#EE9109" d="M22.581 16.955l1.183-.317.317 1.183-1.183.317zM20.68 9.859l1.182-.317.317 1.183-1.182.317z"/>
|
||||
<path fill="#C1E9E9" d="M15.949 11.126l4.73-1.267.318 1.183-4.732 1.267zM17.85 18.223l4.731-1.268.317 1.183-4.731 1.268z"/>
|
||||
<path fill="#DDF3F3" d="M23.045 9.225l4.731-1.268.317 1.183-4.73 1.268zM24.947 16.322l4.73-1.268.318 1.183-4.731 1.267z"/>
|
||||
<path fill="#FFA624" d="M23.764 16.638l1.183-.316.317 1.182-1.183.317zM21.862 9.542l1.183-.317.317 1.183-1.183.317z"/>
|
||||
<g>
|
||||
<path stroke="#FFA624" stroke-width="1.5" d="M21.737 3.348c-.295-1.038-1.009-2.02-2.008-2.204-1-.184-1.69.542-1.495 1.297.195.755.88.984 3.075 1.916.623.264.723.03.428-1.009z"/>
|
||||
<path stroke="#FFBE5D" stroke-width="1.5" d="M24.307 3.71c.57-.918 1.527-1.664 2.538-1.565 1.012.098 1.475.986 1.08 1.658-.396.671-1.117.703-3.484.994-.672.083-.703-.17-.134-1.088z"/>
|
||||
<path fill="#EE9109" d="M23.129 2.769c-1.968-.277-1.106 2.141-.317 2.252.79.111 2.285-1.976.317-2.252z"/>
|
||||
<path fill="#F8F9F9" d="M22.862 4.665l7.276 1.022-.511 3.638-7.276-1.022z"/>
|
||||
<path fill="#DDF3F3" d="M15.587 3.642l7.275 1.023-.51 3.638-7.276-1.023z"/>
|
||||
<path fill="#FFBE5D" d="M20.437 4.324l4.85.682-.51 3.638-4.85-.682z"/>
|
||||
<path fill="#FFA624" d="M20.437 4.324l2.425.341-.51 3.638-2.426-.341z"/>
|
||||
<path fill="#FFA624" d="M22.862 4.665l2.426.34-.17 1.213-2.426-.34z"/>
|
||||
<path fill="#EE9109" d="M20.437 4.324l2.425.341-.17 1.213-2.425-.341z"/>
|
||||
<path fill="#C1E9E9" d="M15.246 6.068l4.85.681-.17 1.213-4.85-.682z"/>
|
||||
<path fill="#DDF3F3" d="M24.947 7.431l4.85.682-.17 1.212-4.85-.681z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path stroke="#FFA624" stroke-width="1.5" d="M49.696 7.04c-.549-1.24-1.609-2.337-2.885-2.391-1.276-.054-2.007.969-1.632 1.874.374.905 1.266 1.071 4.16 1.847.822.22.905-.09.357-1.33z"/>
|
||||
<path stroke="#FFBE5D" stroke-width="1.5" d="M52.956 7.04c.548-1.24 1.609-2.337 2.885-2.391 1.276-.054 2.007.969 1.632 1.874-.374.905-1.266 1.071-4.16 1.847-.822.22-.905-.09-.357-1.33z"/>
|
||||
<path fill="#EE9109" d="M51.326 6.075c-2.497 0-1.002 2.858 0 2.858s2.497-2.858 0-2.858z"/>
|
||||
<path fill="#F8F9F9" d="M51.326 8.481h9.23v4.616h-9.23z"/>
|
||||
<path fill="#DDF3F3" d="M42.095 8.481h9.23v4.616h-9.23z"/>
|
||||
<path fill="#FFBE5D" d="M48.249 8.481h6.154v4.616h-6.154z"/>
|
||||
<path fill="#FFA624" d="M48.249 8.481h3.077v4.616h-3.077zM51.326 8.481h3.077v1.539h-3.077z"/>
|
||||
<path fill="#EE9109" d="M48.249 8.481h3.077v1.539h-3.077z"/>
|
||||
<path fill="#F8F9F9" d="M51.326 13.097h7.692v10.769h-7.692z"/>
|
||||
<path fill="#DDF3F3" d="M43.634 13.097h7.692v10.769h-7.692z"/>
|
||||
<path fill="#FFA624" d="M49.787 13.097h1.538v10.769h-1.538z"/>
|
||||
<path fill="#FFBE5D" d="M51.326 13.097h1.538v10.769h-1.538z"/>
|
||||
<path fill="#EE9109" d="M49.787 22.327h1.539v1.539h-1.539zM49.787 13.097h1.539v1.538h-1.539z"/>
|
||||
<path fill="#C1E9E9" d="M43.634 13.097h6.153v1.538h-6.153zM42.095 11.558h6.154v1.539h-6.154zM43.634 22.327h6.153v1.539h-6.153z"/>
|
||||
<path fill="#DDF3F3" d="M52.864 13.097h6.154v1.538h-6.154zM54.403 11.558h6.154v1.539h-6.154zM52.864 22.327h6.154v1.539h-6.154z"/>
|
||||
<path fill="#FFA624" d="M51.326 22.327h1.538v1.539h-1.538zM51.326 13.097h1.538v1.538h-1.538z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -164,30 +164,30 @@ export default {
|
||||
classGear (heroClass) {
|
||||
if (heroClass === 'rogue') {
|
||||
return {
|
||||
armor: 'armor_rogue_5',
|
||||
head: 'head_rogue_5',
|
||||
shield: 'shield_rogue_6',
|
||||
weapon: 'weapon_rogue_6',
|
||||
armor: 'armor_special_winter2019Rogue',
|
||||
head: 'head_special_winter2019Rogue',
|
||||
shield: 'shield_special_winter2019Rogue',
|
||||
weapon: 'weapon_special_winter2019Rogue',
|
||||
};
|
||||
} else if (heroClass === 'wizard') {
|
||||
return {
|
||||
armor: 'armor_wizard_5',
|
||||
head: 'head_wizard_5',
|
||||
weapon: 'weapon_wizard_6',
|
||||
armor: 'armor_special_winter2019Mage',
|
||||
head: 'head_special_winter2019Mage',
|
||||
weapon: 'weapon_special_winter2019Mage',
|
||||
};
|
||||
} else if (heroClass === 'healer') {
|
||||
return {
|
||||
armor: 'armor_healer_5',
|
||||
head: 'head_healer_5',
|
||||
shield: 'shield_healer_5',
|
||||
weapon: 'weapon_healer_6',
|
||||
armor: 'armor_special_winter2019Healer',
|
||||
head: 'head_special_winter2019Healer',
|
||||
shield: 'shield_special_winter2019Healer',
|
||||
weapon: 'weapon_special_winter2019Healer',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
armor: 'armor_warrior_5',
|
||||
head: 'head_warrior_5',
|
||||
shield: 'shield_warrior_5',
|
||||
weapon: 'weapon_warrior_6',
|
||||
armor: 'armor_special_winter2019Warrior',
|
||||
head: 'head_special_winter2019Warrior',
|
||||
shield: 'shield_special_winter2019Warrior',
|
||||
weapon: 'weapon_special_winter2019Warrior',
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
.quest(:class='`quest_${user.party.quest.completed}`')
|
||||
p(v-if='questData.completion && typeof questData.completion === "function"', v-html='questData.completion()')
|
||||
.quest-rewards.text-center
|
||||
h3 {{ $t('youReceived') }}
|
||||
h3(v-once) {{ $t('paymentYouReceived') }}
|
||||
questDialogDrops(:item="questData")
|
||||
.modal-footer
|
||||
button.btn.btn-primary(@click='setQuestCompleted()') {{ $t('ok') }}
|
||||
|
||||
@@ -298,7 +298,9 @@ export default {
|
||||
this.$emit('show-member-modal', memberId);
|
||||
},
|
||||
atHighlight (text) {
|
||||
const userRegex = new RegExp(`@(${this.user.auth.local.username}|${this.user.profile.name})(?:\\b)`, 'gi');
|
||||
const escapedDisplayName = escapeRegExp(this.user.profile.name);
|
||||
const escapedUsername = escapeRegExp(this.user.auth.local.username);
|
||||
const userRegex = new RegExp(`@(${escapedDisplayName}|${escapedUsername})(?:\\b)`, 'gi');
|
||||
const atRegex = new RegExp(/(?!\b)@[\w-]+/g);
|
||||
|
||||
if (userRegex.test(text)) {
|
||||
|
||||
@@ -141,7 +141,7 @@ export default {
|
||||
this.changePage(this.PAGES.PAY);
|
||||
},
|
||||
pay (paymentMethod) {
|
||||
const subscriptionKey = 'group_monthly'; // @TODO: Get from content API?
|
||||
const subscriptionKey = 'group_monthly';
|
||||
let paymentData = {
|
||||
subscription: subscriptionKey,
|
||||
coupon: null,
|
||||
@@ -149,6 +149,7 @@ export default {
|
||||
|
||||
if (this.upgradingGroup && this.upgradingGroup._id) {
|
||||
paymentData.groupId = this.upgradingGroup._id;
|
||||
paymentData.group = this.upgradingGroup;
|
||||
} else {
|
||||
paymentData.groupToCreate = this.newGroup;
|
||||
}
|
||||
|
||||
@@ -1,100 +1,61 @@
|
||||
<template lang="pug">
|
||||
b-modal#create-party-modal(title="Empty", size='lg', hide-footer=true)
|
||||
b-modal#create-party-modal(size='lg', hide-footer=true)
|
||||
.header-wrap(slot="modal-header")
|
||||
.quest_screen
|
||||
.row.heading
|
||||
.col-12.text-center
|
||||
h2(v-once) {{$t('playInPartyTitle')}}
|
||||
p(v-once) {{$t('playInPartyDescription')}}
|
||||
.col-12.text-center.pr-5.pl-5
|
||||
h2(v-once) {{ $t('playInPartyTitle') }}
|
||||
p.mb-4(v-once) {{ $t('playInPartyDescription') }}
|
||||
button.btn.btn-primary(v-once, @click='createParty()') {{ $t('createParty') }}
|
||||
.row.grey-row
|
||||
.col-6.text-center
|
||||
.start-party
|
||||
h3(v-once) {{$t('startYourOwnPartyTitle')}}
|
||||
p(v-once) {{$t('startYourOwnPartyDescription')}}
|
||||
button.btn.btn-primary(v-once, @click='createParty()') {{$t('createParty')}}
|
||||
.col-6
|
||||
div.text-center
|
||||
.join-party
|
||||
h3(v-once) {{$t('wantToJoinPartyTitle')}}
|
||||
p(v-once) {{$t('wantToJoinPartyDescription')}}
|
||||
button.btn.btn-primary(v-once, @click='shareUserId()') {{$t('shartUserId')}}
|
||||
.share-userid-options(v-if="shareUserIdShown")
|
||||
.option-item(@click='copyUserId()')
|
||||
.svg-icon(v-html="icons.copy")
|
||||
input(type="text", v-model="user._id", id="userIdInput")
|
||||
| Copy User ID
|
||||
//.option-item(v-once)
|
||||
.svg-icon(v-html="icons.greyBadge")
|
||||
| {{$t('lookingForGroup')}}
|
||||
//.option-item(v-once)
|
||||
.svg-icon(v-html="icons.qrCode")
|
||||
| {{$t('qrCode')}}
|
||||
//.option-item(v-once)
|
||||
.svg-icon.facebook(v-html="icons.facebook")
|
||||
| Facebook
|
||||
//.option-item(v-once)
|
||||
.svg-icon(v-html="icons.twitter")
|
||||
| Twitter
|
||||
.col-12.text-center
|
||||
.join-party
|
||||
h2(v-once) {{ $t('wantToJoinPartyTitle') }}
|
||||
p(v-html='$t("wantToJoinPartyDescription")')
|
||||
.form-group(@click='copyUsername')
|
||||
.d-flex.align-items-center
|
||||
label.mr-3(v-once) {{ $t('username') }}
|
||||
.flex-grow-1
|
||||
.input-group-prepend.input-group-text @
|
||||
.text {{ user.auth.local.username }}
|
||||
.svg-icon.copy-icon(v-html='icons.copy')
|
||||
.small(v-once) {{ $t('copy') }}
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#create-party-modal .modal-body {
|
||||
padding: 0rem 0.75rem;
|
||||
}
|
||||
|
||||
#create-party-modal .modal-dialog {
|
||||
width: 684px;
|
||||
width: 35.75rem;
|
||||
}
|
||||
|
||||
#create-party-modal .modal-header {
|
||||
padding: 0;
|
||||
border-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
.heading {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
.copy-icon {
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
.header-wrap {
|
||||
padding: 0;
|
||||
color: #4e4a57;
|
||||
width: 100%;
|
||||
|
||||
.quest_screen {
|
||||
background-image: url('~client/assets/images/quest_screen.png');
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
height: 246px;
|
||||
margin-bottom: .5em;
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #4f2a93;
|
||||
}
|
||||
.form-control[readonly] {
|
||||
background-color: $white;
|
||||
color: $gray-50;
|
||||
}
|
||||
|
||||
.start-party {
|
||||
background-image: url('~client/assets/images/basilist@3x.png');
|
||||
background-size: cover;
|
||||
width: 122px;
|
||||
height: 69px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.join-party {
|
||||
background-image: url('~client/assets/images/party@3x.png');
|
||||
background-size: cover;
|
||||
width: 203px;
|
||||
height: 66px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
.form-group {
|
||||
background-color: $gray-600;
|
||||
border-radius: 2px;
|
||||
border: solid 1px $gray-500;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.grey-row {
|
||||
@@ -104,97 +65,130 @@ b-modal#create-party-modal(title="Empty", size='lg', hide-footer=true)
|
||||
border-radius: 0px 0px 2px 2px;
|
||||
}
|
||||
|
||||
.share-userid-options {
|
||||
background-color: $white;
|
||||
border-radius: 2px;
|
||||
width: 220px;
|
||||
position: absolute;
|
||||
top: 9em;
|
||||
left: 4.8em;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
h2 {
|
||||
color: $gray-100;
|
||||
}
|
||||
|
||||
#userIdInput {
|
||||
position: absolute;
|
||||
left: 1000rem;
|
||||
.header-wrap {
|
||||
padding: 0;
|
||||
color: #4e4a57;
|
||||
width: 100%;
|
||||
|
||||
.quest_screen {
|
||||
background-image: url('~client/assets/images/group@3x.png');
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
height: 246px;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 2px 2px 0 0;
|
||||
image-rendering: optimizequality;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
padding: 1em;
|
||||
|
||||
.svg-icon {
|
||||
margin-right: .5em;
|
||||
width: 20px;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.facebook svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.option-item:hover {
|
||||
background-color: $header-color;
|
||||
h2 {
|
||||
color: $purple-200;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
border: 0px;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
.input-group-prepend {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.input-group-text {
|
||||
background-color: $white;
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
color: $gray-300;
|
||||
padding: 0rem 0.1rem 0rem 0.75rem;
|
||||
}
|
||||
|
||||
.join-party {
|
||||
background-image: url('~client/assets/images/party.png');
|
||||
background-size: cover;
|
||||
width: 203px;
|
||||
height: 66px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
label {
|
||||
color: $gray-100;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0rem;
|
||||
margin-left: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-dialog .text {
|
||||
min-height: 1rem;
|
||||
margin: 0.75rem auto 0.75rem 0.25rem;
|
||||
}
|
||||
|
||||
.small {
|
||||
color: $gray-200;
|
||||
margin: auto 0.5rem auto 0.25rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'client/libs/store';
|
||||
import * as Analytics from 'client/libs/analytics';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import * as Analytics from 'client/libs/analytics';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
import copyIcon from 'assets/svg/copy.svg';
|
||||
import greyBadgeIcon from 'assets/svg/grey-badge.svg';
|
||||
import qrCodeIcon from 'assets/svg/qrCode.svg';
|
||||
import facebookIcon from 'assets/svg/facebook.svg';
|
||||
import twitterIcon from 'assets/svg/twitter.svg';
|
||||
import copyIcon from 'assets/svg/copy.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
copy: copyIcon,
|
||||
greyBadge: greyBadgeIcon,
|
||||
qrCode: qrCodeIcon,
|
||||
facebook: facebookIcon,
|
||||
twitter: twitterIcon,
|
||||
}),
|
||||
shareUserIdShown: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
shareUserId () {
|
||||
this.shareUserIdShown = !this.shareUserIdShown;
|
||||
},
|
||||
async createParty () {
|
||||
let group = {
|
||||
type: 'party',
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
copy: copyIcon,
|
||||
}),
|
||||
};
|
||||
group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
||||
let party = await this.$store.dispatch('guilds:create', {group});
|
||||
this.$store.state.party.data = party;
|
||||
this.user.party._id = party._id;
|
||||
|
||||
Analytics.updateUser({
|
||||
partyID: party._id,
|
||||
partySize: 1,
|
||||
});
|
||||
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
this.$router.push('/party');
|
||||
},
|
||||
copyUserId () {
|
||||
const copyText = document.getElementById('userIdInput');
|
||||
copyText.select();
|
||||
document.execCommand('copy');
|
||||
alert('User ID has been copied');
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
},
|
||||
};
|
||||
methods: {
|
||||
async createParty () {
|
||||
let group = {
|
||||
type: 'party',
|
||||
};
|
||||
group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
||||
let party = await this.$store.dispatch('guilds:create', {group});
|
||||
this.$store.state.party.data = party;
|
||||
this.user.party._id = party._id;
|
||||
|
||||
Analytics.updateUser({
|
||||
partyID: party._id,
|
||||
partySize: 1,
|
||||
});
|
||||
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
this.$router.push('/party');
|
||||
},
|
||||
copyUsername () {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(this.user.auth.local.username);
|
||||
} else {
|
||||
let copyText = document.createElement('textarea');
|
||||
copyText.value = this.user.auth.local.username;
|
||||
document.body.appendChild(copyText);
|
||||
copyText.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(copyText);
|
||||
}
|
||||
this.text(this.$t('usernameCopied'));
|
||||
},
|
||||
},
|
||||
mixins: [notifications],
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -395,14 +395,15 @@ export default {
|
||||
this.changePage(this.PAGES.PAY);
|
||||
},
|
||||
pay (paymentMethod) {
|
||||
let subscriptionKey = 'group_monthly'; // @TODO: Get from content API?
|
||||
let paymentData = {
|
||||
const subscriptionKey = 'group_monthly'; // @TODO: Get from content API?
|
||||
const paymentData = {
|
||||
subscription: subscriptionKey,
|
||||
coupon: null,
|
||||
};
|
||||
|
||||
if (this.upgradingGroup && this.upgradingGroup._id) {
|
||||
paymentData.groupId = this.upgradingGroup._id;
|
||||
paymentData.group = this.upgradingGroup;
|
||||
} else {
|
||||
paymentData.groupToCreate = this.newGroup;
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<template lang="pug">
|
||||
.row
|
||||
.col
|
||||
h1.page-header Page
|
||||
p {{ $route.path }}
|
||||
</template>
|
||||
@@ -33,8 +33,11 @@
|
||||
import * as Analytics from 'client/libs/analytics';
|
||||
import axios from 'axios';
|
||||
import { mapState } from 'client/libs/store';
|
||||
import { CONSTANTS, setLocalSetting } from 'client/libs/userlocalManager';
|
||||
import pick from 'lodash/pick';
|
||||
|
||||
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
|
||||
const habiticaUrl = `${location.protocol}//${location.host}`;
|
||||
|
||||
export default {
|
||||
data () {
|
||||
@@ -54,6 +57,8 @@ export default {
|
||||
OffAmazonPayments: {},
|
||||
isAmazonSetup: false,
|
||||
amazonButtonEnabled: false,
|
||||
groupToCreate: null, // creating new group
|
||||
group: null, // upgrading existing group
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -186,6 +191,45 @@ export default {
|
||||
|
||||
new this.OffAmazonPayments.Widgets.Wallet(walletParams).bind('AmazonPayWallet');
|
||||
},
|
||||
storePaymentStatusAndReload (url) {
|
||||
let paymentType;
|
||||
|
||||
if (this.amazonPayments.type === 'single' && !this.amazonPayments.gift) paymentType = 'gems';
|
||||
if (this.amazonPayments.type === 'subscription') paymentType = 'subscription';
|
||||
if (this.amazonPayments.groupId || this.amazonPayments.groupToCreate) paymentType = 'groupPlan';
|
||||
if (this.amazonPayments.type === 'single' && this.amazonPayments.gift && this.amazonPayments.giftReceiver) {
|
||||
paymentType = this.amazonPayments.gift.type === 'gems' ? 'gift-gems' : 'gift-subscription';
|
||||
}
|
||||
|
||||
const appState = {
|
||||
paymentMethod: 'amazon',
|
||||
paymentCompleted: true,
|
||||
paymentType,
|
||||
};
|
||||
if (paymentType === 'subscription') {
|
||||
appState.subscriptionKey = this.amazonPayments.subscription;
|
||||
} else if (paymentType === 'groupPlan') {
|
||||
appState.subscriptionKey = this.amazonPayments.subscription;
|
||||
|
||||
if (this.amazonPayments.groupToCreate) {
|
||||
appState.newGroup = true;
|
||||
appState.group = pick(this.amazonPayments.groupToCreate, ['_id', 'memberCount', 'name']);
|
||||
} else {
|
||||
appState.newGroup = false;
|
||||
appState.group = pick(this.amazonPayments.group, ['_id', 'memberCount', 'name']);
|
||||
}
|
||||
} else if (paymentType.indexOf('gift-') === 0) {
|
||||
appState.gift = this.amazonPayments.gift;
|
||||
appState.giftReceiver = this.amazonPayments.giftReceiver;
|
||||
}
|
||||
|
||||
setLocalSetting(CONSTANTS.savedAppStateValues.SAVED_APP_STATE, JSON.stringify(appState));
|
||||
if (url) {
|
||||
window.location.assign(url);
|
||||
} else {
|
||||
window.location.reload(true);
|
||||
}
|
||||
},
|
||||
async amazonCheckOut () {
|
||||
this.amazonButtonEnabled = false;
|
||||
|
||||
@@ -201,12 +245,11 @@ export default {
|
||||
});
|
||||
|
||||
this.$set(this, 'amazonButtonEnabled', true);
|
||||
this.reset();
|
||||
// @TODO: What are we syncing?
|
||||
window.location.reload(true);
|
||||
this.storePaymentStatusAndReload();
|
||||
} catch (e) {
|
||||
console.error(e); // eslint-disable-line no-console
|
||||
this.$set(this, 'amazonButtonEnabled', true);
|
||||
this.amazonPaymentsreset();
|
||||
this.reset();
|
||||
}
|
||||
} else if (this.amazonPayments.type === 'subscription') {
|
||||
let url = '/amazon/subscribe';
|
||||
@@ -231,8 +274,6 @@ export default {
|
||||
if (newGroup && newGroup._id) {
|
||||
// Handle new user signup
|
||||
if (!this.$store.state.isUserLoggedIn) {
|
||||
const habiticaUrl = `${location.protocol}//${location.host}`;
|
||||
|
||||
Analytics.track({
|
||||
hitType: 'event',
|
||||
eventCategory: 'group-plans-static',
|
||||
@@ -240,23 +281,21 @@ export default {
|
||||
eventLabel: 'paid-with-amazon',
|
||||
});
|
||||
|
||||
location.href = `${habiticaUrl}/group-plans/${newGroup._id}/task-information?showGroupOverview=true`;
|
||||
this.storePaymentStatusAndReload(`${habiticaUrl}/group-plans/${newGroup._id}/task-information?showGroupOverview=true`);
|
||||
return;
|
||||
}
|
||||
|
||||
// @TODO: Just append? or $emit?
|
||||
this.$router.push(`/group-plans/${newGroup._id}/task-information`);
|
||||
this.user.guilds.push(newGroup._id);
|
||||
this.storePaymentStatusAndReload(`${habiticaUrl}/group-plans/${newGroup._id}/task-information`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.amazonPayments.groupId) {
|
||||
this.$router.push(`/group-plans/${this.amazonPayments.groupId}/task-information`);
|
||||
this.storePaymentStatusAndReload(`${habiticaUrl}/group-plans/${this.amazonPayments.groupId}/task-information`);
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.reload(true);
|
||||
this.reset();
|
||||
this.storePaymentStatusAndReload();
|
||||
} catch (e) {
|
||||
this.$set(this, 'amazonButtonEnabled', true);
|
||||
// @TODO: do we need this? this.amazonPaymentsreset();
|
||||
@@ -276,13 +315,19 @@ export default {
|
||||
this.amazonPayments.modal = null;
|
||||
this.amazonPayments.type = null;
|
||||
this.amazonPayments.loggedIn = false;
|
||||
|
||||
// Gift
|
||||
this.amazonPayments.gift = null;
|
||||
this.amazonPayments.giftReceiver = null;
|
||||
|
||||
this.amazonPayments.billingAgreementId = null;
|
||||
this.amazonPayments.orderReferenceId = null;
|
||||
this.amazonPayments.paymentSelected = false;
|
||||
this.amazonPayments.recurringConsent = false;
|
||||
this.amazonPayments.subscription = null;
|
||||
this.amazonPayments.coupon = null;
|
||||
this.amazonPayments.groupToCreate = null;
|
||||
this.amazonPayments.group = null;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,180 +2,172 @@
|
||||
mixin featureBullet (text)
|
||||
.row
|
||||
.col-md-2.offset-1
|
||||
.bubble.mx-auto
|
||||
.svg-icon.check(v-html='icons.check')
|
||||
.d-flex.bubble.justify-content-center.align-items-center
|
||||
.svg-icon.check.mx-auto(v-html='icons.check')
|
||||
.col-md-8.align-self-center
|
||||
p=text
|
||||
div(v-if='user')
|
||||
b-modal(:hide-footer='true', :hide-header='true', :id='"buy-gems"', size='lg')
|
||||
.container-fluid.purple-gradient
|
||||
.gemfall
|
||||
b-modal#buy-gems(:hide-footer='true', size='lg')
|
||||
.header-wrap(slot='modal-header')
|
||||
.image-gemfall
|
||||
.row
|
||||
h2.text-invert.mx-auto {{ $t('support') }}
|
||||
h2.header-invert.mx-auto {{ $t('support') }}
|
||||
.row
|
||||
.logo.svg-icon.mx-auto(v-html="icons.logo")
|
||||
.container-fluid
|
||||
.row
|
||||
.col-6.offset-3.nav
|
||||
.nav-item(@click='selectedPage = "subscribe"', :class="{active: selectedPage === 'subscribe'}") {{ $t('subscribe') }}
|
||||
.nav-item(@click='selectedPage = "gems"', :class="{active: selectedPage === 'gems'}") {{ $t('buyGems') }}
|
||||
div(v-show='selectedPage === "gems"')
|
||||
div(v-if='hasSubscription')
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('subscriptionAlreadySubscribedLeadIn') }}
|
||||
.row.text-center
|
||||
.col-6.offset-3
|
||||
p {{ $t("gemsPurchaseNote") }}
|
||||
.d-flex.nav.justify-content-center
|
||||
.nav-item.text-center(@click='selectedPage = "subscribe"', :class="{active: selectedPage === 'subscribe'}") {{ $t('subscribe') }}
|
||||
.nav-item.text-center(@click='selectedPage = "gems"', :class="{active: selectedPage === 'gems'}") {{ $t('buyGems') }}
|
||||
div(v-show='selectedPage === "gems"')
|
||||
div(v-if='hasSubscription')
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('gemBenefitLeadin') }}
|
||||
h2.mx-auto.text-leadin {{ $t('subscriptionAlreadySubscribedLeadIn') }}
|
||||
.row.text-center
|
||||
.col-6.offset-3
|
||||
p {{ $t("gemsPurchaseNote") }}
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('gemBenefitLeadin') }}
|
||||
.row
|
||||
.col
|
||||
+featureBullet("{{ $t('gemBenefit1') }}")
|
||||
+featureBullet("{{ $t('gemBenefit2') }}")
|
||||
.col
|
||||
+featureBullet("{{ $t('gemBenefit3') }}")
|
||||
+featureBullet("{{ $t('gemBenefit4') }}")
|
||||
.card-deck.gem-deck
|
||||
.card.text-center.col-3(:class="{active: gemAmount === 20 }")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.twentyOneGems', style='"height: 55px; width: 47.5px; margin-top: 1.85em;"')
|
||||
.card-body
|
||||
.gem-count 20
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount === 20 ? gemAmount = 0 : gemAmount = 20') {{gemAmount === 20 ? $t('selected') : '$5.00'}}
|
||||
.row.text-center
|
||||
h2.mx-auto.text-payment {{ $t('choosePaymentMethod') }}
|
||||
.card-deck
|
||||
.card.text-center.payment-method(@click='showStripe({})')
|
||||
.card-body
|
||||
.mx-auto(v-html='icons.creditCard', style='"height: 56px; width: 159px; margin-top: 1em;"')
|
||||
.card.text-center.payment-method
|
||||
a.card-body.paypal(@click="openPaypal(paypalCheckoutLink, 'gems')")
|
||||
img(src='~assets/images/paypal.png')
|
||||
.card.text-center.payment-method(@click="amazonPaymentsInit({type: 'single'})")
|
||||
.card-body.amazon
|
||||
img(src='~assets/images/amazon-payments.png')
|
||||
.row.text-center
|
||||
.svg-icon.mx-auto(v-html='icons.heart', style='"height: 24px; width: 24px;"')
|
||||
.row.text-center.text-outtro
|
||||
.col-6.offset-3 {{ $t('buyGemsSupportsDevs') }}
|
||||
|
||||
div(v-show='selectedPage === "subscribe"')
|
||||
.g1g1-promo.d-flex.justify-content-center.align-items-center
|
||||
.svg-icon.svg-gifts.left-gift(v-html="icons.gifts")
|
||||
.text-center
|
||||
strong.gift-text {{ $t('g1g1Announcement') }}
|
||||
.gift-text {{ $t('g1g1Details') }}
|
||||
.svg-icon.svg-gifts.right-gift(v-html="icons.gifts")
|
||||
div(v-if='hasSubscription')
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('subscriptionAlreadySubscribedLeadIn') }}
|
||||
.row.text-center
|
||||
.col-10.offset-1
|
||||
p(v-html='$t("subscriptionAlreadySubscribed1")')
|
||||
div(v-if='!hasSubscription')
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('subscriptionBenefitLeadin') }}
|
||||
.row
|
||||
.col
|
||||
+featureBullet("{{ $t('gemBenefit1') }}")
|
||||
+featureBullet("{{ $t('gemBenefit2') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit1') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit2') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit3') }}")
|
||||
.col
|
||||
+featureBullet("{{ $t('gemBenefit3') }}")
|
||||
+featureBullet("{{ $t('gemBenefit4') }}")
|
||||
.card-deck.gem-deck
|
||||
//.card.text-center(:class="{active: gemAmount === 4}")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.fourGems', style='"height: 53px; width: 49.5px; margin-top: 2em;"')
|
||||
.card-body
|
||||
.gem-count 4
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount = 4') {{gemAmount === 4 ? $t('selected') : '$1.00'}}
|
||||
.card.text-center.col-3(:class="{active: gemAmount === 20 }")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.twentyOneGems', style='"height: 55px; width: 47.5px; margin-top: 1.85em;"')
|
||||
.card-body
|
||||
.gem-count 20
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount === 20 ? gemAmount = 0 : gemAmount = 20') {{gemAmount === 20 ? $t('selected') : '$5.00'}}
|
||||
//.card.text-center(:class="{active: gemAmount === 42}")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.fortyTwoGems', style='"height: 49.5px; width: 51px; margin-top: 1.9em;"')
|
||||
.card-body
|
||||
.gem-count 42
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount = 42') {{gemAmount === 42 ? $t('selected') : '$10.00'}}
|
||||
//.card.text-center(:class="{active: gemAmount === 84}")
|
||||
.card-img-top
|
||||
.mx-auto(v-html='icons.eightyFourGems', style='"height: 65px; width: 67px; margin-top: 1em;"')
|
||||
.card-body
|
||||
.gem-count 84
|
||||
.gem-text {{ $t('gems') }}
|
||||
.divider
|
||||
button.btn.btn-primary(@click='gemAmount = 84') {{gemAmount === 84 ? $t('selected') : '$20.00'}}
|
||||
.row.text-center
|
||||
h2.mx-auto.text-payment {{ $t('choosePaymentMethod') }}
|
||||
+featureBullet("{{ $t('subscriptionBenefit4') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit5') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit6') }}")
|
||||
.card-deck
|
||||
.card.text-center.payment-method(@click='showStripe({})')
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_earned"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 5
|
||||
span.superscript.muted .00
|
||||
.small(v-once) {{ $t('everyMonth') }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:25})')
|
||||
.spacer
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_earned"') {{ subscriptionPlan === "basic_earned" ? $t('selected') : $t('select') }}
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_3mo"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 15
|
||||
span.superscript.muted .00
|
||||
.small(v-once) {{ $t('everyXMonths', {interval: 3}) }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:30})')
|
||||
p.benefits(v-markdown='$t("receiveMysticHourglass")')
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_3mo"') {{ subscriptionPlan === "basic_3mo" ? $t('selected') : $t('select') }}
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_6mo"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 30
|
||||
span.superscript.muted .00
|
||||
.small(v-once) {{ $t('everyXMonths', {interval: 6}) }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:35})')
|
||||
p.benefits(v-markdown='$t("receiveMysticHourglasses", {amount:2})')
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_6mo"') {{ subscriptionPlan === "basic_6mo" ? $t('selected') : $t('select') }}
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_12mo"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 48
|
||||
span.superscript.muted .00
|
||||
.small(v-once) {{ $t('everyYear') }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:45})')
|
||||
p.benefits(v-markdown='$t("receiveMysticHourglasses", {amount:4})')
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_12mo"') {{ subscriptionPlan === "basic_12mo" ? $t('selected') : $t('select') }}
|
||||
.row.text-center(v-if='subscriptionPlan')
|
||||
h2.mx-auto.text-payment(v-once) {{ $t('choosePaymentMethod') }}
|
||||
.row.text-center
|
||||
a.mx-auto(v-once) {{ $t('haveCouponCode') }}
|
||||
.card-deck(v-if='subscriptionPlan')
|
||||
.card.text-center.payment-method
|
||||
.card-body(@click='showStripe({subscription: subscriptionPlan})')
|
||||
.mx-auto(v-html='icons.creditCard', style='"height: 56px; width: 159px; margin-top: 1em;"')
|
||||
.card.text-center.payment-method
|
||||
a.card-body.paypal(:href='paypalCheckoutLink', target='_blank')
|
||||
a.card-body.paypal(@click="openPaypal(paypalSubscriptionLink, 'subscription')")
|
||||
img(src='~assets/images/paypal.png')
|
||||
.card.text-center.payment-method(@click="amazonPaymentsInit({type: 'single'})")
|
||||
.card-body.amazon
|
||||
.card.text-center.payment-method
|
||||
.card-body.amazon(@click="amazonPaymentsInit({type: 'subscription', subscription: subscriptionPlan})")
|
||||
img(src='~assets/images/amazon-payments.png')
|
||||
.row.text-center
|
||||
.svg-icon.mx-auto(v-html='icons.heart', style='"height: 24px; width: 24px;"')
|
||||
.row.text-center.text-outtro
|
||||
.col-6.offset-3 {{ $t('buyGemsSupportsDevs') }}
|
||||
|
||||
div(v-show='selectedPage === "subscribe"')
|
||||
div(v-if='hasSubscription')
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('subscriptionAlreadySubscribedLeadIn') }}
|
||||
.row.text-center
|
||||
.col
|
||||
p(v-html='$t("subscriptionAlreadySubscribed1")')
|
||||
div(v-if='!hasSubscription')
|
||||
.row.text-center
|
||||
h2.mx-auto.text-leadin {{ $t('subscriptionBenefitLeadin') }}
|
||||
.row
|
||||
.col
|
||||
+featureBullet("{{ $t('subscriptionBenefit1') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit2') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit3') }}")
|
||||
.col
|
||||
+featureBullet("{{ $t('subscriptionBenefit4') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit5') }}")
|
||||
+featureBullet("{{ $t('subscriptionBenefit6') }}")
|
||||
.card-deck
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_earned"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 5
|
||||
span.superscript.muted .00
|
||||
.small {{ $t('everyMonth') }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:25})')
|
||||
.spacer
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_earned"') {{ subscriptionPlan === "basic_earned" ? $t('selected') : $t('select') }}
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_3mo"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 15
|
||||
span.superscript.muted .00
|
||||
.small {{ $t('everyXMonths', {interval: 3}) }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:30})')
|
||||
p.benefits(v-markdown='$t("receiveMysticHourglass")')
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_3mo"') {{ subscriptionPlan === "basic_3mo" ? $t('selected') : $t('select') }}
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_6mo"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 30
|
||||
span.superscript.muted .00
|
||||
.small {{ $t('everyXMonths', {interval: 6}) }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:35})')
|
||||
p.benefits(v-markdown='$t("receiveMysticHourglasses", {amount:2})')
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_6mo"') {{ subscriptionPlan === "basic_6mo" ? $t('selected') : $t('select') }}
|
||||
.card.text-center(:class='{active: subscriptionPlan === "basic_12mo"}')
|
||||
.card-body
|
||||
.subscription-price
|
||||
span.superscript $
|
||||
span 48
|
||||
span.superscript.muted .00
|
||||
.small {{ $t('everyYear') }}
|
||||
.divider
|
||||
p.benefits(v-markdown='$t("earnGemsMonthly", {cap:45})')
|
||||
p.benefits(v-markdown='$t("receiveMysticHourglasses", {amount:4})')
|
||||
button.btn.btn-primary(@click='subscriptionPlan = "basic_12mo"') {{ subscriptionPlan === "basic_12mo" ? $t('selected') : $t('select') }}
|
||||
.row.text-center(v-if='subscriptionPlan')
|
||||
h2.mx-auto.text-payment {{ $t('choosePaymentMethod') }}
|
||||
.row.text-center
|
||||
a.mx-auto {{ $t('haveCouponCode') }}
|
||||
.card-deck(v-if='subscriptionPlan')
|
||||
.card.text-center.payment-method
|
||||
.card-body(@click='showStripe({subscription: subscriptionPlan})')
|
||||
.mx-auto(v-html='icons.creditCard', style='"height: 56px; width: 159px; margin-top: 1em;"')
|
||||
.card.text-center.payment-method
|
||||
a.card-body.paypal(:href='paypalSubscriptionLink', target='_blank')
|
||||
img(src='~assets/images/paypal.png')
|
||||
.card.text-center.payment-method
|
||||
.card-body.amazon(@click="amazonPaymentsInit({type: 'subscription', subscription: subscriptionPlan})")
|
||||
img(src='~assets/images/amazon-payments.png')
|
||||
.row.text-center
|
||||
.svg-icon.mx-auto(v-html='icons.heart', style='"height: 24px; width: 24px;"')
|
||||
.row.text-center.text-outtro
|
||||
.col-6.offset-3 {{ $t('subscribeSupportsDevs') }}
|
||||
.col-6.offset-3 {{ $t('subscribeSupportsDevs') }}
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#buy-gems__BV_body_ {
|
||||
#buy-gems .modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#buy-gems .modal-content {
|
||||
border-radius: 8px;
|
||||
width: 824px;
|
||||
}
|
||||
|
||||
#buy-gems .modal-header {
|
||||
padding: 0;
|
||||
border-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
a.mx-auto {
|
||||
color: #2995cd;
|
||||
}
|
||||
@@ -228,6 +220,11 @@
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
.g1g1-promo {
|
||||
background-color: #34b5c1;
|
||||
height: 3.75rem;
|
||||
}
|
||||
|
||||
.gem-count {
|
||||
font-family: Roboto;
|
||||
font-size: 40px;
|
||||
@@ -242,11 +239,40 @@
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.gemfall {
|
||||
.gift-text {
|
||||
color: $white;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.image-gemfall {
|
||||
background: url(~assets/images/gemfall.png) center repeat-y;
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
.svg-gifts {
|
||||
width: 4.6rem;
|
||||
}
|
||||
|
||||
.left-gift {
|
||||
margin: auto 1rem auto 4.8rem;
|
||||
}
|
||||
|
||||
.right-gift {
|
||||
margin: auto 4.8rem auto 1rem;
|
||||
filter: FlipH;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.header-wrap {
|
||||
background-image: linear-gradient(74deg, #4f2a93, #6133b4);
|
||||
height: 14em;
|
||||
width: 100%;
|
||||
color: #4e4a57;
|
||||
padding: 0;
|
||||
border-top-left-radius: 7px;
|
||||
border-top-right-radius: 7px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 256px;
|
||||
height: 56px;
|
||||
@@ -258,19 +284,21 @@
|
||||
|
||||
.nav {
|
||||
font-weight: bold;
|
||||
height: 40px;
|
||||
background-color: $gray-600;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin: 0 auto;
|
||||
padding: 1.5em;
|
||||
margin: 0rem;
|
||||
padding: 1rem;
|
||||
width: 7.5rem;
|
||||
}
|
||||
|
||||
.nav-item:hover, .nav-item.active {
|
||||
color: #4f2a93;
|
||||
border-bottom: 2px solid #4f2a93;
|
||||
border-bottom: 4px solid $purple-300;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -286,11 +314,6 @@
|
||||
padding-top: 1.3em;
|
||||
}
|
||||
|
||||
.purple-gradient {
|
||||
background-image: linear-gradient(74deg, #4f2a93, #6133b4);
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
height: 4em;
|
||||
}
|
||||
@@ -309,10 +332,11 @@
|
||||
|
||||
.svg-icon.check {
|
||||
color: #bda8ff;
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
.text-invert {
|
||||
margin: 1.6em;
|
||||
.header-invert {
|
||||
margin: 3rem auto 1.5rem;
|
||||
color: #FFFFFF;
|
||||
font-family: Roboto;
|
||||
font-weight: normal;
|
||||
@@ -320,9 +344,9 @@
|
||||
}
|
||||
|
||||
.text-leadin {
|
||||
margin: 1.6em;
|
||||
font-weight: normal;
|
||||
color: #4f2a93;
|
||||
margin: 1rem;
|
||||
font-weight: bold;
|
||||
color: $purple-200;
|
||||
}
|
||||
|
||||
.text-outtro {
|
||||
@@ -346,6 +370,7 @@
|
||||
|
||||
import checkIcon from 'assets/svg/check.svg';
|
||||
import creditCard from 'assets/svg/credit-card.svg';
|
||||
import gifts from 'assets/svg/gifts.svg';
|
||||
import heart from 'assets/svg/health.svg';
|
||||
import logo from 'assets/svg/habitica-logo.svg';
|
||||
|
||||
@@ -381,6 +406,7 @@
|
||||
check: checkIcon,
|
||||
creditCard,
|
||||
fourGems,
|
||||
gifts,
|
||||
heart,
|
||||
twentyOneGems,
|
||||
fortyTwoGems,
|
||||
|
||||
@@ -31,11 +31,17 @@ b-modal#send-gems(:title="title", :hide-footer="true", size='lg', @hide='onHide(
|
||||
)
|
||||
h3.panel-heading {{ $t('subscription') }}
|
||||
.panel-body
|
||||
.form-group
|
||||
.radio(v-for='block in subscriptionBlocks', v-if="block.target !== 'group' && block.canSubscribe === true")
|
||||
label
|
||||
input(type="radio", name="subRadio", :value="block.key", v-model='gift.subscription.key')
|
||||
| {{ $t('sendGiftSubscription', {price: block.price, months: block.months}) }}
|
||||
.row
|
||||
.col-md-4
|
||||
.form-group
|
||||
.radio(v-for='block in subscriptionBlocks', v-if="block.target !== 'group' && block.canSubscribe === true")
|
||||
label
|
||||
input(type="radio", name="subRadio", :value="block.key", v-model='gift.subscription.key')
|
||||
| {{ $t('sendGiftSubscription', {price: block.price, months: block.months}) }}
|
||||
.col-md-8
|
||||
h4 {{ $t('winterPromoGiftHeader') }}
|
||||
p {{ $t('winterPromoGiftDetails1') }}
|
||||
p {{ $t('winterPromoGiftDetails2') }}
|
||||
|
||||
textarea.form-control(rows='3', v-model='gift.message', :placeholder="$t('sendGiftMessagePlaceholder')")
|
||||
//include ../formatting-help
|
||||
@@ -47,9 +53,9 @@ b-modal#send-gems(:title="title", :hide-footer="true", size='lg', @hide='onHide(
|
||||
:disabled="sendingInProgress"
|
||||
) {{ $t("send") }}
|
||||
template(v-else)
|
||||
button.btn.btn-primary(@click='showStripe({gift, uuid: userReceivingGems._id})') {{ $t('card') }}
|
||||
button.btn.btn-warning(@click='openPaypalGift({gift: gift, giftedTo: userReceivingGems._id})') PayPal
|
||||
button.btn.btn-success(@click="amazonPaymentsInit({type: 'single', gift, giftedTo: userReceivingGems._id})") Amazon Payments
|
||||
button.btn.btn-primary(@click='showStripe({gift, uuid: userReceivingGems._id, receiverName})') {{ $t('card') }}
|
||||
button.btn.btn-warning(@click='openPaypalGift({gift: gift, giftedTo: userReceivingGems._id, receiverName})') PayPal
|
||||
button.btn.btn-success(@click="amazonPaymentsInit({type: 'single', gift, giftedTo: userReceivingGems._id, receiverName})") Amazon Payments
|
||||
button.btn.btn-secondary(@click='close()') {{$t('cancel')}}
|
||||
</template>
|
||||
|
||||
@@ -131,6 +137,13 @@ export default {
|
||||
if (!this.userReceivingGems) return '';
|
||||
return this.$t('sendGiftHeading', {name: this.userReceivingGems.profile.name});
|
||||
},
|
||||
receiverName () {
|
||||
if (this.userReceivingGems.auth && this.userReceivingGems.auth.local && this.userReceivingGems.auth.local.username) {
|
||||
return this.userReceivingGems.auth.local.username;
|
||||
} else {
|
||||
return this.userReceivingGems.profile.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// @TODO move to payments mixin or action (problem is that we need notifications)
|
||||
@@ -141,11 +154,23 @@ export default {
|
||||
toUserId: this.userReceivingGems._id,
|
||||
gemAmount: this.gift.gems.amount,
|
||||
});
|
||||
this.text(this.$t('sentGems'));
|
||||
this.close();
|
||||
setTimeout(() => { // wait for the send gem modal to be closed
|
||||
this.$root.$emit('habitica:payment-success', {
|
||||
paymentMethod: 'balance',
|
||||
paymentCompleted: true,
|
||||
paymentType: 'gift-gems-balance',
|
||||
gift: {
|
||||
gems: {
|
||||
amount: this.gift.gems.amount,
|
||||
},
|
||||
},
|
||||
giftReceiver: this.receiverName,
|
||||
});
|
||||
}, 500);
|
||||
},
|
||||
onHide () {
|
||||
// TODO this breaks amazon purchases because when the amazon modal
|
||||
// @TODO this breaks amazon purchases because when the amazon modal
|
||||
// is opened this one is closed and the amount reset
|
||||
// this.gift.gems.amount = 0;
|
||||
this.gift.message = '';
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
<template lang="pug">
|
||||
b-modal#payments-success-modal(
|
||||
:title="$t('accountSuspendedTitle')",
|
||||
size='sm',
|
||||
:hideFooter="isFromBalance",
|
||||
:modalClass="isFromBalance ? ['modal-hidden-footer'] : []"
|
||||
)
|
||||
div(slot="modal-header")
|
||||
.check-container.d-flex.align-items-center.justify-content-center
|
||||
.svg-icon.check(v-html="icons.check", v-once)
|
||||
h2 {{ $t(isFromBalance ? 'success' : 'paymentSuccessful') }}
|
||||
div(slot="modal-footer")
|
||||
.small-text(v-once) {{ $t('giftSubscriptionText4') }}
|
||||
.row
|
||||
.col-12.modal-body-col
|
||||
template(v-if="paymentData.paymentType === 'gems'")
|
||||
strong(v-once) {{ $t('paymentYouReceived') }}
|
||||
.details-block.gems
|
||||
.svg-icon(v-html="icons.gem", v-once)
|
||||
span 20
|
||||
template(v-if="paymentData.paymentType === 'gift-gems' || paymentData.paymentType === 'gift-gems-balance'")
|
||||
span(v-html="$t('paymentYouSentGems', {name: paymentData.giftReceiver})")
|
||||
.details-block.gems
|
||||
.svg-icon(v-html="icons.gem", v-once)
|
||||
span {{ paymentData.gift.gems.amount }}
|
||||
template(v-if="paymentData.paymentType === 'gift-subscription'")
|
||||
span(v-html="$t('paymentYouSentSubscription', {name: paymentData.giftReceiver, months: paymentData.subscription.months})")
|
||||
template(v-if="paymentData.paymentType === 'subscription'")
|
||||
strong(v-once) {{ $t('nowSubscribed') }}
|
||||
.details-block
|
||||
span(v-html="$t('paymentSubBilling', {amount: paymentData.subscription.price, months: paymentData.subscription.months})")
|
||||
template(v-if="paymentData.paymentType === 'groupPlan'")
|
||||
span(v-html="$t(paymentData.newGroup ? 'groupPlanCreated' : 'groupPlanUpgraded', {groupName: paymentData.group.name})")
|
||||
.details-block
|
||||
span(v-html="$t('paymentSubBilling', {amount: groupPlanCost, months: paymentData.subscription.months})")
|
||||
button.btn.btn-primary(@click='close()', v-once) {{$t('onwards')}}
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
#payments-success-modal .modal-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#payments-success-modal.modal-hidden-footer .modal-body {
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
#payments-success-modal .modal-header {
|
||||
justify-content: center;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 0px;
|
||||
background: $green-10;
|
||||
border-top-right-radius: 8px;
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom: none;
|
||||
|
||||
h2 {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.check-container {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
background: #1CA372;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.check {
|
||||
width: 35.1px;
|
||||
height: 28px;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
#payments-success-modal .modal-body {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 24px;
|
||||
background: white;
|
||||
|
||||
.modal-body-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.details-block {
|
||||
background: $gray-700;
|
||||
border-radius: 4px;
|
||||
padding: 8px 24px;
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: center;
|
||||
|
||||
&.gems {
|
||||
padding: 12px 16px 12px 20px;
|
||||
color: $green-10;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
|
||||
.svg-icon {
|
||||
margin-right: 8px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#payments-success-modal .modal-footer {
|
||||
background: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
justify-content: center;
|
||||
border-top: none;
|
||||
|
||||
.small-text {
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import checkIcon from 'assets/svg/check.svg';
|
||||
import gemIcon from 'assets/svg/gem.svg';
|
||||
import subscriptionBlocks from '../../../common/script/content/subscriptionBlocks';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
check: checkIcon,
|
||||
gem: gemIcon,
|
||||
}),
|
||||
paymentData: {},
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.$root.$on('habitica:payment-success', (data) => {
|
||||
if (['subscription', 'groupPlan', 'gift-subscription'].indexOf(data.paymentType) !== -1) {
|
||||
data.subscription = subscriptionBlocks[data.subscriptionKey || data.gift.subscription.key];
|
||||
}
|
||||
this.paymentData = data;
|
||||
this.$root.$emit('bv::show::modal', 'payments-success-modal');
|
||||
});
|
||||
},
|
||||
destroyed () {
|
||||
this.paymentData = {};
|
||||
this.$root.$off('habitica:payments-success');
|
||||
},
|
||||
computed: {
|
||||
groupPlanCost () {
|
||||
const sub = this.paymentData.subscription;
|
||||
const memberCount = this.paymentData.group.memberCount || 1;
|
||||
return sub.price + 3 * (memberCount - 1);
|
||||
},
|
||||
isFromBalance () {
|
||||
return this.paymentData.paymentType === 'gift-gems-balance';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.paymentData = {};
|
||||
this.$root.$emit('bv::hide::modal', 'payments-success-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||