More fixes (#8988)

* Links stay white on hover

* Fixed task icon color

* Disabled plus button when needed

* Fixed difficulty color

* Fixed task reward color

* Updated create styles

* Fixed group plan link

* Fixed second group test modal

* Added login incentives

* Fixed group notification clear

* Show baily correctly

* Styled armoire notification

* Fixed contributor achievement styles

* Fixed death

* Fixed drop styles

* Fixed invited friend modal

* Fixed joined challenge achievement style

* Fixed joined guild style

* Fixed level up styles

* Updated low health styles

* Fixed bailey styles

* Updated quest completed

* Added soem conditionals to hide modals

* Added rebirth styles

* Fixed rebirth enable styles

* Fixed streak styles

* Fixed testing modals

* Fixed ultimate gear achievement

* Fixed won challenge

* Set user to welcomed if created on mobile

* Removed old default tasks

* Began adding more options to avatar

* Added change class

* Inbox to messages

* Moved profile to menu

* Added user modal for viewing a user and send message

* Fixed conversations

* Fixed lint

* Fixed challenges sending to server

* Added challenge progress view

* Fixed group sync after pay

* Fixed some group accepting features

* Fixed initial chat loading

* Fixed some exitence errors

* Added user names to assigned

* Added upgrade link

* Began adding new payment flow

* Added default tasks

* Updated avatar styles

* Updated tutorial styles

* Rebuilt notifications and styles

* Updated upload script

* Fixed lint

* Added default tasks back to mobile and added updated tests

* More test fixes
This commit is contained in:
Keith Holliday 2017-08-25 20:56:21 -06:00 committed by GitHub
parent c129c38631
commit 0233f7b486
64 changed files with 13438 additions and 5207 deletions

98
migrations/s3-upload.js Normal file
View file

@ -0,0 +1,98 @@
let Bluebird = require('bluebird');
let request = require('superagent');
let last = require('lodash/last');
let AWS = require('aws-sdk');
let config = require('../config');
const S3_DIRECTORY = 'mobileApp/images'; //config.S3.SPRITES_DIRECTORY;
AWS.config.update({
accessKeyId: config.S3.accessKeyId,
secretAccessKey: config.S3.secretAccessKey,
// region: config.get('S3_REGION'),
});
let BUCKET_NAME = config.S3.bucket;
let s3 = new AWS.S3();
// Adapted from http://stackoverflow.com/a/22210077/2601552
function uploadFile (buffer, fileName) {
return new Promise((resolve, reject) => {
s3.putObject({
Body: buffer,
Key: fileName,
Bucket: BUCKET_NAME,
}, (error) => {
if (error) {
reject(error);
} else {
// console.info(`${fileName} uploaded to ${BUCKET_NAME} succesfully.`);
resolve(fileName);
}
});
});
}
function getFileName (file) {
let piecesOfPath = file.split('/');
let name = last(piecesOfPath);
let fullName = S3_DIRECTORY + name;
return fullName;
}
function getFileFromUrl (url) {
return new Promise((resolve, reject) => {
request.get(url).end((err, res) => {
if (err) return reject(err);
let file = res.body;
resolve(file);
});
});
}
let commit = '78f94e365c72cc58f66857d5941105638db7d35c';
commit = 'df0dbaba636c9ce424cc7040f7bd7fc1aa311015';
let gihuburl = `https://api.github.com/repos/HabitRPG/habitica/commits/${commit}`
let currentIndex = 0;
function uploadToS3(start, end, filesUrls) {
let urls = filesUrls.slice(start, end);
if (urls.length === 0) {
console.log("done");
return;
}
let promises = urls.map(fullUrl => {
return getFileFromUrl(fullUrl)
.then((buffer) => {
return uploadFile(buffer, getFileName(fullUrl));
});
});
console.log(promises.length)
return Bluebird.all(promises)
.then(() => {
currentIndex += 50;
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
})
.catch(e => {
console.log(e);
});
}
request.get(gihuburl)
.end((err, res) => {
console.log(err);
let files = res.body.files;
let filesUrls = [''];
filesUrls = files.map(file => {
return file.raw_url;
})
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
});

16408
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load diff

View file

@ -38,6 +38,7 @@
"connect-ratelimit": "0.0.7",
"cookie-session": "^1.2.0",
"coupon-code": "^0.4.5",
"cross-env": "^4.0.0",
"css-loader": "^0.28.0",
"csv-stringify": "^1.0.2",
"cwait": "~1.0.1",
@ -125,7 +126,6 @@
"vue": "^2.1.0",
"vue-loader": "^11.0.0",
"vue-mugen-scroll": "^0.2.1",
"vue-notification": "^1.3.2",
"vue-router": "^2.0.0-rc.5",
"vue-style-loader": "^3.0.0",
"vue-template-compiler": "^2.1.10",
@ -134,8 +134,7 @@
"webpack-merge": "^4.0.0",
"winston": "^2.1.0",
"winston-loggly-bulk": "^1.4.2",
"xml2js": "^0.4.4",
"cross-env": "^4.0.0"
"xml2js": "^0.4.4"
},
"private": true,
"engines": {

View file

@ -13,7 +13,7 @@ describe('GET /tasks/user', () => {
it('returns all user\'s tasks', async () => {
let createdTasks = await user.post('/tasks/user', [{text: 'test habit', type: 'habit'}, {text: 'test todo', type: 'todo'}]);
let tasks = await user.get('/tasks/user');
expect(tasks.length).to.equal(createdTasks.length + 1); // + 1 because 1 is a default task
expect(tasks.length).to.equal(createdTasks.length + 1); // Plus one for generated todo
});
it('returns only a type of user\'s tasks if req.query.type is specified', async () => {

View file

@ -95,7 +95,7 @@ describe('POST /tasks/unlink-all/:challengeId', () => {
// Have the leader delete the challenge and unlink the tasks
await user.del(`/challenges/${challenge._id}`);
await user.post(`/tasks/unlink-all/${challenge._id}?keep=keep-all`);
// Get the second task for the second user
// Get the task for the second user
const [, anotherUserTask] = await anotherUser.get('/tasks/user');
// Expect the second user to still have the task, but unlinked
expect(anotherUserTask.challenge).to.eql({
@ -106,4 +106,4 @@ describe('POST /tasks/unlink-all/:challengeId', () => {
winner: null,
});
});
});
});

View file

@ -86,6 +86,12 @@ describe('DELETE /user', () => {
});
it('deletes the user\'s tasks', async () => {
await user.post('/tasks/user', {
text: 'test habit',
type: 'habit',
});
await user.sync();
// gets the user's tasks ids
let ids = [];
each(user.tasksOrder, (idsForOrder) => {

View file

@ -82,7 +82,7 @@ describe('GET /user/anonymized', () => {
});
// tasks
expect(tasks2).to.exist;
expect(tasks2.length).to.eql(5); // +1 because generateUser() assigns one todo
expect(tasks2.length).to.eql(5);
expect(tasks2[0].checklist).to.exist;
_.forEach(tasks2, (task) => {
expect(task.text).to.eql('task text');

View file

@ -59,13 +59,8 @@ describe('POST /user/auth/local/register', () => {
let tags = await requests.get('/tags');
expect(habits).to.have.a.lengthOf(0);
expect(dailys).to.have.a.lengthOf(0);
expect(todos).to.have.a.lengthOf(1);
expect(todos[0].text).to.eql(t('defaultTodo1Text'));
expect(todos[0].notes).to.eql(t('defaultTodoNotes'));
expect(rewards).to.have.a.lengthOf(0);
expect(tags).to.have.a.lengthOf(7);
@ -78,7 +73,7 @@ describe('POST /user/auth/local/register', () => {
expect(tags[6].name).to.eql(t('defaultTag7'));
});
it('for Web', async () => {
xit('for Web', async () => {
api = requester(
null,
{'x-client': 'habitica-web'},
@ -667,10 +662,10 @@ describe('POST /user/auth/local/register', () => {
confirmPassword: password,
});
expect(user.tasksOrder.todos).to.not.be.empty;
expect(user.tasksOrder.todos).to.be.empty;
expect(user.tasksOrder.dailys).to.be.empty;
expect(user.tasksOrder.habits).to.not.be.empty;
expect(user.tasksOrder.rewards).to.not.be.empty;
expect(user.tasksOrder.habits).to.be.empty;
expect(user.tasksOrder.rewards).to.be.empty;
});
it('populates user with default tags', async () => {
@ -697,23 +692,8 @@ describe('POST /user/auth/local/register', () => {
let habits = await requests.get('/tasks/user?type=habits');
let todos = await requests.get('/tasks/user?type=todos');
function findTag (tagName) {
let tag = user.tags.find((userTag) => {
return userTag.name === t(tagName);
});
return tag.id;
}
expect(habits[0].tags).to.have.a.lengthOf(3);
expect(habits[0].tags).to.include.members(['defaultTag1', 'defaultTag4', 'defaultTag6'].map(findTag));
expect(habits[1].tags).to.have.a.lengthOf(1);
expect(habits[1].tags).to.include.members(['defaultTag3'].map(findTag));
expect(habits[2].tags).to.have.a.lengthOf(2);
expect(habits[2].tags).to.include.members(['defaultTag2', 'defaultTag3'].map(findTag));
expect(todos[0].tags).to.have.a.lengthOf(0);
expect(habits).to.have.a.lengthOf(0);
expect(todos).to.have.a.lengthOf(0);
});
});
});

View file

@ -1,6 +1,6 @@
<template lang="pug">
#app(:class='{"casting-spell": castingSpell}')
notifications
snackbars
router-view(v-if="!isUserLoggedIn || isStaticPage")
template(v-else)
#loading-screen.h-100.w-100.d-flex.justify-content-center.align-items-center(v-if="!isUserLoaded")
@ -19,6 +19,16 @@
.casting-spell {
cursor: crosshair;
}
.notification {
border-radius: 1000px;
background-color: #24cc8f;
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
padding: .5em 1em;
color: #fff;
margin-top: .5em;
margin-bottom: .5em;
}
</style>
<style>
@ -34,6 +44,7 @@ import AppMenu from './components/appMenu';
import AppHeader from './components/appHeader';
import AppFooter from './components/appFooter';
import notificationsDisplay from './components/notifications';
import snackbars from './components/snackbars/notifications';
import { mapState } from 'client/libs/store';
export default {
@ -43,6 +54,7 @@ export default {
AppHeader,
AppFooter,
notificationsDisplay,
snackbars,
},
data () {
return {

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -1,15 +1,7 @@
<template lang="pug">
.container-fluid
.row
.col-4(style='padding:0')
div(:class='achievementClass')
.col-4(style='padding:0')
.herobox(:style="`${margin}em`")
.character-sprites
//- +generatedAvatar({sleep: false})
avatar(:member='user')
.col-4
div(:class='achievementClass' style='margin: 2em auto')
div(:class='achievementClass')
//- +generatedAvatar({sleep: false})
avatar(:member='user')
</template>
<script>
@ -20,7 +12,6 @@ export default {
components: {
Avatar,
},
props: ['badge', 'margin'],
data () {
return {
achievementClass: `achievement-${this.badge}2x`,

View file

@ -1,15 +1,22 @@
<template lang="pug">
b-modal#armoire-empty(:title="$t('armoireText')", size='lg', :hide-footer="true")
.modal-header
.shop_armoire.pull-right
.modal-body
p {{$t('armoireLastItem')}}
br
p {{$t('armoireNotesEmpty')}}
.row
.col-6.offset-3
.shop_armoire
p {{$t('armoireLastItem')}}
p {{$t('armoireNotesEmpty')}}
.modal-footer
button.btn.btn-default(@click='close()') {{$t('close')}}
.col-12.text-center
button.btn.btn-primary(@click='close()') {{$t('close')}}
</template>
<style scoped>
.shop_armoire {
margin: 1em auto;
}
</style>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';

View file

@ -1,19 +1,20 @@
<template lang="pug">
b-modal#contributor(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
.modal-body.text-center
h3(style='margin-bottom:0') {{ $t('modalContribAchievement') }}
// @TODO: +achievementAvatar('boot',0)
achievement-avatar
| {{ $t('contribModal', {name: user.profile.name, level: user.contributor.level}) }}
a(:href="$t('conRewardsURL')", target='_blank') {{ $t('contribLink') }}
br
button.btn.btn-primary(style='margin-top:1em' @click='close()') {{ $t('huzzah') }}
b-modal#contributor(:title="$t('modalContribAchievement')", size='lg', :hide-footer="true")
.modal-body
.col-6.offset-3.text-center
achievement-avatar.avatar
| {{ $t('contribModal', {name: user.profile.name, level: user.contributor.level}) }}
a(:href="$t('conRewardsURL')", target='_blank') {{ $t('contribLink') }}
br
button.btn.btn-primary(style='margin-top:1em' @click='close()') {{ $t('huzzah') }}
br
achievement-footer
</template>
<style scope>
.dont-despair, .death-penalty {
.avatar {
margin-left: 4em;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>

View file

@ -1,38 +1,37 @@
<template lang="pug">
b-modal#death(:title="$t('lostAllHealth')", size='lg', :hide-footer="true")
.modal-body
.container-fluid
.row
.col-6.col-xs-12
.hero-stats
.meter-label(:tooltip="$t('health')")
span.glyphicon.glyphicon-heart
.meter.health(:tooltip='Math.round(user.stats.hp * 100) / 100')
.bar(:style='barStyle')
span.meter-text.value
| {{Math.ceil(user.stats.hp)}} / {{maxHealth}}
figure.herobox.text-center
.character-sprites
avatar(:member='user')
// @TOOD: Sleep +generatedAvatar({sleep:true})
span(class='knockout')
.col-6.col-xs-12
h4.dont-despair {{ $t('dontDespair') }}
p.death-penalty {{ $t('deathPenaltyDetails') }}
.modal-footer
a.btn.btn-danger.btn-lg.flex-column.btn-wrap(@click='revive(); close()') {{ $t('refillHealthTryAgain') }}
h4.text-center {{ $t('dyingOftenTips') }}
.info
.row
.col-6
.hero-stats
.meter-label(:tooltip="$t('health')")
span.glyphicon.glyphicon-heart
.meter.health(:tooltip='Math.round(user.stats.hp * 100) / 100')
.bar(:style='barStyle')
// span.meter-text.value
| {{Math.ceil(user.stats.hp)}} / {{maxHealth}}
avatar(:member='user', :sleep='true')
// @TOOD: Sleep +generatedAvatar({sleep:true})
span(class='knockout')
.col-6
h4.dont-despair {{ $t('dontDespair') }}
p.death-penalty {{ $t('deathPenaltyDetails') }}
.modal-footer
.col-12.text-center
button.btn.btn-danger(@click='revive()') {{ $t('refillHealthTryAgain') }}
h4.text-center(v-html="$t('dyingOftenTips')")
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.info {
height: 220px;
}
</style>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
import axios from 'axios';
import Avatar from '../avatar';
import { mapState } from 'client/libs/store';
import revive from '../../../common/script/ops/revive';
@ -61,9 +60,10 @@ export default {
close () {
this.$root.$emit('hide::modal', 'death');
},
revive () {
// @TODO: Post
async revive () {
await axios.post('/api/v3/user/revive');
revive(this.user);
this.close();
},
},
};

View file

@ -1,24 +1,21 @@
<template lang="pug">
b-modal#drops-enabled(:title="$t('dropsEnabled')", size='lg', :hide-footer="true")
.modal-header
h4 {{ $t('dropsEnabled') }}
.modal-body
p
figure
.col-6.offset-3.text-center
p
.item-drop-icon(class='Pet_Egg_Wolf')
span {{ firstDropText }}
br
p
figure
span(v-html='firstDropText')
p
.item-drop-icon(class='Pet_Currency_Gem')
span {{ $t('useGems') }}
span(v-html="$t('useGems')")
.modal-footer
button.btn.btn-default(@click='close()') {{ $t('close') }}
.col-12.text-center
button.btn.btn-primary(@click='close()') {{ $t('close') }}
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.item-drop-icon {
margin: 0 auto;
}
</style>

View file

@ -1,10 +1,8 @@
<template lang="pug">
b-modal#invite-friend(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
b-modal#invited-friend(:title="$t('modalAchievement')", size='lg', :hide-footer="true")
.modal-body.text-center
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
// @TODO: +achievementAvatar('friends',0)
achievement-avatar
achievement-avatar.avatar
p {{ $t('invitedFriendText') }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
@ -12,7 +10,9 @@
</template>
<style scope>
.dont-despair, .death-penalty {
.avatar {
margin-left: 10.2em;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>
@ -30,7 +30,7 @@ export default {
},
methods: {
close () {
this.$root.$emit('hide::modal', 'invite-friend');
this.$root.$emit('hide::modal', 'invited-friend');
},
},
};

View file

@ -1,10 +1,8 @@
<template lang="pug">
b-modal#join-challenge(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
b-modal#joined-challenge(:title="$t('modalAchievement')", size='lg', :hide-footer="true")
.modal-body.text-center
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
// @TODO: +achievementAvatar('challenge',0)
achievement-avatar
achievement-avatar.avatar
p {{ $t('joinedChallengeText') }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
@ -12,7 +10,9 @@
</template>
<style scope>
.dont-despair, .death-penalty {
.avatar {
margin-left: 10.2em;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>
@ -30,7 +30,7 @@ export default {
},
methods: {
close () {
this.$root.$emit('hide::modal', 'join-challenge');
this.$root.$emit('hide::modal', 'joined-challenge');
},
},
};

View file

@ -1,9 +1,8 @@
<template lang="pug">
b-modal#joined-guild(:title="$t('modalAchievement')", size='lg', :hide-footer="true")
.modal-body.text-center
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
// @TODO: +achievementAvatar('guild',0)
achievement-avatar
achievement-avatar.avatar
p {{ $t('joinedGuildText') }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
@ -11,7 +10,9 @@
</template>
<style scope>
.dont-despair, .death-penalty {
.avatar {
margin-left: 10.2em;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>

View file

@ -1,50 +1,37 @@
<template lang="pug">
b-modal#level-up(:title="$t('levelUpShare')", size='sm', :hide-footer="true")
.modal-content
.modal-body.text-center
h3 {{ $t('gainedLevel') }}
.container-fluid
.row
.herobox
.character-sprites
// @TODO: ({sleep: false})
avatar(:member='user')
.row
.herobox
.avatar-level(:class='userLevelStyle(user)') {{ $t('level') + user.stats.lvl }}
h4 {{ $t('leveledUp', {level: user.stats.lvl}) }}
p {{ $t('fullyHealed') }}
br
div(v-if='user.flags.classSelected && !user.preferences.disableClasses && !user.preferences.automaticAllocation')
a.btn.btn-default(@click='statsAllocationBoxIsOpen = !statsAllocationBoxIsOpen',
data-toggle='collapse', data-target='#stat-allocation', aria-expanded='false', aria-controls='stat-allocation')
| {{statsAllocationBoxIsOpen ? $t('hideQuickAllocation') : $t('showQuickAllocation')}}
p &nbsp;
.collapse#stat-allocation
table.table.text-left
tr
td
p(v-if='user.stats.lvl >= 100') {{ $t('noMoreAllocate') }}
p(v-if='user.stats.points || user.stats.lvl < 100')
strong.inline
| {{user.stats.points}}&nbsp;
strong.hint(popover-trigger='mouseenter',
popover-placement='right', :popover="$t('quickAllocationLevelPopover')") {{ $t('unallocated') }}
td
// @TODO: +statAllocation
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
.checkbox
label(style='display:inline-block') {{ $t('dontShowAgain') }}
input(type='checkbox', v-model='user.preferences.suppressModals.levelUp', @change='changeLevelupSuppress()')
.modal-footer
.container-fluid
.row
.col-4
a.twitter-share-button(:href='twitterLink') {{ $t('tweet') }}
.col-4
.fb-share-button(:data-href='socialLevelLink', data-layout='button')
.col-4
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
.modal-body.text-center
h3 {{ $t('gainedLevel') }}
avatar.avatar(:member='user')
h4.avatar-level(:class='userLevelStyle(user)') {{ $t('level') + ' ' + user.stats.lvl }}
h4(v-html="$t('leveledUp', {level: user.stats.lvl})")
p {{ $t('fullyHealed') }}
br
div(v-if='showAllocation')
a.btn.btn-default(@click='statsAllocationBoxIsOpen = !statsAllocationBoxIsOpen')
| {{statsAllocationBoxIsOpen ? $t('hideQuickAllocation') : $t('showQuickAllocation')}}
p &nbsp;
#stat-allocation(v-if='statsAllocationBoxIsOpen')
p(v-if='user.stats.lvl >= 100') {{ $t('noMoreAllocate') }}
p(v-if='user.stats.points || user.stats.lvl < 100')
strong.inline
| {{user.stats.points}}&nbsp;
strong.hint(popover-trigger='mouseenter',
popover-placement='right', :popover="$t('quickAllocationLevelPopover')") {{ $t('unallocated') }}
// @TODO: +statAllocation
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
.checkbox
input(type='checkbox', v-model='user.preferences.suppressModals.levelUp', @change='changeLevelupSuppress()')
label(style='display:inline-block') {{ $t('dontShowAgain') }}
.modal-footer
.container-fluid
.row
.col-4
a.twitter-share-button(:href='twitterLink') {{ $t('tweet') }}
.col-4
.fb-share-button(:data-href='socialLevelLink', data-layout='button')
.col-4
a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')
</template>
<style lang="scss">
@ -77,6 +64,12 @@
}
</style>
<style scoped>
.avatar {
margin-left: 6.8em;
}
</style>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
@ -108,6 +101,9 @@ export default {
},
computed: {
...mapState({user: 'user.data'}),
showAllocation () {
return this.user.flags.classSelected && !this.user.preferences.disableClasses && !this.user.preferences.automaticAllocation;
},
},
methods: {
close () {

View file

@ -0,0 +1,62 @@
<template lang="pug">
b-modal#login-incentives(:title="data.message", size='md', :hide-footer="true")
.modal-body
.row.reward-row
div.text-center.col-6.text-center
avatar(:member='user')
div.text-center.col-6.text-center
div(v-if="nextReward.rewardKey.length === 1", :class="nextReward.rewardKey[0]")
div(v-for="reward in nextReward.rewardKey", v-if="nextReward.rewardKey.length > 1", :class='reward')
div(v-if="data.nextRewardAt")
h4 {{ $t('countLeft', {count: data.nextRewardAt - user.loginIncentives}) }}
.row
.col-8.offset-2.text-center
p {{ $t('incentivesDescription') }}
.col-12.text-center(v-if="data.nextRewardAt")
h3 {{ $t('nextRewardUnlocksIn', {numberOfCheckinsLeft: data.nextRewardAt - user.loginIncentives}) }}
.modal-footer
.col-12.text-center
button.btn.btn-primary(@click='close()') {{ $t('awesome') }}
</template>
<style scoped>
.reward-row {
margin-top: 2em;
margin-bottom: 2em;
}
</style>
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
import { mapState } from 'client/libs/store';
import Avatar from '../avatar';
import {loginIncentives} from '../../../common/script/content/index';
export default {
components: {
Avatar,
bModal,
},
props: ['data'],
data () {
return {
loginIncentives,
};
},
computed: {
...mapState({
user: 'user.data',
}),
nextReward () {
let nextRewardKey = this.loginIncentives[this.user.loginIncentives].nextRewardAt;
let nextReward = this.loginIncentives[nextRewardKey];
return nextReward;
},
},
methods: {
close () {
this.$root.$emit('hide::modal', 'login-incentives');
},
},
};
</script>

View file

@ -1,28 +1,29 @@
<template lang="pug">
b-modal#low-health(:title="$t('losingHealthWarning')", size='lg', :hide-footer="true")
b-modal#low-health(:title="$t('losingHealthWarning')", size='md', :hide-footer="true")
.modal-body
.hero-stats
.col-12.text-center
.meter-label(:tooltip="$t('health')")
span.glyphicon.glyphicon-heart
.meter.health(:tooltip='Math.round(user.stats.hp * 100) / 100')
.bar(:style='barStyle')
span.meter-text.value
| {{healthLeft}}
.herobox.inline-block
.character-sprites
avatar(:member='user')
p {{ $t('losingHealthWarning2') }}
h4 {{ $t('toRegainHealth') }}
ul
li.spaced {{ $t('lowHealthTips1') }}
li.spaced {{ $t('lowHealthTips2') }}
h4 {{ $t('losingHealthQuickly') }}
ul
li.spaced {{ $t('lowHealthTips3') }}
li.spaced {{ $t('lowHealthTips4') }}
h4 {{ $t('goodLuck') }}
.col-12
avatar(:member='user')
.col-12
p {{ $t('losingHealthWarning2') }}
h4 {{ $t('toRegainHealth') }}
ul
li.spaced {{ $t('lowHealthTips1') }}
li.spaced {{ $t('lowHealthTips2') }}
h4 {{ $t('losingHealthQuickly') }}
ul
li.spaced {{ $t('lowHealthTips3') }}
li.spaced {{ $t('lowHealthTips4') }}
h4 {{ $t('goodLuck') }}
.modal-footer
a.btn.btn-primary(@click='acknowledgeHealthWarning()') {{ $t('ok') }}
.col-12.text-center
button.btn.btn-primary(@click='acknowledgeHealthWarning()') {{ $t('ok') }}
</template>
<style scope>

View file

@ -1,21 +1,21 @@
<template lang="pug">
b-modal#new-stuff(:title="$t('newStuff')", size='lg', :hide-footer="true")
.modal-header
| {{ this.$t('newStuff') }} by&nbsp;
a(target='_blank', href='https://twitter.com/Mihakuu') Bailey
.modal-body.new-stuff-modal.modal-fixed-height
b-modal#new-stuff(v-if='user.flags.newStuff', :title="$t('newStuff')", size='lg', :hide-footer="true")
.modal-body.new-stuff-modal
h3.text-center
| {{ this.$t('newStuff') }} by&nbsp;
a(target='_blank', href='https://twitter.com/Mihakuu') Bailey
div(:class="baileyClass")
br
br
div(ng-bind-html='latestBaileyMessage')
div(v-html='latestBaileyMessage')
.modal-footer
a.btn.btn-info(href='http://habitica.wikia.com/wiki/Whats_New', target='_blank') {{ this.$t('newsArchive') }}
button.btn.btn-default(@click='close()') {{ this.$t('cool') }}
button.btn.btn-warning(@click='dismissAlert(); close()') {{ this.$t('dismissAlert') }}
button.btn.btn-warning(@click='dismissAlert();') {{ this.$t('dismissAlert') }}
</template>
<script>
import axios from 'axios';
import bModal from 'bootstrap-vue/lib/components/modal';
import { mapState } from 'client/libs/store';
export default {
components: {
@ -33,13 +33,21 @@ export default {
},
};
},
mounted () {
// @TODO: $http.get('/new-stuff.html') ?
computed: {
...mapState({user: 'user.data'}),
async latestBaileyMessage () {
let message = await axios.get('/new-stuff');
return message;
},
},
methods: {
close () {
this.$root.$emit('hide::modal', 'new-stuff');
},
dismissAlert () {
this.$store.dispatch('user:set', {'flags.newStuff': false});
this.close();
},
},
};
</script>

View file

@ -1,10 +1,8 @@
<template lang="pug">
b-modal#quest-completed(:title="$t('lostAllHealth')", size='lg', :hide-footer="true")
.modal-header
h4 "{{quests[user.party.quest.completed].text()}}"&nbsp;
| {{ $t('completed') }}
.modal-body
.col-centered(:class='`quest_${user.party.quest.completed}`')
b-modal#quest-completed(v-if='user.party.quest.completed', :title="quests[user.party.quest.completed].text() + '' + $t('completed')",
size='lg', :hide-footer="true")
.modal-body.text-center
div(:class='`quest_${user.party.quest.completed}`')
p(v-html='quests[user.party.quest.completed].completion()')
.quest-rewards(key='user.party.quest.completed', header-participant="$t('youReceived')", header-quest-owner="$t('questOwnerReceived')")
.modal-footer
@ -19,11 +17,12 @@
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
import quests from 'common/script/content/quests';
import Avatar from '../avatar';
import { mapState } from 'client/libs/store';
import percent from '../../../common/script/libs/percent';
import {maxHealth} from '../../../common/script/index';
import { maxHealth } from '../../../common/script/index';
export default {
components: {
@ -33,6 +32,7 @@ export default {
data () {
return {
maxHealth,
quests,
};
},
computed: {
@ -48,7 +48,7 @@ export default {
this.$root.$emit('hide::modal', 'quest-completed');
},
setQuestCompleted () {
// @TODO: set({"party.quest.completed":""})
this.$store.dispatch('user:set', {'party.quest.completed': ''});
this.close();
},
},

View file

@ -1,5 +1,5 @@
<template lang="pug">
b-modal#quest-invitation(:title="$t('questInvitation')", size='lg', :hide-footer="true")
b-modal#quest-invitation(v-if='user.party.quest.key', :title="$t('questInvitation')", size='lg', :hide-footer="true")
.modal-header
h4 {{ $t('questInvitation') }}
|&nbsp;{{quests[user.party.quest.key].text()}}

View file

@ -1,13 +1,11 @@
<template lang="pug">
b-modal#rebirth(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
b-modal#rebirth(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body.text-center
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
// @TODO: +achievementAvatar('sun',0)
achievement-avatar
div(ng-if='user.achievements.rebirthLevel < 100')
div(v-if='user.achievements.rebirthLevel < 100')
| {{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }}
div(ng-if='user.achievements.rebirthLevel >= 100')
div(v-if='user.achievements.rebirthLevel >= 100')
| {{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}

View file

@ -1,19 +1,18 @@
<template lang="pug">
b-modal#rebirth-enabled(:title="$t('rebirthNew')", size='lg', :hide-footer="true")
.modal-header
h4 {{ $t('rebirthNew') }}
b-modal#rebirth-enabled(:title="$t('rebirthNew')", size='md', :hide-footer="true")
.modal-body
figure
.col-12
.rebirth_orb
p
span {{ $t('rebirthUnlock') }}
p
span {{ $t('rebirthUnlock') }}
.modal-footer
button.btn.btn-default(@click='close()') {{ $t('close') }}
.col-12.text-center
button.btn.btn-primary(@click='close()') {{ $t('close') }}
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.rebirth_orb {
margin: 0 auto;
}
</style>

View file

@ -1,19 +1,17 @@
<template lang="pug">
b-modal#streak(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
b-modal#streak(:title="$t('streakAchievement')", size='md', :hide-footer="true")
.modal-body.text-center
h3(style='margin-bottom: 0') {{ $t('streakAchievement') }}
// @TODO: +achievementAvatar('thermometer',2.5)
achievement-avatar
h4(ng-if='user.achievements.streak === 1') {{ $t('firstStreakAchievement') }}
h4(ng-if='user.achievements.streak > 1') {{ $t('streakAchievementCount', {streaks: user.achievements.streak}) }}
h3(v-if='user.achievements.streak === 1') {{ $t('firstStreakAchievement') }}
h3(v-if='user.achievements.streak > 1') {{ $t('streakAchievementCount', {streaks: user.achievements.streak}) }}
p {{ $t('twentyOneDays') }}
p {{ $t('dontBreakStreak') }}
br
button.btn.btn-primary(@click='close()') {{ $t('dontStop') }}
.checkbox
label(style='display:inline-block') {{ $t('dontShowAgain') }}
input(type='checkbox', ng-model='user.preferences.suppressModals.streak', ng-change='set({"preferences.suppressModals.streak": user.preferences.suppressModals.streak?true: false})')
input(type='checkbox', v-model='user.preferences.suppressModals.streak', @change='suppressModals')
label {{ $t('dontShowAgain') }}
achievement-footer
</template>
@ -43,6 +41,10 @@ export default {
close () {
this.$root.$emit('hide::modal', 'streak');
},
suppressModals () {
let surpress = this.user.preferences.suppressModals.streak ? true : false;
this.$store.dispatch('user:set', {'preferences.suppressModals.streak': surpress});
},
},
};
</script>

View file

@ -1,10 +1,8 @@
<template lang="pug">
b-modal#testing(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content
.modal-body.text-center
h3 {{ $t('guildReminderTitle') }}
br
.scene_guilds.center-block
.scene_guilds
br
h4 {{ $t('guildReminderText1') }}
.modal-footer
@ -13,12 +11,12 @@
.col-6.text-center
button.btn.btn-secondary(@click='close()') {{ $t('guildReminderDismiss') }}
.col-6.text-center(@click='close()')
router-link.btn.btn-primary(:to="{ name: 'guildsDiscovery'}") {{ $t('guildReminderCTA') }}
.btn.btn-primary(@click='takeMethere()') {{ $t('guildReminderCTA') }}
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.scene_guilds {
margin: 0 auto;
}
</style>
@ -33,6 +31,10 @@ export default {
close () {
this.$root.$emit('hide::modal', 'testing');
},
takeMethere () {
this.$router.push('/groups/discovery');
this.close();
},
},
};
</script>

View file

@ -2,23 +2,22 @@
b-modal#testingletiant(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content
.modal-body.text-center
h3 {{ $t('guildReminderTitle') }}
br
.scene_guilds.center-block
.scene_guilds
br
h4 {{ $t('guildReminderText2') }}
.modal-footer
.container-fluid
.row
.col-xs-6.text-center
button.btn-lg.btn-default(@click='close()') {{ $t('guildReminderDismiss') }}
.col-xs-6.text-center
button.btn-lg.btn-primary(ui-sref='options.social.guilds.public', href='/#/options/groups/guilds/public', ng-click='$close()') {{ $t('guildReminderCTA') }}
.col-6.text-center
button.btn.btn-secondary(@click='close()') {{ $t('guildReminderDismiss') }}
.col-6.text-center
.btn.btn-primary(@click='takeMethere()') {{ $t('guildReminderCTA') }}
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.scene_guilds {
margin: 0 auto;
}
</style>
@ -33,6 +32,10 @@ export default {
close () {
this.$root.$emit('hide::modal', 'testingletiant');
},
takeMethere () {
this.$router.push('/groups/discovery');
this.close();
},
},
};
</script>

View file

@ -1,40 +1,38 @@
<template lang="pug">
b-modal#ultimate-gear(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
b-modal#ultimate-gear(:title="$t('modalAchievement')", size='md', :hide-footer="true")
.modal-body.text-center
h3(style='margin-bottom:0') {{ $t('modalAchievement') }}
// @TODO: +achievementAvatar('armor',2.5)
achievement-avatar
p {{ $t('gearAchievement') }}
br
table.multi-achievement
tr
td(ng-if='::user.achievements.ultimateGearSets.healer').multi-achievement
td(v-if='user.achievements.ultimateGearSets.healer').multi-achievement
.achievement-ultimate-healer2x.multi-achievement
| {{ $t('healer') }}
td(ng-if='::user.achievements.ultimateGearSets.wizard').multi-achievement
td(v-if='user.achievements.ultimateGearSets.wizard').multi-achievement
.achievement-ultimate-mage2x.multi-achievement
| {{ $t('mage') }}
td(ng-if='::user.achievements.ultimateGearSets.rogue').multi-achievement
td(v-if='user.achievements.ultimateGearSets.rogue').multi-achievement
.achievement-ultimate-rogue2x.multi-achievement
| {{ $t('rogue') }}
td(ng-if='::user.achievements.ultimateGearSets.warrior').multi-achievement
td(v-if='user.achievements.ultimateGearSets.warrior').multi-achievement
.achievement-ultimate-warrior2x.multi-achievement
| {{ $t('warrior') }}
br
div(ng-if='!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)')
p {{ $t('moreGearAchievements') }}
div(v-if='!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)')
p(v-html="$t('moreGearAchievements')")
br
.shop_armoire.pull-right
p {{ $t("armoireUnlocked") }}
.shop_armoire
p(v-html='$t("armoireUnlocked")')
br
button.btn.btn-primary(@click='close()') {{ $t('huzzah') }}
achievement-footer
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.shop_armoire {
margin: 0 auto;
}
</style>
@ -42,6 +40,7 @@
import bModal from 'bootstrap-vue/lib/components/modal';
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import { mapState } from 'client/libs/store';
export default {
components: {
@ -49,6 +48,9 @@ export default {
achievementFooter,
achievementAvatar,
},
computed: {
...mapState({user: 'user.data'}),
},
methods: {
close () {
this.$root.$emit('hide::modal', 'ultimate-gear');

View file

@ -1,45 +1,35 @@
<template lang="pug">
b-modal#won-challenge(:title="$t('guildReminderTitle')", size='lg', :hide-footer="true")
.modal-content(style='min-width:28em')
.modal-body.text-center
h3(style='margin-bottom: 0') {{ $t('wonChallenge') }}
h4(v-markdown='user.achievements.challenges[user.achievements.challenges.length - 1]')
.container-fluid
.row(style='margin-bottom:1em')
.col-4(style='padding:0')
.container-fluid
.row
.col-4(style='padding:0')
.col-4(style='padding:0')
.achievement-karaoke-2x(style='margin-top: 2em')
.col-4(style='padding:0')
.herobox(style='padding:0; width:0; height:7em')
.character-sprites(style='width:0')
// @TODO: +generatedAvatar({sleep: false})
avatar(:member='user')
.col-4(style='padding:0')
.container-fluid
.row
.col-4(style='padding:0')
.col-4(style='padding:0')
.achievement-karaoke-2x(style='margin-top: 2em')
p {{ $t('congratulations') }}
br
button.btn.btn-primary(@click='close()') {{ $t('hurray') }}
.modal-footer(style='margin-top:0', ng-init='loadWidgets()')
.container-fluid
.row
.col-3
a.twitter-share-button(href='https://twitter.com/intent/tweet?text=#{tweet}&via=habitica&url=#{env.BASE_URL}/social/won-challenge&count=none') {{ $t('tweet') }}
.col-4(style='margin-left:.8em')
.fb-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-layout='button')
.col-4(style='margin-left:.8em')
a.tumblr-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-notes='none')
b-modal#won-challenge(:title="$t('wonChallenge')", size='md', :hide-footer="true")
.modal-body.text-center
h4(v-markdown='user.achievements.challenges[user.achievements.challenges.length - 1]')
.row
.col-4
.achievement-karaoke-2x
.col-4
// @TODO: +generatedAvatar({sleep: false})
avatar(:member='user', :avatar-only='true')
.col-4
.achievement-karaoke-2x
p {{ $t('congratulations') }}
br
button.btn.btn-primary(@click='close()') {{ $t('hurray') }}
.modal-footer
.col-3
a.twitter-share-button(href='https://twitter.com/intent/tweet?text=#{tweet}&via=habitica&url=#{env.BASE_URL}/social/won-challenge&count=none') {{ $t('tweet') }}
.col-4(style='margin-left:.8em')
.fb-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-layout='button')
.col-4(style='margin-left:.8em')
a.tumblr-share-button(data-href='#{env.BASE_URL}/social/won-challenge', data-notes='none')
</template>
<style scope>
.dont-despair, .death-penalty {
margin-top: 1.5em;
.achievement-karaoke-2x {
margin: 0 auto;
margin-top: 6em;
}
.avatar {
margin-left: 0em;
}
</style>

View file

@ -1,5 +1,5 @@
<template lang="pug">
#app-header.row
#app-header.row(:class="{'hide-header': $route.path.startsWith('/group-plans')}")
create-party-modal
members-modal(:hide-badge="true")
member-details(:member="user")
@ -38,6 +38,10 @@
position: relative;
}
.hide-header {
display: none;
}
.sticky {
position: fixed !important;
width: 100%;

View file

@ -2,6 +2,7 @@
div
inbox-modal
creator-intro
profile
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm
.navbar-header
.logo.svg-icon(v-html="icons.logo")
@ -32,7 +33,7 @@ div
router-link.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
router-link.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
router-link.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
.nav-item.dropdown(tag="li", :class="{'active': $route.path.startsWith('/group-plans')}")
router-link.nav-item.dropdown(tag="li", :to="{name: 'groupPlan'}", :class="{'active': $route.path.startsWith('/group-plans')}")
a.nav-link(v-once) {{ $t('group') }}
.dropdown-menu
router-link.dropdown-item(v-for='group in groupPlans', :key='group._id', :to="{name: 'groupPlanDetailTaskInformation', params: {groupId: group._id}}") {{ group.name }}
@ -67,7 +68,7 @@ div
a.dropdown-item.edit-avatar.dropdown-separated(@click='showAvatar()')
h3 {{ user.profile.name }}
span.small-text {{ $t('editAvatar') }}
a.nav-link.dropdown-item(@click.prevent='showInbox()') {{ $t('inbox') }}
a.nav-link.dropdown-item(@click.prevent='showInbox()') {{ $t('messages') }}
a.dropdown-item(@click='showAvatar("backgrounds", "2017")') {{ $t('backgrounds') }}
router-link.dropdown-item(:to="{name: 'stats'}") {{ $t('stats') }}
router-link.dropdown-item(:to="{name: 'achievements'}") {{ $t('achievements') }}
@ -231,12 +232,14 @@ import logo from 'assets/svg/logo.svg';
import InboxModal from './userMenu/inbox.vue';
import notificationMenu from './notificationMenu';
import creatorIntro from './creatorIntro';
import profile from './userMenu/profile';
export default {
components: {
InboxModal,
notificationMenu,
creatorIntro,
profile,
},
data () {
return {

View file

@ -70,7 +70,7 @@
min-height: 100%;
}
small a {
small a, small a:hover {
color: #fff;
text-decoration: underline;
}

View file

@ -2,6 +2,7 @@
.row
challenge-modal(:challenge='challenge', v-on:updatedChallenge='updatedChallenge')
close-challenge-modal(:members='members', :challengeId='challenge._id')
challenge-member-progress-modal(:memberId='progressMemberId', :challengeId='challenge._id')
.col-8.standard-page
.row
@ -25,6 +26,14 @@
.svg-icon.gem-icon(v-html="icons.gemIcon")
| {{challenge.prize}}
.details(v-once) {{$t('prize')}}
.row(v-if='isLeader')
.col-6.offset-6
span
strong View Progress Of
b-dropdown.create-dropdown(text="Select a Participant")
b-dropdown-item(v-for="member in members", :key="member._id", @click="openMemberProgressModal(member._id)")
| {{ member.profile.name }}
.row
task-column.col-6(
v-for="column in columns",
@ -160,6 +169,7 @@ import closeChallengeModal from './closeChallengeModal';
import Column from '../tasks/column';
import TaskModal from '../tasks/taskModal';
import challengeModal from './challengeModal';
import challengeMemberProgressModal from './challengeMemberProgressModal';
import taskDefaults from 'common/script/libs/taskDefaults';
@ -172,6 +182,7 @@ export default {
components: {
closeChallengeModal,
challengeModal,
challengeMemberProgressModal,
TaskColumn: Column,
TaskModal,
bDropdown,
@ -197,6 +208,7 @@ export default {
creatingTask: {},
workingTask: {},
taskFormPurpose: 'create',
progressMemberId: '',
};
},
computed: {
@ -287,6 +299,10 @@ export default {
updatedChallenge (eventData) {
Object.assign(this.challenge, eventData.challenge);
},
openMemberProgressModal (memberId) {
this.progressMemberId = memberId;
this.$root.$emit('show::modal', 'challenge-member-modal');
},
},
};
</script>

View file

@ -0,0 +1,44 @@
<template lang="pug">
b-modal#challenge-member-modal(title="User Progress", size='lg')
.row
task-column.col-6(
v-for="column in columns",
:type="column",
:key="column",
:taskListOverride='tasksByType[column]')
</template>
<script>
import axios from 'axios';
import bModal from 'bootstrap-vue/lib/components/modal';
import Column from '../tasks/column';
export default {
props: ['challengeId', 'memberId'],
components: {
bModal,
TaskColumn: Column,
},
data () {
return {
columns: ['habit', 'daily', 'todo', 'reward'],
tasksByType: {
habit: [],
daily: [],
todo: [],
reward: [],
},
};
},
watch: {
async memberId (id) {
if (!id) return;
let response = await axios.get(`/api/v3/challenges/${this.challengeId}/members/${this.memberId}`);
let tasks = response.data.data.tasks;
tasks.forEach((task) => {
this.tasksByType[task.type].push(task);
});
},
},
};
</script>

View file

@ -337,6 +337,16 @@ export default {
alert(errors);
} else {
this.workingChallenge.timestamp = new Date().getTime();
let categoryKeys = this.workingChallenge.categories;
let serverCategories = [];
categoryKeys.forEach(key => {
let catName = this.categoriesHashByKey[key];
serverCategories.push({
slug: key,
name: catName,
});
});
this.workingChallenge.categories = serverCategories;
let challenge = await this.$store.dispatch('challenges:createChallenge', {challenge: this.workingChallenge});
// @TODO: When to remove from guild instead?

View file

@ -7,7 +7,7 @@
.row
.hr.col-12
div(v-for="(msg, index) in chat", v-if='chat && Object.keys(cachedProfileData).length > 0')
div(v-for="(msg, index) in chat", v-if='chat && (inbox || Object.keys(cachedProfileData).length > 0)')
// @TODO: is there a different way to do these conditionals? This creates an infinite loop
//.hr(v-if='displayDivider(msg)')
.hr-middle(v-once) {{ msg.timestamp }}
@ -143,7 +143,7 @@ import likedIcon from 'assets/svg/liked.svg';
import reportIcon from 'assets/svg/report.svg';
export default {
props: ['chat', 'groupId', 'groupName'],
props: ['chat', 'groupId', 'groupName', 'inbox'],
mixins: [styleHelper],
components: {
copyAsTodoModal,
@ -208,7 +208,7 @@ export default {
// @TODO: write an explination
if (screenPosition && Math.floor(screenPosition) + 1 > this.currentProfileLoadedEnd / 10) {
this.currentProfileLoadedEnd = 10 * (Math.floor(screenPosition) + 1);
} else {
} else if (screenPosition) {
return;
}

View file

@ -1,40 +1,42 @@
<template lang="pug">
b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='true')
b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='true', :class='{"page-2": modalPage > 1 && !editing}')
.section.row.welcome-section(v-if='modalPage === 1 && !editing')
.col-6.offset-3.text-center
h3(v-once) {{$t('welcomeTo')}}
.svg-icon.logo(v-html='icons.logoPurple')
.section.row
.section.avatar-section.row(:class='{"page-2": modalPage === 2}')
.col-6.offset-3
.user-creation-bg
avatar(:member='user')
div(v-if='modalPage == 2')
.section(v-if='modalPage === 2')
// @TODO Implement in V2 .section.row
.col-12.text-center
button.btn.btn-secondary(v-once) {{$t('randomize')}}
.section.row.text-center.customize-menu
div(:class='{"col-3": !editing, "col-2 offset-1": editing}')
.menu-item(@click='changeTopPage("body", "size")')
.svg-icon(v-html='icons.bodyIcon')
strong(v-once) {{$t('body')}}
div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("skin", "color")')
.svg-icon(v-html='icons.skinIcon')
strong(v-once) {{$t('skin')}}
div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("hair", "color")')
.svg-icon(v-html='icons.hairIcon')
strong(v-once) {{$t('hair')}}
div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("extra", "glasses")')
.svg-icon(v-html='icons.accessoriesIcon')
strong(v-once) {{$t('extra')}}
.col-2(v-if='editing')
.menu-item(@click='changeTopPage("backgrounds", "2017")')
.svg-icon(v-html='icons.backgroundsIcon')
strong(v-once) {{$t('backgrounds')}}
.container.section.text-center.customize-menu
.row
div(:class='{"col-3": !editing, "col-2 offset-1": editing}')
.menu-item(@click='changeTopPage("body", "size")')
.svg-icon(v-html='icons.bodyIcon')
strong(v-once) {{$t('body')}}
div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("skin", "color")')
.svg-icon(v-html='icons.skinIcon')
strong(v-once) {{$t('skin')}}
div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("hair", "color")')
.svg-icon(v-html='icons.hairIcon')
strong(v-once) {{$t('hair')}}
div(:class='{"col-3": !editing, "col-2": editing}')
.menu-item(@click='changeTopPage("extra", "glasses")')
.svg-icon(v-html='icons.accessoriesIcon')
strong(v-once) {{$t('extra')}}
.col-2(v-if='editing')
.menu-item(@click='changeTopPage("backgrounds", "2017")')
.svg-icon(v-html='icons.backgroundsIcon')
strong(v-once) {{$t('backgrounds')}}
.section.customize-section(v-if='activeTopPage === "body"')
.row.sub-menu.col-6.offset-3.text-center
.col-2.offset-4.sub-menu-item(@click='changeSubPage("size")', :class='{active: activeSubPage === "size"}')
@ -43,20 +45,16 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
strong(v-once) {{$t('shirt')}}
.row(v-if='activeSubPage === "size"')
.col-12.customize-options.size-options
.slim_shirt_black.option(@click='set({"preferences.size":"slim"})', :class='{active: user.preferences.size === "slim"}')
.broad_shirt_black.option(@click='set({"preferences.size":"broad"})', :class='{active: user.preferences.size === "broad"}')
.option(v-for='option in ["slim", "broad"]', :class='{active: user.preferences.size === option}')
.sprite(:class="`${option}_shirt_black`", @click='set({"preferences.size": option})')
.row(v-if='activeSubPage === "shirt"')
.col-12.customize-options
.slim_shirt_black.option(@click='set({"preferences.shirt":"black"})', :class='{active: user.preferences.shirt === "black"}')
.slim_shirt_blue.option(@click='set({"preferences.shirt":"blue"})', :class='{active: user.preferences.shirt === "blue"}')
.slim_shirt_green.option(@click='set({"preferences.shirt":"green"})', :class='{active: user.preferences.shirt === "green"}')
.slim_shirt_pink.option(@click='set({"preferences.shirt":"pink"})', :class='{active: user.preferences.shirt === "pink"}')
.slim_shirt_white.option(@click='set({"preferences.shirt":"white"})', :class='{active: user.preferences.shirt === "white"}')
.slim_shirt_yellow.option(@click='set({"preferences.shirt":"yellow"})', :class='{active: user.preferences.shirt === "yellow"}')
.col-12.customize-options
.option(v-for='option in ["black", "blue", "green", "pink", "white", "yellow"]', :class='{active: user.preferences.shirt === option}')
.sprite(:class="`slim_shirt_${option}`", @click='set({"preferences.shirt": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["convict", "cross", "fire", "horizon", "ocean", "purple", "rainbow", "redblue", "thunder", "tropical", "zombie"]',
:class='[`broad_shirt_${option}`, {active: user.preferences.shirt === option}]',
@click='set({"preferences.shirt": option})')
:class='{active: user.preferences.shirt === option}')
.sprite(:class="`broad_shirt_${option}`", @click='set({"preferences.shirt": option})')
.section.customize-section(v-if='activeTopPage === "skin"')
.row.sub-menu.col-6.offset-3.text-center
@ -64,14 +62,19 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
strong(v-once) {{$t('color')}}
.row
.col-12.customize-options
.skin_ddc994.option(@click='set({"preferences.skin":"ddc994"})', :class='{active: user.preferences.skin === "ddc994"}')
.skin_f5a76e.option(@click='set({"preferences.skin":"f5a76e"})', :class='{active: user.preferences.skin === "f5a76e"}')
.skin_ea8349.option(@click='set({"preferences.skin":"ea8349"})', :class='{active: user.preferences.skin === "ea8349"}')
.skin_c06534.option(@click='set({"preferences.skin":"c06534"})', :class='{active: user.preferences.skin === "c06534"}')
.skin_98461a.option(@click='set({"preferences.skin":"98461a"})', :class='{active: user.preferences.skin === "98461a"}')
.skin_915533.option(@click='set({"preferences.skin":"915533"})', :class='{active: user.preferences.skin === "915533"}')
.skin_c3e1dc.option(@click='set({"preferences.skin":"c3e1dc"})', :class='{active: user.preferences.skin === "c3e1dc"}')
.skin_6bd049.option(@click='set({"preferences.skin":"6bd049"})', :class='{active: user.preferences.skin === "6bd049"}')
.option(v-for='option in ["ddc994", "f5a76e", "ea8349", "c06534", "98461a", "915533", "c3e1dc", "6bd049"]',
:class='{active: user.preferences.skin === option}')
.skin.sprite(:class="`skin_${option}`", @click='set({"preferences.skin": option})')
.row(v-if='editing')
.col-12.customize-options
.option(v-for='option in ["eb052b", "f69922", "f5d70f", "0ff591", "2b43f6", "d7a9f7", "800ed0", "rainbow"]',
:class='{active: user.preferences.skin === option}')
.skin.sprite(:class="`skin_${option}`", @click='set({"preferences.skin": option})')
.row(v-if='editing')
.col-12.customize-options
.option(v-for='option in ["bear", "cactus", "fox", "lion", "panda", "pig", "tiger", "wolf"]',
:class='{active: user.preferences.skin === option}')
.skin.sprite(:class="`skin_${option}`", @click='set({"preferences.skin": option})')
.section.customize-section(v-if='activeTopPage === "hair"')
.row.sub-menu.col-6.offset-3.text-center
@ -79,27 +82,51 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
strong(v-once) {{$t('color')}}
.col-2.text-center.sub-menu-item(@click='changeSubPage("bangs")', :class='{active: activeSubPage === "bangs"}')
strong(v-once) {{$t('bangs')}}
.col-2.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}')
.col-3.text-center.sub-menu-item(@click='changeSubPage("ponytail")', :class='{active: activeSubPage === "ponytail"}')
strong(v-once) {{$t('ponytail')}}
.row(v-if='activeSubPage === "color"')
.col-12.customize-options
.hair_bangs_1_white.option(@click='set({"preferences.hair.color": "white"})', :class='{active: user.preferences.hair.color === "white"}')
.hair_bangs_1_brown.option(@click='set({"preferences.hair.color": "brown"})', :class='{active: user.preferences.hair.color === "brown"}')
.hair_bangs_1_blond.option(@click='set({"preferences.hair.color": "blond"})', :class='{active: user.preferences.hair.color === "blond"}')
.hair_bangs_1_red.option(@click='set({"preferences.hair.color": "red"})', :class='{active: user.preferences.hair.color === "red"}')
.hair_bangs_1_black.option(@click='set({"preferences.hair.color": "black"})', :class='{active: user.preferences.hair.color === "black"}')
.option(v-for='option in ["white", "brown", "blond", "red", "black"]',
:class='{active: user.preferences.hair.color === option}')
.color-bangs.sprite(:class="`hair_bangs_1_${option}`", @click='set({"preferences.hair.color": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["rainbow", "yellow", "green", "purple", "blue", "TRUred"]',
:class='{active: user.preferences.hair.color === option}')
.color-bangs.sprite(:class="`hair_bangs_1_${option}`", @click='set({"preferences.hair.color": option})')
.row(v-if='activeSubPage === "bangs"')
.col-12.customize-options
.head_0.option(@click='set({"preferences.hair.bangs": 0})', :class="[{ active: user.preferences.hair.bangs === 0 }, 'hair_bangs_0_' + user.preferences.hair.color]")
.option(@click='set({"preferences.hair.bangs": 1})', :class="[{ active: user.preferences.hair.bangs === 1 }, 'hair_bangs_1_' + user.preferences.hair.color]")
.option(@click='set({"preferences.hair.bangs": 2})',:class="[{ active: user.preferences.hair.bangs === 2 }, 'hair_bangs_2_' + user.preferences.hair.color]")
.option(@click='set({"preferences.hair.bangs": 3})', :class="[{ active: user.preferences.hair.bangs === 3 }, 'hair_bangs_3_' + user.preferences.hair.color]")
.option(@click='set({"preferences.hair.bangs": 4})', :class="[{ active: user.preferences.hair.bangs === 4 }, 'hair_bangs_4_' + user.preferences.hair.color]")
.head_0.option(@click='set({"preferences.hair.bangs": 0})',
:class="[{ active: user.preferences.hair.bangs === 0 }, 'hair_bangs_0_' + user.preferences.hair.color]")
.option(v-for='option in ["1", "2", "3", "4"]',
:class='{active: user.preferences.hair.bangs === option}')
.bangs.sprite(:class="`hair_bangs_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.bangs": option})')
.row(v-if='activeSubPage === "ponytail"')
.col-12.customize-options
.head_0.option(@click='set({"preferences.hair.base": 0})', :class="[{ active: user.preferences.hair.base === 0 }, 'hair_base_0_' + user.preferences.hair.color]")
.hair_base_1_blond.option(@click='set({"preferences.hair.base": 1})', :class="[{ active: user.preferences.hair.base === 1 }, 'hair_base_1_' + user.preferences.hair.color]")
.hair_base_3_blond.option(@click='set({"preferences.hair.base": 3})', :class="[{ active: user.preferences.hair.base === 3 }, 'hair_base_3_' + user.preferences.hair.color]")
.option(v-for='option in ["1", "3"]',
:class='{active: user.preferences.hair.base === option}')
.base.sprite(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["2", "4", "5", "6", "7", "8"]',
:class='{active: user.preferences.hair.base === option}')
.base.sprite(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["9", "10", "11", "12", "13", "14"]',
:class='{active: user.preferences.hair.base === option}')
.base.sprite(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["15", "16", "17", "18", "19", "20"]',
:class='{active: user.preferences.hair.base === option}')
.base.sprite(:class="`hair_base_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.base": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["1", "2", "3"]',
:class='{active: user.preferences.hair.beard === option}')
.base.sprite(:class="`hair_beard_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.beard": option})')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["1", "2"]',
:class='{active: user.preferences.hair.mustache === option}')
.base.sprite(:class="`hair_mustache_${option}_${user.preferences.hair.color}`", @click='set({"preferences.hair.mustache": option})')
.section.container.customize-section(v-if='activeTopPage === "extra"')
.row.sub-menu.col-6.offset-3.text-center
@ -118,31 +145,24 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.eyewear_special_redTopFrame.option(@click='equip("eyewear_special_redTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_redTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_redTopFrame"}')
.eyewear_special_whiteTopFrame.option(@click='equip("eyewear_special_whiteTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_whiteTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_whiteTopFrame"}')
.eyewear_special_yellowTopFrame.option(@click='equip("eyewear_special_yellowTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_yellowTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_yellowTopFrame"}')
.col-12.customize-options(v-if='editing')
.option(v-for='option in ["bearEars", "cactusEars", "foxEars", "lionEars", "pandaEars", "pigEars", "tigerEars", "wolfEars"]',
:class='{active: user.preferences.costume ? user.items.gear.costume.headAccessory === `eyewear_special_${option}` : user.items.gear.equipped.headAccessory === `eyewear_special_${option}`}')
.sprite(:class="`.eyewear_special_${option}`", @click='equip(`eyewear_special_${option}`)')
.row(v-if='activeSubPage === "wheelchair"')
.col-12.customize-options.weelchairs
.option(@click='set({"preferences.chair": "none"})', :class='{active: user.preferences.chair === "none"}')
| None
.option(@click='set({"preferences.chair": "black"})', :class='{active: user.preferences.chair === "black"}')
.button_chair_black
.option(@click='set({"preferences.chair": "blue"})', :class='{active: user.preferences.chair === "blue"}')
.button_chair_blue
.option(@click='set({"preferences.chair": "green"})', :class='{active: user.preferences.chair === "green"}')
.button_chair_green
.option(@click='set({"preferences.chair": "pink"})', :class='{active: user.preferences.chair === "pink"}')
.button_chair_pink
.option(@click='set({"preferences.chair": "red"})', :class='{active: user.preferences.chair === "red"}')
.button_chair_red
.option(@click='set({"preferences.chair": "yellow"})', :class='{active: user.preferences.chair === "yellow"}')
.button_chair_yellow
.option(v-for='option in ["black", "blue", "green", "pink", "red", "yellow"]',
:class='{active: user.preferences.chair === option}')
.chair.sprite(:class="`button_chair_${option}`", @click='set({"preferences.chair": option})')
.row(v-if='activeSubPage === "flower"')
.col-12.customize-options
.head_0.option(@click='set({"preferences.hair.flower":0})', :class='{active: user.preferences.hair.flower === 0}')
.hair_flower_1.option(@click='set({"preferences.hair.flower":1})', :class='{active: user.preferences.hair.flower === 1}')
.hair_flower_2.option(@click='set({"preferences.hair.flower":2})', :class='{active: user.preferences.hair.flower === 2}')
.hair_flower_3.option(@click='set({"preferences.hair.flower":3})', :class='{active: user.preferences.hair.flower === 3}')
.hair_flower_4.option(@click='set({"preferences.hair.flower":4})', :class='{active: user.preferences.hair.flower === 4}')
.hair_flower_5.option(@click='set({"preferences.hair.flower":5})', :class='{active: user.preferences.hair.flower === 5}')
.hair_flower_6.option(@click='set({"preferences.hair.flower":6})', :class='{active: user.preferences.hair.flower === 6}')
.option(v-for='option in ["1", "2", "3", "4", "5", "6"]',
:class='{active: user.preferences.hair.flower === option}')
.sprite(:class="`hair_flower_${option}`", @click='set({"preferences.hair.flower": option})')
.row(v-if='activeSubPage === "flower"')
.col-12.customize-options
// button.customize-option(ng-repeat='item in ::getGearArray("animal")', class='{{::item.key}}',
@ -194,50 +214,58 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
h2 I want to work on:
.section.row
.col-4.offset-2
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='work', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('work') }}
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='exercise', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('exercise') }}
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='health_wellness', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('health_wellness') }}
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='school', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('school') }}
.col-4
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='chores', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('chores') }}
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='creativity', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('creativity') }}
div
.task-option
label.custom-control.custom-checkbox
input.custom-control-input(type="checkbox")
input.custom-control-input(type="checkbox", value='self_care', v-model='taskCategories')
span.custom-control-indicator
span.custom-control-description(v-once) {{ $t('self_care') }}
.section.row.justin-message-section(:class='{top: modalPage > 1}')
.col-9
.justin-message(v-if='modalPage == 1')
p(v-once) {{$t('justinIntroMessage1')}}
p(v-once) {{$t('justinIntroMessage2')}}
.justin-message(v-if='modalPage > 1')
p(v-once) {{$t('justinIntroMessage3')}}
.section.row.justin-message-section(:class='{top: modalPage > 1}', v-if='!editing')
.col-12
.justin-message
.featured-label
span.rectangle
span.text Justin
span.rectangle
.npc_justin_textbox
div(v-if='modalPage === 1')
p(v-once) {{$t('justinIntroMessage1')}}
p(v-once) {{$t('justinIntroMessage2')}}
div(v-if='modalPage === 2')
p So how would you like to look? Dont worry, you can change this later.
div(v-if='modalPage === 3')
p(v-once) {{$t('justinIntroMessage3')}}
.section.container.footer(v-if='!editing')
.row
@ -258,7 +286,15 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
</template>
<style>
#avatar-modal_modal_body {
.page-2 #avatar-modal__BV_body_ {
margin-top: 8em;
}
.page-2 .modal-content {
margin-top: 7em;
}
#avatar-modal_modal_body, #avatar-modal__BV_body_ {
padding: 0;
}
</style>
@ -285,6 +321,10 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
margin-top: 2em;
}
.avatar-section.page-2 {
min-height: 150px;
}
.welcome-section {
margin-top: 5em;
margin-bottom: 5em;
@ -292,18 +332,20 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.logo {
width: 190px;
margin: 0 auto;
}
.user-creation-bg {
background-image: url('~client/assets/creator/creator-hills-bg.png');
height: 105px;
width: 219px;
margin: 0 auto;
}
.avatar {
position: absolute;
top: -23px;
left: 48px;
left: 9.2em;
}
.justin-message {
@ -311,7 +353,27 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
height: 144px;
width: 400px;
padding: 2em;
margin-left: 1.5em;
margin: 0 auto;
position: relative;
.featured-label {
position: absolute;
top: -1em;
.text {
min-height: auto;
color: $white;
}
}
.npc_justin_textbox {
position: absolute;
right: 1em;
top: -3.6em;
width: 48px;
height: 52px;
background-image: url('~client/assets/images/justin_textbox.png');
}
}
.justin-message-section {
@ -321,7 +383,8 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.justin-message-section.top {
position: absolute;
top: -15em;
top: -16em;
left: 13em;
}
.circles {
@ -346,6 +409,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
width: 32px;
height: 32px;
margin: 0 auto;
color: #6133B4;
}
.menu-item:hover {
@ -369,14 +433,49 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
border-bottom: 2px solid $purple-200;
}
.customize-options .option {
display: inline-block;
padding: 2em;
vertical-align: bottom;
.customize-section {
text-align: center;
}
.size-options {
padding-left: 9em;
.customize-options .option {
display: inline-block;
vertical-align: bottom;
width: 90px;
height: 90px;
.sprite {
margin-top: -2em;
margin-left: -1em;
}
.skin {
margin-top: -.5em;
}
.chair {
margin-top: 1em;
margin-left: 1em;
}
.hair {
margin-top: 0em;
margin-left: -2em;
}
.color-bangs {
margin-top: 0em;
margin-left: -1em;
}
.bangs {
margin-top: 0em;
margin-left: -1em;
}
.base {
margin-top: -1em;
margin-left: -2em;
}
}
.weelchairs .option {
@ -402,6 +501,11 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
.interests-section {
margin-top: 7em;
.task-option {
margin: 0 auto;
width: 70%;
}
}
#backgrounds {
@ -462,7 +566,6 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
}
.footer {
position: absolute;
padding-bottom: 1em;
bottom: 0;
width: 100%;
@ -488,7 +591,6 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
}
.next {
color: #6133b4;
font-weight: bold;
display: inline-block;
padding: 0.4em;
@ -564,6 +666,134 @@ import gem from 'assets/svg/gem.svg';
import pin from 'assets/svg/pin.svg';
import { isPinned } from 'common/script/ops/pinnedGearUtils';
let tasksByCategory = {
work: [
{
type: 'habit',
text: 'Process email',
up: true,
down: false,
},
{
type: 'daily',
text: 'Most important task >> Worked on todays most important task',
notes: '(ADD) Notes: Tap to specify your most important task',
},
{
type: 'todo',
text: 'Work project >> Complete work project',
notes: '(ADD) Notes: Tap to specify the name of your current project + set a due date!',
},
],
exercise: [
{
type: 'habit',
text: '10 min cardio >> + 10 minutes cardio',
up: true,
down: false,
},
{
type: 'daily',
text: 'Stretching >> Daily workout routine',
notes: '(ADD) Notes: Tap to choose your schedule and specify exercises!',
},
{
type: 'todo',
text: 'Set up workout schedule',
notes: '(ADD) Notes: Tap to add a checklist!',
},
],
health_wellness: [ // eslint-disable-line
{
type: 'habit',
text: 'Eat Health/Junk Food',
up: true,
down: true,
},
{
type: 'daily',
text: 'Floss',
notes: '(ADD) Notes: Tap to make any changes!',
},
{
type: 'todo',
text: 'Schedule check-up >> Brainstorm a healthy change',
notes: '(ADD) Notes: Tap to add checklists!',
},
],
school: [
{
type: 'habit',
text: 'Study/Procrastinate',
up: true,
down: true,
},
{
type: 'daily',
text: 'Finish homework',
notes: '(ADD) Notes: Tap to choose your homework schedule!',
},
{
type: 'todo',
text: 'Finish assignment for class',
notes: '(ADD) [Notes: Tap to name the assignment and choose a due date!]',
},
],
self_care: [ // eslint-disable-line
{
type: 'habit',
text: 'Take a short break',
up: true,
down: false,
},
{
type: 'daily',
text: '5 minutes of quiet breathing',
notes: '(ADD) Notes: Tap to choose your schedule!',
},
{
type: 'todo',
text: 'Engage in a fun activity',
notes: '(ADD) Notes: Tap to specify what you plan to do!',
},
],
chores: [
{
type: 'habit',
text: '10 minutes cleaning',
up: true,
down: false,
},
{
type: 'daily',
text: 'Wash dishes',
notes: '(ADD) Notes: Tap to choose your schedule!',
},
{
type: 'todo',
text: 'Organize closet >> Organize clutter',
notes: '(ADD) Notes: Tap to specify the cluttered area!',
},
],
creativity: [
{
type: 'habit',
text: 'Study a master of the craft >> + Practiced a new creative technique',
up: true,
down: false,
},
{
type: 'daily',
text: 'Work on creative project',
notes: '(ADD) Notes: Tap to specify the name of your current project + set the schedule!',
},
{
type: 'todo',
text: 'Finish creative project',
notes: '(ADD) Notes: Tap to specify the name of your project',
},
],
};
export default {
mixins: [guide, notifications],
@ -593,6 +823,7 @@ export default {
modalPage: 1,
activeTopPage: 'body',
activeSubPage: 'size',
taskCategories: [],
};
},
watch: {
@ -663,7 +894,20 @@ export default {
this.$store.dispatch('common:equip', {key, type: 'equipped'});
this.user.items.gear.equipped[key] = !this.user.items.gear.equipped[key];
},
done () {
async done () {
let tasksToCreate = [];
this.taskCategories.forEach(category => {
tasksToCreate = tasksToCreate.concat(tasksByCategory[category]);
});
// @TODO: Move to the action
let response = await axios.post('/api/v3/tasks/user', tasksToCreate);
let tasks = response.data.data;
tasks.forEach(task => {
this.$store.state.user.data.tasksOrder[`${task.type}s`].unshift(task._id);
Object.assign(this.$store.state.tasks.data[`${task.type}s`][0], task);
});
this.$root.$emit('hide::modal', 'avatar-modal');
this.$router.push('/');
this.$store.dispatch('user:set', {

View file

@ -289,6 +289,9 @@ export default {
groupId: this.groupId,
});
let members = await this.$store.dispatch('members:getGroupMembers', {groupId: this.groupId});
this.group.members = members;
let tasks = await this.$store.dispatch('tasks:getGroupTasks', {
groupId: this.groupId,
});

View file

@ -39,7 +39,8 @@
.col-6
.col-6
.button-container
button.btn.btn-success(class='btn-success', v-if='isLeader') {{ $t('upgrade') }}
button.btn.btn-success(class='btn-success', v-if='isLeader && !group.purchased.active', @click='upgradeGroup()')
| {{ $t('upgrade') }}
.button-container
button.btn.btn-primary(b-btn, @click="updateGuild", v-once, v-if='isLeader') {{ $t('edit') }}
.button-container
@ -673,6 +674,10 @@ export default {
// $rootScope.hardRedirect('/#/options/groups/party');
// });
},
upgradeGroup () {
this.$store.state.upgradingGroup = this.group;
this.$router.push('/group-plans');
},
// @TODO: Move to notificatin component
async leaveOldPartyAndJoinNewParty () {
let newPartyName = 'where does this come from';

View file

@ -1,7 +1,7 @@
<template lang="pug">
div
amazon-payments-modal(:amazon-payments='amazonPayments')
div(v-if='activePage === PAGES.BENEFITS')
div
.header
h1.text-center Need more for your Group?
.row
@ -23,7 +23,7 @@ div
h2 In-Game Benefits
p Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.
.container.payment-options
.container.payment-options(v-if='upgradingGroup._id')
h1.text-center.purple-header Are you ready to upgrade?
.row
.col-6.offset-3.text-center
@ -36,7 +36,7 @@ div
.number 3
.name Each Individual Group Member
.box
.box.payment-providers
h3 Choose your payment method
.box.payment-button(@click='createGroup(PAYMENTS.STRIPE)')
p Credit Card
@ -44,9 +44,30 @@ div
.box.payment-button(@click='createGroup(PAYMENTS.AMAZON)')
| Amazon Pay
.standard-page(v-if='activePage === PAGES.CREATE_GROUP')
h1.text-center {{ $t('createAGroup') }}
.col-6.offset-3
.container.col-6.offset-3.create-option(v-if='!upgradingGroup._id')
.row
h1.col-12.text-center.purple-header Create your Group today!
.row
.col-12.text-center
button.btn.btn-primary.create-group(@click='launchModal("create")') Create Your New Group
.row.pricing
.col-5
.dollar $
.number 9
.name
div Group Owner
div Subscription
.col-1
.plus +
.col-6
.dollar $
.number 3
.name
div Each Additional
div Member
b-modal#group-plan-modal(title="Empty", size='md', hide-footer=true)
.col-12(v-if='activePage === PAGES.CREATE_GROUP')
.form-group
label.control-label(for='new-group-name') Name
input.form-control#new-group-name.input-medium.option-content(required, type='text', placeholder="Name", v-model='newGroup.name')
@ -76,9 +97,17 @@ div
input(type='checkbox', v-model='newGroup.leaderOnly.challenges')
| {{ $t('leaderOnlyChallenges') }}
.form-group(v-if='type === "party"')
button.btn.btn-default.form-control(@click='pay()', :value="$t('create')")
button.btn.btn-default.form-control(@click='createGroup()', :value="$t('create')")
.form-group
button.btn.btn-primary.btn-lg.btn-block(@click="pay()", :disabled="!newGroupIsReady") {{ $t('create') }}
button.btn.btn-primary.btn-lg.btn-block(@click="createGroup()", :disabled="!newGroupIsReady") {{ $t('create') }}
.col-12(v-if='activePage === PAGES.PAY')
.payment-providers
h3 Choose your payment method
.box.payment-button(@click='pay(PAYMENTS.STRIPE)')
p Credit Card
p Powered by Stripe
.box.payment-button(@click='pay(PAYMENTS.AMAZON)')
| Amazon Pay
</template>
<style lang="scss" scoped>
@ -108,12 +137,50 @@ div
text-align: center;
}
button.create-group {
width: 330px;
height: 96px;
}
.purple-header {
color: #6133b4;
font-size: 48px;
margin-top: 1em;
}
.pricing {
margin-top: 2em;
margin-bottom: 4em;
.dollar, .number, .name {
display: inline-block;
vertical-align: bottom;
color: #a5a1ac;
}
.plus {
font-size: 34px;
color: #a5a1ac;
}
.dollar {
margin-bottom: 1.5em;
font-size: 32px;
font-weight: bold;
}
.name {
font-size: 24px;
margin-bottom: .8em;
margin-left: .5em;
}
.number {
font-size: 72px;
font-weight: bolder;
}
}
.payment-options {
margin-bottom: 4em;
@ -152,25 +219,28 @@ div
display: inline-block;
vertical-align: bottom;
}
}
.payment-button {
width: 200px;
height: 80px;
margin-bottom: .5em;
padding: .5em;
display: block;
}
.payment-button {
width: 200px;
height: 80px;
margin-bottom: .5em;
padding: .5em;
display: block;
}
</style>
<script>
import paymentsMixin from '../../mixins/payments';
import amazonPaymentsModal from '../payments/amazonModal';
import { mapState } from 'client/libs/store';
import bModal from 'bootstrap-vue/lib/components/modal';
export default {
mixins: [paymentsMixin],
components: {
amazonPaymentsModal,
bModal,
},
data () {
return {
@ -179,6 +249,7 @@ export default {
PAGES: {
CREATE_GROUP: 'create-group',
UPGRADE_GROUP: 'upgrade-group',
PAY: 'pay',
},
// @TODO: Import from payment library?
PAYMENTS: {
@ -213,17 +284,26 @@ export default {
newGroupIsReady () {
return Boolean(this.newGroup.name);
},
upgradingGroup () {
return this.$store.state.upgradingGroup;
},
// @TODO: can we move this to payment mixin?
...mapState({user: 'user.data'}),
},
methods: {
launchModal () {
this.changePage(this.PAGES.CREATE_GROUP);
this.$root.$emit('show::modal', 'group-plan-modal');
},
changePage (page) {
this.activePage = page;
window.scrollTo(0, 0);
},
createGroup (paymentType) {
this.paymentMethod = paymentType;
this.changePage(this.PAGES.CREATE_GROUP);
createGroup () {
this.changePage(this.PAGES.PAY);
},
pay () {
pay (paymentMethod) {
this.paymentMethod = paymentMethod;
let subscriptionKey = 'group_monthly'; // @TODO: Get from content API?
if (this.paymentMethod === this.PAYMENTS.STRIPE) {
this.showStripe({

View file

@ -41,12 +41,6 @@ div
.svg-icon.inline(v-html="icons.removeIcon")
span.text {{$t('removeManager2')}}
.row.gradient(v-if='members.length > 3')
b-modal#remove-member(:title="$t('confirmRemoveMember')")
button(@click='confirmRemoveMember(member)', v-once) {{$t('remove')}}
b-modal#private-message(:title="$t('confirmRemoveMember')")
button(@click='confirmRemoveMember(member)', v-once) {{$t('remove')}}
</template>
<style lang='scss' scoped>

View file

@ -1,7 +1,6 @@
<template lang="pug">
div
profile
.d-flex.member-details(:class="{ condensed, expanded }", @click='showMemberModal()')
.d-flex.member-details(:class="{ condensed, expanded }", @click='showMemberModal(member)')
avatar(:member="member",
@click.native="$emit('click')",
@mouseover.native="$emit('onHover')",
@ -221,8 +220,8 @@ export default {
},
methods: {
percent,
showMemberModal () {
// @TODO: set viewing users in $store?
showMemberModal (member) {
this.$store.state.profileUser = member;
this.$root.$emit('show::modal', 'profile');
},
},

View file

@ -9,25 +9,25 @@ div.item-with-icon.item-notifications.dropdown
a.dropdown-item(v-if='user.purchased.plan.mysteryItems.length', @click='go("/inventory/items")')
span.glyphicon.glyphicon-gift
span {{ $t('newSubscriberItem') }}
a.dropdown-item(v-for='party in user.invitations.parties')
a.dropdown-item(v-for='(party, index) in user.invitations.parties')
div
span.glyphicon.glyphicon-user
span {{ $t('invitedTo', {name: party.name}) }}
div
span(@click='accept(party)') Accept
span(@click='reject(party)') Reject
button.btn.btn-primary(@click='accept(party, index, "party")') Accept
button.btn.btn-primary(@click='reject(party, index, "party")') Reject
a.dropdown-item(v-if='user.flags.cardReceived', @click='go("/inventory/items")')
span.glyphicon.glyphicon-envelope
span {{ $t('cardReceived') }}
a.dropdown-item(@click='clearCards()', :popover="$t('clear')",
popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true')
a.dropdown-item(v-for='guild in user.invitations.guilds')
a.dropdown-item(v-for='(guild, index) in user.invitations.guilds')
div
span.glyphicon.glyphicon-user
span {{ $t('invitedTo', {name: guild.name}) }}
div
span(@click='accept(guild)') Accept
span(@click='reject(guild)') Reject
button.btn.btn-primary(@click='accept(guild, index, "guild")') Accept
button.btn.btn-primary(@click='reject(guild, index, "guild")') Reject
a.dropdown-item(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points',
@click='go("/user/profile")')
span.glyphicon.glyphicon-plus-sign
@ -35,7 +35,8 @@ div.item-with-icon.item-notifications.dropdown
a.dropdown-item(v-for='(message, key) in user.newMessages', v-if='message.value', @click='navigateToGroup(key)')
span.glyphicon.glyphicon-comment
span {{message.name}}
a.dropdown-item(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
span.clear-button(@click='clearMessages(k)', :popover="$t('clear')",
popover-placement='right', popover-trigger='mouseenter', popover-append-to-body='true') Clear
a.dropdown-item(v-for='(notification, index) in user.groupNotifications', @click='viewGroupApprovalNotification(notification, index, true)')
span(:class="groupApprovalNotificationIcon(notification)")
span
@ -51,6 +52,10 @@ div.item-with-icon.item-notifications.dropdown
<style lang='scss' scoped>
@import '~client/assets/scss/colors.scss';
.clear-button {
margin-left: .5em;
}
.item-notifications {
width: 44px;
}
@ -273,13 +278,28 @@ export default {
await this.$store.dispatch('guilds:rejectInvite', {groupId: group.id});
// @TODO: User.sync();
},
async accept (group) {
async accept (group, index, type) {
if (group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
return;
}
if (type === 'party') {
// @TODO: pretty sure mutability is wrong. Need to check React docs
this.user.invitations.party.splice(index, 1);
} else {
this.user.invitations.guilds.splice(index, 1);
}
if (type === 'party') {
this.user.party._id = group.id;
this.$router.push('/groups/party');
} else {
this.user.guilds.push(group.id);
this.$router.push(`/groups/guild/${group.id}`);
}
// @TODO: check for party , type: 'myGuilds'
await this.$store.dispatch('guilds:join', {guildId: group.id});
// this.user.guilds.push(this.group._id);
},
},
};

View file

@ -1,6 +1,7 @@
<template lang="pug">
div
yesterdaily-modal(:yesterDailies='yesterDailies')
armoire-empty
new-stuff
death
low-health
@ -18,6 +19,9 @@ div
joined-guild
joined-challenge
invited-friend
login-incentives(:data='notificationData')
quest-completed
quest-invitation
</template>
<script>
@ -51,6 +55,7 @@ import rebirth from './achievements/rebirth';
import streak from './achievements/streak';
import ultimateGear from './achievements/ultimateGear';
import wonChallenge from './achievements/wonChallenge';
import loginIncentives from './achievements/login-incentives';
export default {
mixins: [notifications, guide],
@ -77,6 +82,7 @@ export default {
rebirthEnabled,
dropsEnabled,
contributor,
loginIncentives,
},
data () {
// Levels that already display modals and should not trigger generic Level Up
@ -92,6 +98,7 @@ export default {
return {
yesterDailies: [],
notificationData: {},
unlockLevels,
lastShownNotifications,
alreadyReadNotification,
@ -229,11 +236,11 @@ export default {
async mounted () {
Promise.all(['user.fetch', 'tasks.fetchUserTasks'])
.then(() => {
let { created, loggedin } = this.user.auth.timestamps;
let createdDate = moment(created);
let loggedinDate = moment(loggedin);
if (this.user.flags.newStuff) {
this.$root.$emit('show::modal', 'new-stuff');
}
if (!this.user.flags.welcomed && !createdDate.isBefore(loggedinDate)) {
if (!this.user.flags.welcomed) {
this.$store.state.avatarEditorOptions.editingUser = false;
this.$root.$emit('show::modal', 'avatar-modal');
}
@ -274,7 +281,7 @@ export default {
if (this.yesterDailies.length === 0) {
this.isRunningYesterdailies = false;
await axios.post('/api/v3/cron');
this.handleUserNotifications(this.user);
this.handleUserNotifications(this.user.notifications);
return;
}
@ -285,7 +292,7 @@ export default {
this.user.groupNotifications.push(notification);
},
async handleUserNotifications (after) {
if (!after || after.length === 0) return;
if (!after || after.length === 0 || !Array.isArray(after)) return;
let notificationsToRead = [];
let scoreTaskNotification = [];
@ -389,7 +396,8 @@ export default {
}
break;
case 'LOGIN_INCENTIVE':
// @TODO: Notification.showLoginIncentive(this.user, notification.data, Social.loadWidgets);
this.notificationData = notification.data;
this.$root.$emit('show::modal', 'login-incentives');
break;
default:
if (notification.data.headerText && notification.data.bodyText) {

View file

@ -18,6 +18,7 @@
<script>
import axios from 'axios';
import { mapState } from 'client/libs/store';
import bModal from 'bootstrap-vue/lib/components/modal';
@ -38,6 +39,9 @@ export default {
amazonPaymentsrecurringConsent: 'false',
};
},
computed: {
...mapState({user: 'user.data'}),
},
mounted () {
// @TODO:
// window.onAmazonLoginReady = function() {
@ -202,6 +206,7 @@ export default {
if (newGroup && newGroup._id) {
// @TODO: Just append? or $emit?
this.$router.push(`/group-plans/${newGroup._id}/task-information`);
this.user.guilds.push(newGroup._id);
return;
}

View file

@ -24,6 +24,15 @@
option(v-for='dateFormat in availableFormats', :value='dateFormat') {{dateFormat}}
hr
.form-horizontal(v-if='user.flags.classSelected && !user.preferences.disableClasses')
h5 {{ $t('characterBuild') }}
h6(v-once) {{ $t('class') + ': ' }}
span {{ classText }}&nbsp;
button.btn.btn-danger.btn-xs(@click='changeClass(null)', v-once) {{ $t('changeClass') }}
small.cost 3
span.Pet_Currency_Gem1x.inline-gems
hr
div
.checkbox
label
@ -194,6 +203,7 @@ import restoreModal from './restoreModal';
import resetModal from './resetModal';
import deleteModal from './deleteModal';
import { SUPPORTED_SOCIAL_NETWORKS } from '../../../common/script/constants';
import changeClass from '../../../common/script/ops/changeClass';
// @TODO: this needs our window.env fix
// import { availableLanguages } from '../../../server/libs/i18n';
@ -362,6 +372,15 @@ export default {
this.$router.go('/tasks');
},
async changeClass () {
if (!confirm('Are you sure you want to change your class for 3 gems?')) return;
try {
changeClass(this.user);
await axios.post('/api/v3/user/change-class');
} catch (e) {
alert(e.message);
}
},
},
};
</script>

View file

@ -173,7 +173,7 @@ export default {
this.members = members;
}
if (this.$store.state.viewingMembers.length > 0) {
if (this.$store.state.memberModalOptions.viewingMembers.length > 0) {
this.members = this.$store.state.viewingMembers;
}
},

View file

@ -0,0 +1,151 @@
<template lang="pug">
transition(name="fade")
.notification.callout.animated(:class="classes", v-if='show')
.row(v-if='notification.type !== "info" && notification.type !== "drop"')
.text.col-7.offset-1
div
| {{message}}
.icon.col-4
div.svg-icon(v-html="icons.health", v-if='notification.type === "hp"')
div.svg-icon(v-html="icons.gold", v-if='notification.type === "gp"')
div.svg-icon(v-html="icons.star", v-if='notification.type === "xp"')
div.svg-icon(v-html="icons.mana", v-if='notification.type === "mp"')
div(v-html='notification.text')
.row(v-if='notification.type === "info"')
.text.col-12
div(v-html='notification.text')
.row(v-if='notification.type !== "info" && notification.type === "drop"')
.col-2
.icon-item
div(:class='notification.icon')
.text.col-9
div(v-html='notification.text')
</template>
<style lang="scss" scoped>
.notification {
border-radius: 1000px;
background-color: #24cc8f;
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
color: white;
width: 300px;
margin-left: 1em;
margin-bottom: 1em;
}
.info {
max-height: 56px;
background-color: #46a7d9;
padding-top: .5em;
}
.negative {
background-color: #f74e52;
}
.text {
text-align: center;
padding: .5em;
}
.svg-icon {
width: 20px;
margin-right: .5em;
}
.hp .icon {
color: #f74e52;
}
.mp .icon {
color: #2995cd;
}
.icon {
background: #fff;
color: #ffa623;
border-radius: 0 1000px 1000px 0;
padding: .5em;
div {
display: inline-block;
vertical-align: bottom;
}
}
.drop {
background-color: #4e4a57;
}
.icon-item {
width: 64px;
height: 64px;
background-color: #ffffff;
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
border-radius: 50%;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0
}
</style>
<script>
import health from 'assets/svg/health.svg';
import gold from 'assets/svg/gold.svg';
import star from 'assets/svg/star.svg';
import mana from 'assets/svg/mana.svg';
export default {
props: ['notification'],
data () {
return {
timer: null,
icons: Object.freeze({
health,
gold,
star,
mana,
}),
show: true,
};
},
created () {
let timeout = this.notification.hasOwnProperty('timeout') ? this.notification.timeout : true;
if (timeout) {
let delay = this.notification.delay || 1000;
delay += this.$store.state.notificationStore.length * 1000;
setTimeout(() => {
this.show = false;
}, delay);
}
},
watch: {
show () {
setTimeout(() => {
this.$store.state.notificationStore.splice(0, 1);
}, 1000);
},
},
computed: {
message () {
let direction = this.negative === 'negative' ? 'lost' : 'gained';
if (this.notification.type === 'hp') return `You ${direction} some ${this.$t('health')}`;
if (this.notification.type === 'mp') return `You ${direction} some ${this.$t('mana')}`;
if (this.notification.type === 'xp') return `You ${direction} some exp`;
if (this.notification.type === 'gp') return `You ${direction} some ${this.$t('gold')}`;
},
negative () {
return this.notification.sign === '-' ? 'negative' : 'positive';
},
classes () {
return `${this.notification.type} ${this.negative}`;
},
},
};
</script>

View file

@ -0,0 +1,29 @@
<template lang="pug">
.notifications
notification(v-for='notification in notifications', :notification='notification')
</template>
<style lang="scss" scoped>
.notifications {
position: fixed;
right: 10px;
top: 10px;
width: 350px;
z-index: 99999;
}
</style>
<script>
import notification from './notification';
export default {
components: {
notification,
},
computed: {
notifications () {
return this.$store.state.notificationStore;
},
},
};
</script>

View file

@ -22,6 +22,7 @@ div
</style>
<script>
import findIndex from 'lodash/findIndex';
import { mapState } from 'client/libs/store';
import approvalModal from './approvalModal';
@ -37,10 +38,22 @@ export default {
},
message () {
let assignedUsers = this.task.group.assignedUsers;
let assignedUsersNames = [];
let assignedUsersLength = assignedUsers.length;
// @TODO: Eh, I think we only ever display one user name
if (this.group && this.group.members) {
assignedUsers.forEach(userId => {
let index = findIndex(this.group.members, (member) => {
return member._id === userId;
});
let assignedMember = this.group.members[index];
assignedUsersNames.push(assignedMember.profile.name);
});
}
if (assignedUsersLength === 1 && !this.userIsAssigned) {
return `Assigned to ${assignedUsers}`;
return `Assigned to ${assignedUsersNames[0]}`;
} else if (assignedUsersLength > 1 && !this.userIsAssigned) {
return `Assigned to ${assignedUsersLength} members`;
} else if (assignedUsersLength > 1 && this.userIsAssigned) {

View file

@ -133,21 +133,25 @@
.icon-habit {
width: 30px;
height: 20px;
color: #A5A1AC;
}
.icon-daily {
width: 30px;
height: 20px;
color: #A5A1AC;
}
.icon-todo {
width: 20px;
height: 20px;
color: #A5A1AC;
}
.icon-reward {
width: 26px;
height: 20px;
color: #A5A1AC;
}
</style>

View file

@ -4,7 +4,7 @@
.d-flex(:class="{'task-not-scoreable': isUser !== true}")
// Habits left side control
.left-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.up")
.task-control.habit-control(:class="controlClass.up + '-control-habit'", @click="isUser ? score('up') : null")
.task-control.habit-control(:class="controlClass.up + '-control-habit'", @click="(isUser && controlClass.up !== 'task-habit-disabled') ? score('up') : null")
.svg-icon.positive(v-html="icons.positive")
// Dailies and todos left side control
.left-control.d-flex.justify-content-center(v-if="task.type === 'daily' || task.type === 'todo'", :class="controlClass")
@ -284,7 +284,7 @@
.task-reward {
// @TODO: I'm unsure of where this is defined. Can't find it in search. So, I am using important for now
background-color: rgba(255, 217, 160, 0.28) !important;
background-color: #ffd9a0 !important;
}
</style>

View file

@ -226,21 +226,25 @@
.difficulty-trivial-icon {
width: 16px;
height: 16px;
color: #A5A1AC;
}
.difficulty-normal-icon {
width: 36px;
height: 16px;
color: #A5A1AC;
}
.difficulty-medium-icon {
width: 36px;
height: 32px;
color: #A5A1AC;
}
.difficulty-hard-icon {
width: 36px;
height: 36px;
color: #A5A1AC;
}
.option {
@ -413,7 +417,7 @@ export default {
},
watch: {
async task () {
if (this.groupId && this.task.group && this.task.group.approval.required) {
if (this.groupId && this.task.group && this.task.group.approval && this.task.group.approval.required) {
this.requiresApproval = true;
}
@ -426,7 +430,8 @@ export default {
this.members.forEach(member => {
this.memberNamesById[member._id] = member.profile.name;
});
this.assignedMembers = this.task.group.assignedUsers;
this.assignedMembers = [];
if (this.task.group && this.task.group.assignedUsers) this.assignedMembers = this.task.group.assignedUsers;
}
},
},

View file

@ -64,7 +64,7 @@
| {{ $t('create') }}
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
span.dropdown-icon-item(v-once)
span.svg-icon.inline(v-html="icons[type]")
span.svg-icon.inline(v-html="icons[type]", :class='`icon_${type}`')
span.text {{$t(type)}}
.row.tasks-columns
@ -142,16 +142,33 @@
}
.dropdown-icon-item .svg-icon {
width: 22px;
color: #C3C0C7;
}
.dropdown-icon-item:hover .svg-icon, .dropdown-item.active .svg-icon {
color: $purple-500;
.dropdown-icon-item {
.icon_habit {
width: 30px;
height: 20px;
}
.icon_daily {
width: 24px;
height: 20px;
}
.icon_todo {
width: 20px;
height: 20px;
}
.icon_reward {
width: 26px;
height: 20px;
}
}
.dropdown-icon-item .text {
font-weight: bold;
.dropdown-icon-item:hover .svg-icon, .dropdown-item.active .svg-icon {
color: #4f2a93;
}
button.btn.btn-secondary.filter-button {

View file

@ -26,10 +26,10 @@
.conversation(v-for='conversation in conversations', @click='selectConversation(conversation.key)', :class="{active: selectedConversation === conversation.key}")
div
span(:class="userLevelStyle(conversation)") {{conversation.name}}
span.timeago {{conversation.date}}
span.timeago {{conversation.date | timeAgo}}
div {{conversation.lastMessageText.substring(0, 30)}}
.col-8.messages
chat-message.container-fluid(:chat.sync='activeChat')
chat-message.container-fluid(:chat.sync='activeChat', :inbox='true')
// @TODO: Implement new message header here when we fix the above
@ -130,7 +130,7 @@
<script>
import moment from 'moment';
import filter from 'lodash/filter';
import sortBy from 'lodash/sortBy';
// import sortBy from 'lodash/sortBy';
import { mapState } from 'client/libs/store';
import styleHelper from 'client/mixins/styleHelper';
@ -159,6 +159,11 @@ export default {
activeChat: [],
};
},
filters: {
timeAgo (value) {
return moment(new Date(value)).fromNow();
},
},
computed: {
...mapState({user: 'user.data'}),
conversations () {
@ -185,7 +190,7 @@ export default {
timestamp: message.timestamp,
});
conversations[userId].lastMessageText = message.text;
conversations[userId].date = moment(new Date(message.timestamp)).fromNow();
conversations[userId].date = message.timestamp;
}
return conversations;
@ -207,10 +212,12 @@ export default {
},
selectConversation (key) {
this.selectedConversation = key;
this.activeChat = this.conversations[this.selectedConversation].messages;
this.activeChat = sortBy(this.activeChat, [(o) => {
return o.timestamp;
}]);
let activeChat = this.conversations[this.selectedConversation].messages;
// @TODO: I think I did this wrong
// activeChat = sortBy(this.activeChat, [(o) => {
// return o.timestamp;
// }]);
this.$set(this, 'activeChat', activeChat);
},
sendPrivateMessage () {
this.$store.dispatch('members:sendPrivateMessage', {

View file

@ -1,186 +1,190 @@
<template lang="pug">
b-modal#profile(title="Profile", size='lg', :hide-footer="true")
.row
.col-6.offset-3.text-center.nav
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
.nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") Stats
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
.standard-page(v-show='selectedPage === "profile"')
div
b-modal#profile(title="Profile", size='lg', :hide-footer="true")
.row
.col-8
.header
h1 {{user.profile.name}}
h4
strong User Id:
| {{user._id}}
.col-4
button.btn.btn-secondary(@click='editing = !editing') Edit
.row(v-if='!editing')
.col-8
.about
h2 About
p {{user.profile.blurb}}
.photo
h2 Photo
img.img-rendering-auto(v-if='user.profile.imageUrl', :src='user.profile.imageUrl')
.col-6.offset-3
button.btn.btn-secondary(@click='sendMessage()') Message
.row
.col-6.offset-3.text-center.nav
.nav-item(@click='selectedPage = "profile"', :class="{active: selectedPage === 'profile'}") Profile
.nav-item(@click='selectedPage = "stats"', :class="{active: selectedPage === 'stats'}") Stats
.nav-item(@click='selectedPage = "achievements"', :class="{active: selectedPage === 'achievements'}") Achievements
.standard-page(v-show='selectedPage === "profile"', v-if='user.profile')
.row
.col-8
.header
h1 {{user.profile.name}}
h4
strong User Id:
| {{user._id}}
.col-4
button.btn.btn-secondary(v-if='user._id === userLoggedIn._id', @click='editing = !editing') Edit
.row(v-if='!editing')
.col-8
.about
h2 About
p {{user.profile.blurb}}
.photo
h2 Photo
img.img-rendering-auto(v-if='user.profile.imageUrl', :src='user.profile.imageUrl')
.col-4
.info
h2 info
div
strong Joined:
| {{user.auth.timestamps.created}}
div
strong Total Log Ins:
span {{ $t('totalCheckins', {count: user.loginIncentives}) }}
div
| {{getProgressDisplay()}}
.progress
.progress-bar(role='progressbar', :aria-valuenow='incentivesProgress', aria-valuemin='0', aria-valuemax='100', :style='{width: incentivesProgress + "%"}')
span.sr-only {{ incentivesProgress }}% Complete
// @TODO: Implement in V2 .social
.col-4
.info
h2 info
div
strong Joined:
| {{user.auth.timestamps.created}}
div
strong Total Log Ins:
span {{ $t('totalCheckins', {count: user.loginIncentives}) }}
div
| {{getProgressDisplay()}}
.progress
.progress-bar(role='progressbar', :aria-valuenow='incentivesProgress', aria-valuemin='0', aria-valuemax='100', :style='{width: incentivesProgress + "%"}')
span.sr-only {{ incentivesProgress }}% Complete
// @TODO: Implement in V2 .social
.row(v-if='editing')
h1 Edit Profile
.col-12
.alert.alert-info.alert-sm(v-html='$t("communityGuidelinesWarning", managerEmail)')
.row(v-if='editing')
h1 Edit Profile
.col-12
.alert.alert-info.alert-sm(v-html='$t("communityGuidelinesWarning", managerEmail)')
// TODO use photo-upload instead: https://groups.google.com/forum/?fromgroups=#!topic/derbyjs/xMmADvxBOak
.form-group
label {{ $t('displayName') }}
input.form-control(type='text', :placeholder="$t('fullName')", v-model='editingProfile.name')
.form-group
label {{ $t('photoUrl') }}
input.form-control(type='url', v-model='editingProfile.imageUrl', :placeholder="$t('imageUrl')")
.form-group
label {{ $t('about') }}
textarea.form-control(rows=5, :placeholder="$t('displayBlurbPlaceholder')", v-model='editingProfile.blurb')
// include ../../shared/formatting-help
.form-group
label Facebook
input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.facebook')
.form-group
label Instagram
input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.instagram')
.form-group
label Twitter
input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.twitter')
// TODO use photo-upload instead: https://groups.google.com/forum/?fromgroups=#!topic/derbyjs/xMmADvxBOak
.form-group
label {{ $t('displayName') }}
input.form-control(type='text', :placeholder="$t('fullName')", v-model='editingProfile.name')
.form-group
label {{ $t('photoUrl') }}
input.form-control(type='url', v-model='editingProfile.imageUrl', :placeholder="$t('imageUrl')")
.form-group
label {{ $t('about') }}
textarea.form-control(rows=5, :placeholder="$t('displayBlurbPlaceholder')", v-model='editingProfile.blurb')
// include ../../shared/formatting-help
.form-group
label Facebook
input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.facebook')
.form-group
label Instagram
input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.instagram')
.form-group
label Twitter
input.form-control(type='text', placeholder="Paste your link here", v-model='editingProfile.twitter')
.col-3.offset-6.text.center
button.btn.btn-primary(@click='save()') {{ $t("save") }}
button.btn.btn-warning(@click='editing = false') {{ $t("cancel") }}
.standard-page.container(v-show='selectedPage === "achievements"')
.row(v-for='(category, key) in achievements')
h2.col-12 {{ $t(key+'Achievs') }}
.col-3.text-center(v-for='achievment in category.achievements')
div.achievement-container(:data-popover-html='achievment.title + achievment.text',
popover-placement='achievPopoverPlacement',
popover-append-to-body='achievAppendToBody')
div(popover-trigger='mouseenter',
:data-popover-html='achievment.title + achievment.text',
.col-3.offset-6.text.center
button.btn.btn-primary(@click='save()') {{ $t("save") }}
button.btn.btn-warning(@click='editing = false') {{ $t("cancel") }}
.standard-page.container(v-show='selectedPage === "achievements"', v-if='user.achievements')
.row(v-for='(category, key) in achievements')
h2.col-12 {{ $t(key+'Achievs') }}
.col-3.text-center(v-for='achievment in category.achievements')
div.achievement-container(:data-popover-html='achievment.title + achievment.text',
popover-placement='achievPopoverPlacement',
popover-append-to-body='achievAppendToBody')
.achievement(:class='achievment.icon + "2x"', v-if='achievment.earned')
.counter.badge.badge-info.stack-count(v-if='achievment.optionalCount') {{achievment.optionalCount}}
.achievement(class='achievement-unearned2x', v-if='!achievment.earned')
.row
.col-6
h2 Challeges Won
div(v-for='chal in user.achievements.challenges')
span {{chal}}
.col-6
h2 Quests Completed
div(v-for='(value, key) in user.achievements.quests')
span {{ content.quests[key].text() }}
span {{ value }}
.standard-page(v-show='selectedPage === "stats"')
.row
.col-6
h2.text-center Equipment
// user.items.gear.equipped
.well
.col-4.item-wrapper
.box
h3 Eyewear
.col-4.item-wrapper
.box
h3 Head Gear
.col-4.item-wrapper
.box
h3 Head Access.
.col-4.item-wrapper
.box
h3 Back Access.
.col-4.item-wrapper
.box
h3 Armor
.col-4.item-wrapper
.box
h3 Body Access.
.col-4.item-wrapper
.box
h3 Main-Hand
.col-4.item-wrapper
.col-4.item-wrapper
.box
h3 Off-Hand
.col-6
h2.text-center Costume
// user.items.gear.costume
.well
.col-4.item-wrapper
.box
h3 Eyewear
.col-4.item-wrapper
.box
h3 Head Gear
.col-4.item-wrapper
.box
h3 Head Access.
.col-4.item-wrapper
.box
h3 Back Access.
.col-4.item-wrapper
.box
h3 Armor
.col-4.item-wrapper
.box
h3 Body Access.
.col-4.item-wrapper
.box
h3 Main-Hand
.col-4.item-wrapper
.box
h3 Background {{ user.preferences.background }}
.col-4.item-wrapper
.box
h3 Off-Hand
.row
.col-6
h2.text-center(v-once) {{ $t('pets') }}
ul
li(ng-if='user.items.currentPet')
| {{ $t('activePet') }}:
| {{ formatAnimal(user.items.currentPet, 'pet') }}
li
| {{ $t('petsFound') }}:
| {{ totalCount(user.items.pets) }}
li
| {{ $t('beastMasterProgress') }}:
| {{ beastMasterProgress(user.items.pets) }}
.col-6
h2.text-center(v-once) {{ $t('mounts') }}
ul
li(v-if='user.items.currentMount')
| {{ $t('activeMount') }}:
| {{ formatAnimal(user.items.currentMount, 'mount') }}
li
| {{ $t('mountsTamed') }}:
| {{ totalCount(user.items.mounts) }}
li
| {{ $t('mountMasterProgress') }}:
| {{ mountMasterProgress(user.items.mounts) }}
.row#attributes
div(popover-trigger='mouseenter',
:data-popover-html='achievment.title + achievment.text',
popover-placement='achievPopoverPlacement',
popover-append-to-body='achievAppendToBody')
.achievement(:class='achievment.icon + "2x"', v-if='achievment.earned')
.counter.badge.badge-info.stack-count(v-if='achievment.optionalCount') {{achievment.optionalCount}}
.achievement(class='achievement-unearned2x', v-if='!achievment.earned')
.row
.col-6(v-if='user.achievements.challenges')
h2 Challeges Won
div(v-for='chal in user.achievements.challenges')
span {{chal}}
.col-6(v-if='user.achievements.quests')
h2 Quests Completed
div(v-for='(value, key) in user.achievements.quests')
span {{ content.quests[k].text() }}
span {{ value }}
.standard-page(v-show='selectedPage === "stats"', v-if='user.preferences')
.row
.col-6
h2.text-center Equipment
// user.items.gear.equipped
.well
.col-4.item-wrapper
.box
h3 Eyewear
.col-4.item-wrapper
.box
h3 Head Gear
.col-4.item-wrapper
.box
h3 Head Access.
.col-4.item-wrapper
.box
h3 Back Access.
.col-4.item-wrapper
.box
h3 Armor
.col-4.item-wrapper
.box
h3 Body Access.
.col-4.item-wrapper
.box
h3 Main-Hand
.col-4.item-wrapper
.col-4.item-wrapper
.box
h3 Off-Hand
.col-6
h2.text-center Costume
// user.items.gear.costume
.well
.col-4.item-wrapper
.box
h3 Eyewear
.col-4.item-wrapper
.box
h3 Head Gear
.col-4.item-wrapper
.box
h3 Head Access.
.col-4.item-wrapper
.box
h3 Back Access.
.col-4.item-wrapper
.box
h3 Armor
.col-4.item-wrapper
.box
h3 Body Access.
.col-4.item-wrapper
.box
h3 Main-Hand
.col-4.item-wrapper
.box
h3 Background {{ user.preferences.background }}
.col-4.item-wrapper
.box
h3 Off-Hand
.row
.col-6
h2.text-center(v-once) {{ $t('pets') }}
ul
li(ng-if='user.items.currentPet')
| {{ $t('activePet') }}:
| {{ formatAnimal(user.items.currentPet, 'pet') }}
li
| {{ $t('petsFound') }}:
| {{ totalCount(user.items.pets) }}
li
| {{ $t('beastMasterProgress') }}:
| {{ beastMasterProgress(user.items.pets) }}
.col-6
h2.text-center(v-once) {{ $t('mounts') }}
ul
li(v-if='user.items.currentMount')
| {{ $t('activeMount') }}:
| {{ formatAnimal(user.items.currentMount, 'mount') }}
li
| {{ $t('mountsTamed') }}:
| {{ totalCount(user.items.mounts) }}
li
| {{ $t('mountMasterProgress') }}:
| {{ mountMasterProgress(user.items.mounts) }}
.row#attributes
hr.col-12
h2.col-12 Attributes
.row.col-6(v-for="(statInfo, stat) in stats")
@ -206,14 +210,7 @@ b-modal#profile(title="Profile", size='lg', :hide-footer="true")
li
strong Buffs:
| {{user.stats.buffs[stat]}}
// @TODO: Implement .col-4(v-if='user.flags.classSelected && !user.preferences.disableClasses')
h3(v-once) {{ $t('characterBuild') }}
h4(v-once) {{ $t('class') + ': ' }}
span {{ classText }}&nbsp;
button.btn.btn-danger.btn-xs(@click='changeClass(null)', v-once) {{ $t('changeClass') }}
small.cost 3
span.Pet_Currency_Gem1x.inline-gems
// @TODO: Implement
div
div
p(v-if='userLevel100Plus', v-once) {{ $t('noMoreAllocate') }}
@ -256,6 +253,11 @@ b-modal#profile(title="Profile", size='lg', :hide-footer="true")
.col-4(v-if='user.stats.points', @click='allocate(stat)')
button.btn.btn-primary(popover-trigger='mouseenter', popover-placement='right',
:popover='$t(statInfo.allocatepop)') +
// @TODO: Make separate componenet
b-modal#private-message(title="Message", size='sm', :hide-footer="true")
textarea.form-control(v-model='privateMessage')
button.btn.btn-primary(@click='sendPrivateMessage()') Send
</template>
<style lang="scss" scoped>
@ -331,7 +333,6 @@ import keys from 'lodash/keys';
import { beastMasterProgress, mountMasterProgress } from '../../../common/script/count';
import statsComputed from '../../../common/script/libs/statsComputed';
import autoAllocate from '../../../common/script/fns/autoAllocate';
import changeClass from '../../../common/script/ops/changeClass';
import allocate from '../../../common/script/ops/allocate';
import achievementsLib from '../../../common/script/libs/achievements';
@ -347,6 +348,8 @@ export default {
},
data () {
return {
userIdToMessage: '',
privateMessage: '',
editing: false,
editingProfile: {
name: '',
@ -385,16 +388,29 @@ export default {
},
};
},
mounted () {
this.editingProfile.name = this.user.profile.name;
this.editingProfile.imageUrl = this.user.profile.imageUrl;
this.achievements = achievementsLib.getAchievementsForProfile(this.user);
},
computed: {
...mapState({
user: 'user.data',
userLoggedIn: 'user.data',
flatGear: 'content.gear.flat',
}),
user () {
let user = this.userLoggedIn;
let profileUser = this.$store.state.profileUser;
if (profileUser._id && profileUser._id !== this.userLoggedIn._id) {
user = profileUser;
}
this.editingProfile.name = user.profile.name;
this.editingProfile.imageUrl = user.profile.imageUrl;
if (!user.achievements.quests) user.achievements.quests = {};
if (!user.achievements.challenges) user.achievements.challenges = {};
// @TODO: this common code should handle the above
this.achievements = achievementsLib.getAchievementsForProfile(user);
return user;
},
incentivesProgress () {
return this.getIncentivesProgress();
},
@ -416,6 +432,20 @@ export default {
},
},
methods: {
sendMessage () {
this.userIdToMessage = this.user._id;
this.$root.$emit('show::modal', 'private-message');
},
async sendPrivateMessage () {
if (!this.privateMessage || !this.userIdToMessage) return;
await this.$store.dispatch('members:sendPrivateMessage', {
message: this.privateMessage,
toUserId: this.userIdToMessage,
});
alert(this.$t('messageSentAlert'));
// @TODO: Notification.text(window.env.t('messageSentAlert'));
},
getProgressDisplay () {
// let currentLoginDay = Content.loginIncentives[this.user.loginIncentives];
// if (!currentLoginDay) return this.$t('checkinReceivedAllRewardsMessage');
@ -471,7 +501,8 @@ export default {
if (bg.hasOwnProperty(background)) {
return `${bg[background].text()} (${this.$t(bg[background].set.text)})`;
}
return window.env.t('noBackground');
return this.$t('noBackground');
},
totalCount (objectToCount) {
let total = size(objectToCount);
@ -493,9 +524,6 @@ export default {
let display = `${stat}/${totalStat}`;
return display;
},
changeClass () {
changeClass(this.user);
},
allocate (stat) {
allocate(this.user, stat);
},

View file

@ -9,7 +9,6 @@ import getStore from './store';
import StoreModule from './libs/store';
import './filters/registerGlobals';
import i18n from './libs/i18n';
import Notifications from 'vue-notification';
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
@ -23,8 +22,6 @@ Vue.config.performance = !IS_PRODUCTION;
// Disable annoying reminder abour production build in dev mode
Vue.config.productionTip = IS_PRODUCTION;
Vue.use(Notifications);
// window['habitica-i18n] is injected by the server
Vue.use(i18n, {i18nData: window && window['habitica-i18n']});
Vue.use(StoreModule);

View file

@ -22,7 +22,6 @@ export default {
intro: [
[
{
element: '.tasks-columns',
intro: this.$t('introTour'),
scrollTo: 'tooltip',
},

View file

@ -1,6 +1,10 @@
import habiticaMarkdown from 'habitica-markdown';
import { mapState } from 'client/libs/store';
export default {
computed: {
...mapState({notifications: 'notificationStore'}),
},
methods: {
/**
Show '+ 5 {gold_coin} 3 {silver_coin}'
@ -58,18 +62,18 @@ export default {
},
exp (val) {
if (val < -50) return; // don't show when they level up (resetting their exp)
let message = `${this.sign(val)} ${this.round(val)} + ${this.$t('experience')}`;
this.notify(message, 'xp', 'glyphicon glyphicon-star');
let message = `${this.sign(val)} ${this.round(val)}`;
this.notify(message, 'xp', 'glyphicon glyphicon-star', this.sign(val));
},
error (error, canHide) {
this.notify(error, 'danger', 'glyphicon glyphicon-exclamation-sign', canHide);
},
gp (val, bonus) {
this.notify(`${this.sign(val)} ${this.coins(val - bonus)}`, 'gp');
this.notify(`${this.sign(val)} ${this.coins(val - bonus)}`, 'gp', '', this.sign(val));
},
hp (val) {
// don't show notifications if user dead
this.notify(`${this.sign(val)} ${this.round(val)} ${this.$t('health')}`, 'hp', 'glyphicon glyphicon-heart');
this.notify(`${this.sign(val)} ${this.round(val)}`, 'hp', 'glyphicon glyphicon-heart', this.sign(val));
},
lvl () {
this.notify(this.$t('levelUp'), 'lvl', 'glyphicon glyphicon-chevron-up');
@ -80,7 +84,7 @@ export default {
this.notify(parsedMarkdown, 'info');
},
mp (val) {
this.notify(`${this.sign(val)} ${this.round(val)} ${this.$t('mana')}`, 'mp', 'glyphicon glyphicon-fire');
this.notify(`${this.sign(val)} ${this.round(val)}`, 'mp', 'glyphicon glyphicon-fire', this.sign(val));
},
streak (val) {
this.notify(`${this.$t('streaks')}: ${val}`, 'streak', 'glyphicon glyphicon-repeat');
@ -99,31 +103,15 @@ export default {
round (number) {
return Math.abs(number.toFixed(1));
},
notify (html) {
// @TODO: try these params type, icon, canHide, onClick
this.$notify({
title: 'Habitica',
notify (html, type, icon, sign) {
this.notifications.push({
title: '',
text: html,
type,
icon,
sign,
timeout: true,
});
// let stack_topright = {"dir1": "down", "dir2": "left", "spacing1": 15, "spacing2": 15, "firstpos1": 60};
// let notice = $.pnotify({
// type: type || 'warning', //('info', 'text', 'warning', 'success', 'gp', 'xp', 'hp', 'lvl', 'death', 'mp', 'crit')
// text: html,
// opacity: 1,
// addclass: 'alert-' + type,
// delay: 7000,
// hide: ((type == 'error' || type == 'danger') && !canHide) ? false : true,
// mouse_reset: false,
// width: "250px",
// stack: stack_topright,
// icon: icon || false
// }).click(function() {
// notice.pnotify_remove();
//
// if (onClick) {
// onClick();
// }
// });
},
},
};

View file

@ -57,6 +57,7 @@ export default {
if (newGroup && newGroup._id) {
// @TODO: Just append? or $emit?
this.$router.push(`/group-plans/${newGroup._id}/task-information`);
this.user.guilds.push(newGroup._id);
return;
}

View file

@ -98,6 +98,9 @@ export default function () {
castingSpell: false,
spellDrawOpen: true,
},
profileUser: {},
upgradingGroup: {},
notificationStore: [],
},
});

View file

@ -1,9 +1,9 @@
import shared from '../../../common';
import _ from 'lodash';
import moment from 'moment';
import * as Tasks from '../task';
import Bluebird from 'bluebird';
import baseModel from '../../libs/baseModel';
import * as Tasks from '../task';
import schema from './schema';
@ -34,6 +34,7 @@ function _populateDefaultTasks (user, taskTypes) {
let defaultsData;
if (user.registeredThrough === 'habitica-android' || user.registeredThrough === 'habitica-ios') {
defaultsData = shared.content.userDefaultsMobile;
user.flags.welcomed = true;
} else {
defaultsData = shared.content.userDefaults;
}
@ -51,7 +52,10 @@ function _populateDefaultTasks (user, taskTypes) {
});
}
// @TODO: default tasks are handled differently now, and not during registration. We should move this code
let tasksToCreate = [];
if (user.registeredThrough === 'habitica-web') return Bluebird.all(tasksToCreate);
if (tagsI !== -1) {
taskTypes = _.clone(taskTypes);