New client misc with some more misc (#8929)

* Added markdown

* Added styles and option for debug menu

* Added sm icons

* Began styling autocomplete

* Added autocomplete styles

* Added more challenge categories

* Updated challenge participants modal

* Fixed challenge list updating without reload

* Added close and delete challenge

* Fixed form placeholder, adjusted desc style and fixed create button style

* Fixed faq collapsing and style

* Fixed repeating ending

* Fixed delete account

* Fixed party fetch issue

* Fixed scope issue

* Added member count filters

* Fixed create button style

* Fixed badge color display

* Updated tavern styles

* Fixed some party styles

* Updated login styles

* Fixed login redirect

* Fixed initial login process

* Added done local
This commit is contained in:
Keith Holliday
2017-08-07 14:26:17 -06:00
committed by GitHub
parent 1896984777
commit 0b076311df
46 changed files with 671 additions and 206 deletions
@@ -3,7 +3,7 @@
.modal-content(style='min-width:28em')
.modal-body.text-center
h3(style='margin-bottom: 0') {{ $t('wonChallenge') }}
// @TODO: h4: markdown(text='user.achievements.challenges[user.achievements.challenges.length - 1]')
h4(v-markdown='user.achievements.challenges[user.achievements.challenges.length - 1]')
.container-fluid
.row(style='margin-bottom:1em')
.col-xs-4(style='padding:0')
@@ -43,12 +43,20 @@
</style>
<script>
import { mapState } from 'client/libs/store';
import bModal from 'bootstrap-vue/lib/components/modal';
import markdownDirective from 'client/directives/markdown';
export default {
components: {
bModal,
},
directives: {
markdown: markdownDirective,
},
computed: {
...mapState({user: 'user.data'}),
},
data () {
let tweet = this.$t('wonChallengeShare');
return {
+54 -24
View File
@@ -62,11 +62,14 @@
.col-6
h3 Social
.social-circle
a(href='https://twitter.com/habitica', target='_blank') Twitter
a(href='https://twitter.com/habitica', target='_blank')
.social-icon.svg-icon(v-html='icons.twitter')
.social-circle
a(href='https://www.instagram.com/habitica/', target='_blank') Instagram
a(href='https://www.instagram.com/habitica/', target='_blank')
.social-icon.svg-icon(v-html='icons.instagram')
.social-circle
a(href='https://www.facebook.com/Habitica', target='_blank') Facebook
a(href='https://www.facebook.com/Habitica', target='_blank')
.social-icon.facebook.svg-icon(v-html='icons.facebook')
.row
.col-10
| Were an open source project that depends on our users for support. The money you donate helps us keep the servers running, maintain a small staff, develop new features, and provide incentives for our volunteers.
@@ -77,32 +80,32 @@
.row
.col-4
| © 2017 Habitica. All rights reserved.
.debug.float-left(v-if='!IS_PRODUCTION')
button.btn.btn-primary(@click='debugMenuShown = !debugMenuShown') Toggle Debug Menu
.debug-group(v-if='debugMenuShown')
a.btn.btn-default(@click='setHealthLow()') Health = 1
a.btn.btn-default(@click='addMissedDay(1)') +1 Missed Day
a.btn.btn-default(@click='addMissedDay(2)') +2 Missed Days
a.btn.btn-default(@click='addMissedDay(8)') +8 Missed Days
a.btn.btn-default(@click='addMissedDay(32)') +32 Missed Days
a.btn.btn-default(@click='addTenGems()') +10 Gems
a.btn.btn-default(@click='addHourglass()') +1 Mystic Hourglass
a.btn.btn-default(@click='addGold()') +500GP
a.btn.btn-default(@click='plusTenHealth()') + 10HP
a.btn.btn-default(@click='addMana()') +MP
a.btn.btn-default(@click='addLevelsAndGold()') +Exp +GP +MP
a.btn.btn-default(@click='addOneLevel()') +1 Level
a.btn.btn-default(@click='addQuestProgress()' tooltip="+1000 to boss quests. 300 items to collection quests") Quest Progress Up
a.btn.btn-default(@click='makeAdmin()') Make Admin
a.btn.btn-default(@click='openModifyInventoryModal()') Modify Inventory
.col-4.text-center
.logo.svg-icon(v-html='icons.gryphon')
.col-4.text-right
span Privacy Policy
span Terms of Use
.row
h4 Debug
.btn-group-vertical
a.btn.btn-default(@click='setHealthLow()') Health = 1
a.btn.btn-default(@click='addMissedDay(1)') +1 Missed Day
a.btn.btn-default(@click='addMissedDay(2)') +2 Missed Days
a.btn.btn-default(@click='addMissedDay(8)') +8 Missed Days
a.btn.btn-default(@click='addMissedDay(32)') +32 Missed Days
a.btn.btn-default(@click='addTenGems()') +10 Gems
a.btn.btn-default(@click='addHourglass()') +1 Mystic Hourglass
a.btn.btn-default(@click='addGold()') +500GP
a.btn.btn-default(@click='plusTenHealth()') + 10HP
a.btn.btn-default(@click='addMana()') +MP
a.btn.btn-default(@click='addLevelsAndGold()') +Exp +GP +MP
a.btn.btn-default(@click='addOneLevel()') +1 Level
a.btn.btn-default(@click='addQuestProgress()' tooltip="+1000 to boss quests. 300 items to collection quests") Quest Progress Up
a.btn.btn-default(@click='makeAdmin()') Make Admin
a.btn.btn-default(@click='openModifyInventoryModal()') Modify Inventory
</template>
<style scoped>
<style lang="scss" scoped>
footer {
background-color: #e1e0e3;
height: 376px;
@@ -133,6 +136,17 @@
background-color: #c3c0c7;
display: inline-block;
margin-right: 1em;
.social-icon {
color: #e1e0e3;
width: 16px;
margin: 0 auto;
margin-top: 1em;
}
.svg-icon.facebook svg {
height: 20px;
}
}
.logo.svg-icon {
@@ -140,17 +154,29 @@
margin: 0 auto;
color: #c3c0c7;
}
.debug-group {
position: absolute;
background: #fff;
top: -300px;
border-radius: 2px;
padding: 2em;
}
</style>
<script>
import axios from 'axios';
import moment from 'moment';
import { mapState } from 'client/libs/store';
import gryphon from 'assets/svg/gryphon.svg';
import twitter from 'assets/svg/twitter.svg';
import facebook from 'assets/svg/facebook.svg';
import instagram from 'assets/svg/instagram.svg';
import modifyInventory from './modifyInventory';
// const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
export default {
components: {
@@ -160,7 +186,12 @@ export default {
return {
icons: Object.freeze({
gryphon,
twitter,
facebook,
instagram,
}),
debugMenuShown: false,
IS_PRODUCTION,
};
},
computed: {
@@ -190,7 +221,6 @@ export default {
// @TODO: Sync user?
},
async addTenGems () {
// @TODO: User.addTenGems();
await axios.post('/api/v3/debug/add-ten-gems');
// @TODO: Notification.text('+10 Gems!');
this.user.balance += 2.5;
@@ -34,10 +34,11 @@
.text-center
.btn.btn-info(@click='register()', v-if='registering', v-once) {{$t('joinHabitica')}}
.btn.btn-info(@click='login()', v-if='!registering', v-once) {{$t('login')}}
router-link(tag="li", :to="{name: 'login'}", v-if='registering', exact)
a(v-once) {{ $t('login') }}
router-link(tag="li", :to="{name: 'register'}", v-if='!registering', exact)
a(v-once) {{ $t('joinHabitica') }}
.toggle-links
router-link(:to="{name: 'login'}", v-if='registering', exact)
a.toggle-link(v-once) {{ $t('login') }}
router-link(:to="{name: 'register'}", v-if='!registering', exact)
a.toggle-link(v-once) Don't have an account? Join Habitica!
#bottom-background
.seamless_mountains_demo_repeat
@@ -51,11 +52,24 @@
background-color: $purple-200;
}
::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: $purple-400;
}
::-moz-placeholder { /* Firefox 19+ */
color: $purple-400;
}
:-ms-input-placeholder { /* IE 10+ */
color: $purple-400;
}
:-moz-placeholder { /* Firefox 18- */
color: $purple-400;
}
#login-form {
margin: 0 auto;
width: 40em;
padding-top: 5em;
padding-bottom: 22.5em;
padding-bottom: 4em;
position: relative;
z-index: 1;
@@ -83,20 +97,7 @@
background-color: #432874;
border-color: transparent;
height: 50px;
color: $purple-400;
::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: $purple-400;
}
::-moz-placeholder { /* Firefox 19+ */
color: $purple-400;
}
:-ms-input-placeholder { /* IE 10+ */
color: $purple-400;
}
:-moz-placeholder { /* Firefox 18- */
color: $purple-400;
}
color: $white;
}
.form-text {
@@ -123,7 +124,7 @@
background-repeat: repeat-x;
position: absolute;
height: 500px;
width: 1600px;
width: 1517px;
}
}
@@ -133,7 +134,7 @@
.seamless_mountains_demo_repeat {
background-image: url('~assets/images/auth/seamless_mountains_demo.png');
background-repeat: repeat-x;
width: 1600px;
width: 1517px;
height: 500px;
position: absolute;
z-index: 0;
@@ -147,6 +148,14 @@
height: 150px;
}
}
.toggle-links {
margin-top: 1em;
}
.toggle-link {
color: #fff !important;
}
</style>
<script>
@@ -215,7 +224,7 @@ export default {
passwordConfirm: this.passwordConfirm,
});
this.$router.push('/tasks');
window.location.href = '/';
},
async login () {
await this.$store.dispatch('auth:login', {
@@ -224,7 +233,7 @@ export default {
password: this.password,
});
this.$router.push('/tasks');
window.location.href = '/';
},
async socialAuth (network) {
let auth = await hello(network).login({scope: 'email'});
@@ -233,7 +242,7 @@ export default {
auth,
});
this.$router.push('/tasks');
window.location.href = '/';
},
},
};
@@ -1,7 +1,7 @@
<template lang="pug">
.row
challenge-modal(:challenge='challenge', v-on:updatedChallenge='updatedChallenge')
close-challenge-modal
close-challenge-modal(:members='members', :challengeId='challenge._id')
.col-8.standard-page
.row
@@ -39,10 +39,9 @@
div(v-if='isMember')
button.btn.btn-danger(v-once, @click='leaveChallenge()') {{$t('leaveChallenge')}}
div(v-if='isLeader')
b-dropdown(:text="$t('create')")
b-dropdown.create-dropdown(:text="$t('create')")
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
| {{$t(type)}}
//- button.btn.btn-success(v-once) {{$t('addTask')}}
task-modal(
:task="workingTask",
:purpose="taskFormPurpose",
@@ -129,6 +128,7 @@
div, button {
width: 60%;
margin: 0 auto;
margin-bottom: .5em;
text-align: center;
}
}
@@ -138,6 +138,14 @@
}
</style>
<style>
.create-dropdown button {
width: 100%;
font-size: 16px !important;
font-weight: bold !important;
}
</style>
<script>
import Vue from 'vue';
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
@@ -220,7 +228,7 @@ export default {
createTask (type) {
this.taskFormPurpose = 'create';
this.creatingTask = taskDefaults({type, text: ''});
this.workingTask = this.editingTask;
this.workingTask = this.creatingTask;
// Necessary otherwise the first time the modal is not rendered
Vue.nextTick(() => {
this.$root.$emit('show::modal', 'task-modal');
@@ -240,6 +248,7 @@ export default {
this.tasksByType[task.type].splice(index, 1, task);
},
showMemberModal () {
this.$store.state.groupId = 'challenge'; // @TODO: change these terrible settings
this.$store.state.viewingMembers = this.members;
this.$root.$emit('show::modal', 'members-modal');
},
@@ -106,6 +106,7 @@
color: $gray-200;
margin-top: 2em;
margin-bottom: 2em;
overflow: hidden;
}
.well-wrapper {
@@ -8,7 +8,7 @@
.form-group
label
strong(v-once) {{$t('shortName')}}*
b-form-input(type="text", :placeholder="$t('challengeNamePlaceHolder')", v-model="workingChallenge.shortName")
b-form-input(type="text", :placeholder="$t('shortNamePlaceholder')", v-model="workingChallenge.shortName")
.form-group
label
strong(v-once) {{$t('description')}}*
@@ -110,7 +110,8 @@
}
.category-box {
top: -40px !important;
top: -120px !important;
z-index: 10;
}
}
</style>
@@ -134,49 +135,101 @@ export default {
},
data () {
let categoryOptions = [
{
label: 'Habitica Official',
key: 'habitica_official',
},
{
label: 'Academic',
key: 'academic',
},
{
label: 'Accountability',
key: 'accountability',
},
{
label: 'Advocacy & Causes',
key: 'advocacy_causes',
},
{
label: 'animals',
key: 'animals',
},
{
label: 'artDesign',
key: 'art_design',
label: 'Creativity',
key: 'creativity',
},
{
label: 'booksWriting',
key: 'books_writing',
label: 'Entertainment & Fandom',
key: 'entertainment_fandom',
},
{
label: 'comicsHobbies',
key: 'comics_hobbies',
label: 'Finance',
key: 'finance',
},
{
label: 'diyCrafts',
key: 'diy_crafts',
},
{
label: 'education',
key: 'education',
},
{
label: 'foodCooking',
label: 'Food & Cooking',
key: 'food_cooking',
},
{
label: 'healthFitness',
label: 'Games & Gaming',
key: 'games_gaming',
},
{
label: 'Health + Fitness',
key: 'health_fitness',
},
{
label: 'music',
key: 'music',
label: 'Hobbies',
key: 'hobbies',
},
{
label: 'relationship',
key: 'relationship',
label: 'Language & Literature',
key: 'language_literature',
},
{
label: 'scienceTech',
key: 'science_tech ',
label: 'Location-based',
key: 'location_based',
},
{
label: 'Mental Health',
key: 'mental_health ',
},
{
label: 'Occupations',
key: 'occupations ',
},
{
label: 'Online Communities',
key: 'online_communities ',
},
{
label: 'Getting Organized',
key: 'getting_organized ',
},
{
label: 'Recovery',
key: 'recovery ',
},
{
label: 'Role-Play',
key: 'role_play ',
},
{
label: 'Self-Care',
key: 'self_care ',
},
{
label: 'Self-Improvement',
key: 'self_improvement ',
},
{
label: 'Spirituality',
key: 'spirituality ',
},
{
label: 'Time-Management',
key: 'time_management',
},
];
let hashedCategories = {};
@@ -205,11 +258,13 @@ export default {
});
this.groups = await this.$store.dispatch('guilds:getMyGuilds');
let party = await this.$store.dispatch('guilds:getGroup', {groupId: 'party'});
this.groups.push({
name: party.name,
_id: party._id,
});
if (this.user.party._id) {
let party = await this.$store.dispatch('guilds:getGroup', {groupId: 'party'});
this.groups.push({
name: party.name,
_id: party._id,
});
}
this.groups.push({
name: 'Public',
@@ -10,11 +10,10 @@ div
.col-12
strong(v-once) {{$t('selectChallengeWinnersDescription')}}
.col-12
b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(@click='sort(option.value)')
| Member
select.form-control(v-model='winnerId')
option(v-for='member in members', :value='member._id') {{member.profile.name}}
.col-12
button.btn.btn-primary(v-once) {{$t('awardWinners')}}
button.btn.btn-primary(v-once, @click='closeChallenge') {{$t('awardWinners')}}
.col-12
hr
.or {{$t('or')}}
@@ -78,26 +77,29 @@ import bDropdown from 'bootstrap-vue/lib/components/dropdown';
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
export default {
props: ['challenge'],
props: ['challengeId', 'members'],
components: {
bModal,
bDropdown,
bDropdownItem,
},
data () {
return {
winnerId: '',
};
},
methods: {
closeChallenge () {
// this.challenge = this.$store.dispatch('challenges:selectChallengeWinner', {
// challengeId: this.challengeId,
// winnerId: this.winnerId,
// });
async closeChallenge () {
this.challenge = await this.$store.dispatch('challenges:selectChallengeWinner', {
challengeId: this.challengeId,
winnerId: this.winnerId,
});
this.$router.push('/challenges/myChallenges');
},
deleteChallenge () {
// this.challenge = this.$store.dispatch('challenges:deleteChallenge', {challengeId: this.challengeId});
async deleteChallenge () {
if (!confirm('Are you sure you want to delete this challenge?')) return;
this.challenge = await this.$store.dispatch('challenges:deleteChallenge', {challengeId: this.challengeId});
this.$router.push('/challenges/myChallenges');
},
},
};
@@ -1,6 +1,6 @@
<template lang="pug">
.row
challenge-modal
challenge-modal(v-on:createChallenge='challengeCreated')
sidebar(v-on:search="updateSearch", v-on:filter="updateFilters")
.col-10.standard-page
@@ -127,6 +127,9 @@ export default {
async loadchallanges () {
this.challenges = await this.$store.dispatch('challenges:getUserChallenges');
},
challengeCreated (challenge) {
this.challenges.push(challenge);
},
},
};
</script>
@@ -7,7 +7,7 @@ div
h4(v-once) {{ $t('haveNoChallenges') }}
p(v-once) {{ $t('challengeDescription') }}
button.btn.btn-secondary(v-once, @click='createChallenge()') {{ $t('createChallenge') }}
router-link.title(:to="{ name: 'challenge', params: { challengeId: challenge._id } }", v-for='challenge in challenges')
router-link.title(:to="{ name: 'challenge', params: { challengeId: challenge._id } }", v-for='challenge in challenges',:key='challenge._id')
.col-12.challenge-item
.row
.col-9
@@ -26,7 +26,7 @@ div
button.btn.btn-secondary(@click='createChallenge()') {{ $t('createChallenge') }}
</template>
<style>
<style scoped>
.title {
color: #4E4A57;
}
@@ -1,6 +1,6 @@
<template lang="pug">
.row
challenge-modal
challenge-modal(v-on:createChallenge='challengeCreated')
sidebar(v-on:search="updateSearch", v-on:filter="updateFilters")
.col-10.standard-page
@@ -151,6 +151,9 @@ export default {
async loadchallanges () {
this.challenges = await this.$store.dispatch('challenges:getUserChallenges');
},
challengeCreated (challenge) {
this.challenges.push(challenge);
},
},
};
</script>
@@ -46,24 +46,100 @@ export default {
categoryFilters: [],
categoryOptions: [
{
label: 'habiticaOfficial',
key: 'official',
label: 'Habitica Official',
key: 'habitica_official',
},
{
label: 'Academic',
key: 'academic',
},
{
label: 'Accountability',
key: 'accountability',
},
{
label: 'Advocacy & Causes',
key: 'advocacy_causes',
},
{
label: 'animals',
key: 'animals',
},
{
label: 'artDesign',
key: 'art_design',
label: 'Creativity',
key: 'creativity',
},
{
label: 'booksWriting',
key: 'books_writing',
label: 'Entertainment & Fandom',
key: 'entertainment_fandom',
},
{
label: 'comicsHobbies',
key: 'comics_hobbies',
label: 'Finance',
key: 'finance',
},
{
label: 'Food & Cooking',
key: 'food_cooking',
},
{
label: 'Games & Gaming',
key: 'games_gaming',
},
{
label: 'Health + Fitness',
key: 'health_fitness',
},
{
label: 'Hobbies',
key: 'hobbies',
},
{
label: 'Language & Literature',
key: 'language_literature',
},
{
label: 'Location-based',
key: 'location_based',
},
{
label: 'Mental Health',
key: 'mental_health ',
},
{
label: 'Occupations',
key: 'occupations ',
},
{
label: 'Online Communities',
key: 'online_communities ',
},
{
label: 'Getting Organized',
key: 'getting_organized ',
},
{
label: 'Recovery',
key: 'recovery ',
},
{
label: 'Role-Play',
key: 'role_play ',
},
{
label: 'Self-Care',
key: 'self_care ',
},
{
label: 'Self-Improvement',
key: 'self_improvement ',
},
{
label: 'Spirituality',
key: 'spirituality ',
},
{
label: 'Time-Management',
key: 'time_management',
},
],
roleFilters: [],
+26 -26
View File
@@ -1,28 +1,38 @@
<template lang="pug">
div.autocomplete-selection
div(v-for='result in searchResults', @click='select(result)') {{ result }}
div.autocomplete-selection(v-if='searchResults.length > 0', :style='autocompleteStyle')
.autocomplete-results(v-for='result in searchResults', @click='select(result)') {{ result }}
</template>
<style scoped>
.autocomplete-results {
padding: .5em;
box-shadow: 1px 1px 1px #efefef;
}
</style>
<script>
export default {
props: ['selections', 'text'],
props: ['selections', 'text', 'coords', 'groupId'],
data () {
return {
currentSearch: '',
searchActive: false,
currentSearchPosition: 0,
// @TODO: HAve this passed
tmpSelections: [
'TheHollidayInn',
'Paglias',
],
tmpSelections: [],
};
},
computed: {
autocompleteStyle () {
return {
top: `${this.coords.TOP + 30}px`,
left: `${this.coords.LEFT + 30}px`,
position: 'absolute',
minWidth: '100px',
minHeight: '100px',
zIndex: 100,
backgroundColor: 'white',
};
},
searchResults () {
if (!this.searchActive) return [];
let currentSearch = this.text.substring(this.currentSearchPosition + 1, this.text.length);
@@ -37,23 +47,13 @@ export default {
this.searchActive = true;
this.currentSearchPosition = newText.length - 1;
},
// @TODO: implement position
// caretChanged = function(newCaretPos) {
// var relativeelement = $('.chat-form div:first');
// var textarea = $('.chat-form textarea');
// var userlist = $('.list-at-user');
// var offset = {
// x: textarea.offset().left - relativeelement.offset().left,
// y: textarea.offset().top - relativeelement.offset().top,
// };
// if(relativeelement) {
// var caretOffset = InputCaret.getPosition(textarea);
// userlist.css({
// left: caretOffset.left + offset.x,
// top: caretOffset.top + offset.y + 16
// });
// }
// }
async groupId () {
if (!this.groupId) return;
let members = await this.$store.dispatch('members:getGroupMembers', {groupId: this.groupId});
this.tmpSelections = members.map((member) => {
return member.profile.name;
});
},
},
methods: {
select (result) {
@@ -17,7 +17,7 @@ div
.card-block
h3.leader {{msg.user}}
p {{msg.timestamp | timeAgo}}
.text {{msg.text}}
.text(v-markdown='msg.text')
hr
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
.svg-icon(v-html="icons.like")
@@ -97,6 +97,7 @@ div
import moment from 'moment';
import cloneDeep from 'lodash/cloneDeep';
import { mapState } from 'client/libs/store';
import markdownDirective from 'client/directives/markdown';
import copyAsTodoModal from './copyAsTodoModal';
import reportFlagModal from './reportFlagModal';
@@ -113,6 +114,9 @@ export default {
copyAsTodoModal,
reportFlagModal,
},
directives: {
markdown: markdownDirective,
},
data () {
return {
icons: Object.freeze({
@@ -17,7 +17,7 @@
| &nbsp;
div.task-text
markdown(text='text',target='_blank')
div(v-markdown='text', target='_blank')
.modal-footer
button.btn.btn-default(@click='close()') {{ $t('close') }}
@@ -26,11 +26,15 @@
<script>
import bModal from 'bootstrap-vue/lib/components/modal';
import markdownDirective from 'client/directives/markdown';
export default {
components: {
bModal,
},
directives: {
markdown: markdownDirective,
},
props: ['copyingMessage', 'groupName', 'groupId'],
data () {
return {
@@ -4,7 +4,7 @@
h4(v-html="$t('abuseFlagModalHeading', reportData)")
.modal-body
blockquote
// @TODO: markdown(text='abuseObject.text')
div(v-markdown='abuseObject.text')
p(v-html="$t('abuseFlagModalBody', abuseFlagModalBody)")
.modal-footer
button.pull-left.btn.btn-danger(@click='clearFlagCount()', v-if='user.contributor.admin && abuseObject.flagCount > 0')
@@ -17,12 +17,16 @@
import bModal from 'bootstrap-vue/lib/components/modal';
import { mapState } from 'client/libs/store';
import notifications from 'client/mixins/notifications';
import markdownDirective from 'client/directives/markdown';
export default {
mixins: [notifications],
components: {
bModal,
},
directives: {
markdown: markdownDirective,
},
computed: {
...mapState({user: 'user.data'}),
reportData () {
@@ -434,6 +434,7 @@ import { mapState } from 'client/libs/store';
import avatar from './avatar';
import { getBackgroundShopSets } from '../../common/script/libs/shops';
import unlock from '../../common/script/ops/unlock';
import guide from 'client/mixins/guide';
import bModal from 'bootstrap-vue/lib/components/modal';
@@ -445,6 +446,7 @@ import hairIcon from 'assets/svg/hair.svg';
import backgroundsIcon from 'assets/svg/backgrounds.svg';
export default {
mixins: [guide],
components: {
avatar,
bModal,
@@ -518,6 +520,15 @@ export default {
done () {
this.$root.$emit('hide::modal', 'avatar-modal');
this.$router.push('/');
this.$store.dispatch('user:set', {
'flags.welcomed': true,
});
// @TODO: This is a timeout to ensure dom is loaded
window.setTimeout(() => {
this.initTour();
this.goto('intro', 0);
}, 1000);
},
showPlainBackgroundBlurb (identifier, set) {
return identifier === 'incentiveBackgrounds' && !this.ownsSet('background', set);
@@ -26,7 +26,9 @@
span(v-once) {{ $t('loading') }}
</template>
<style scoped>
<style lang="scss" scoped>
@import '~client/assets/scss/colors.scss';
.sort-select {
margin: 2em;
}
+56 -6
View File
@@ -25,7 +25,8 @@
.col-12
h3(v-once) {{ $t('chat') }}
textarea(:placeholder="$t('chatPlaceHolder')", v-model='newMessage')
textarea(:placeholder="!isParty ? $t('chatPlaceHolder') : $t('partyChatPlaceholder')", v-model='newMessage', @keydown='updateCarretPosition')
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete", :coords='coords', :groupId='groupId')
button.btn.btn-secondary.send-chat.float-right(v-once, @click='sendMessage()') {{ $t('send') }}
button.btn.btn-secondary.float-left(v-once, @click='fetchRecentMessages()') {{ $t('fetchRecentMessages') }}
@@ -87,7 +88,7 @@
.col-6
h4.float-left(v-once) {{ questData.boss.name() }}
.col-6
span.float-right(v-once) {{ $t('participants') }}
span.float-right(v-once) {{ $t('participantsTitle') }}
.row
.col-12
.grey-progress-bar
@@ -95,9 +96,9 @@
.row.boss-details
.col-6
span.float-left
| {{group.quest.progress.hp}} / {{questData.boss.hp}}
| {{parseFloat(group.quest.progress.hp).toFixed(2)}} / {{parseFloat(questData.boss.hp).toFixed(2)}}
.col-6
span.float-right 30 pending damage
span.float-right {{group.quest.progress.up || 0}} pending damage
button.btn.btn-secondary(v-once, @click="questAbort()") {{ $t('abort') }}
.section-header
@@ -211,12 +212,24 @@
background-color: $white;
border: solid 1px $gray-400;
font-size: 16px;
font-style: italic;
line-height: 1.43;
color: $gray-300;
padding: .5em;
}
textarea::-webkit-input-placeholder { /* Chrome/Opera/Safari */
font-style: italic;
}
textarea::-moz-placeholder { /* Firefox 19+ */
font-style: italic;
}
textarea:-ms-input-placeholder { /* IE 10+ */
font-style: italic;
}
textarea:-moz-placeholder { /* Firefox 18- */
font-style: italic;
}
.title-details {
padding-top: 1em;
padding-left: 1em;
@@ -284,7 +297,8 @@
}
.tooltip-wrapper {
margin-left: 2.2em;
width: 15px;
margin-left: 1.2em;
}
}
@@ -359,6 +373,7 @@ import percent from 'common/script/libs/percent';
import groupFormModal from './groupFormModal';
import inviteModal from './inviteModal';
import chatMessage from '../chat/chatMessages';
import autocomplete from '../chat/autoComplete';
import groupChallenges from '../challenges/groupChallenges';
import bCollapse from 'bootstrap-vue/lib/components/collapse';
@@ -392,6 +407,7 @@ export default {
chatMessage,
inviteModal,
groupChallenges,
autocomplete,
},
directives: {
bToggle,
@@ -422,6 +438,10 @@ export default {
challenges: true,
},
newMessage: '',
coords: {
TOP: 0,
LEFT: 0,
},
};
},
computed: {
@@ -515,6 +535,36 @@ export default {
},
},
methods: {
// @TODO: abstract autocomplete
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
getCoord (e, text) {
let carPos = text.selectionEnd;
let div = document.createElement('div');
let span = document.createElement('span');
let copyStyle = getComputedStyle(text);
[].forEach.call(copyStyle, (prop) => {
div.style[prop] = copyStyle[prop];
});
div.style.position = 'absolute';
document.body.appendChild(div);
div.textContent = text.value.substr(0, carPos);
span.textContent = text.value.substr(carPos) || '.';
div.appendChild(span);
this.coords = {
TOP: span.offsetTop,
LEFT: span.offsetLeft,
};
document.body.removeChild(div);
},
updateCarretPosition (eventUpdate) {
let text = eventUpdate.target;
this.getCoord(eventUpdate, text);
},
selectedAutocomplete (newText) {
this.newMessage = newText;
},
showMemberModal () {
this.$store.state.groupId = this.group._id;
this.$root.$emit('show::modal', 'members-modal');
@@ -160,13 +160,15 @@ export default {
methods: {
async getMembers () {
let groupId = this.$store.state.groupId || this.group._id;
if (groupId) {
if (groupId && groupId !== 'challenge') {
let members = await this.$store.dispatch('members:getGroupMembers', {
groupId,
includeAllPublicFields: true,
});
this.members = members;
} else if (this.$store.state.viewingMembers.length > 1) {
}
if (this.$store.state.viewingMembers.length > 0) {
this.members = this.$store.state.viewingMembers;
}
},
@@ -4,7 +4,9 @@ router-link.card-link(:to="{ name: 'guild', params: { groupId: guild._id } }")
.card-block
.row
.col-md-2
.svg-icon.shield(v-html="icons.goldGuildBadge")
.svg-icon.shield(v-html="icons.goldGuildBadge", v-if='guild.memberCount > 1000')
.svg-icon.shield(v-html="icons.silverGuildBadgeIcon", v-if='guild.memberCount > 100 && guild.memberCount < 999')
.svg-icon.shield(v-html="icons.bronzeGuildBadgeIcon", v-if='guild.memberCount < 100')
.member-count {{guild.memberCount}}
.col-md-10
.row
@@ -111,6 +113,8 @@ import groupUtilities from 'client/mixins/groupsUtilities';
import findIndex from 'lodash/findIndex';
import gemIcon from 'assets/svg/gem.svg';
import goldGuildBadgeIcon from 'assets/svg/gold-guild-badge.svg';
import silverGuildBadgeIcon from 'assets/svg/silver-guild-badge.svg';
import bronzeGuildBadgeIcon from 'assets/svg/bronze-guild-badge.svg';
export default {
mixins: [groupUtilities],
@@ -126,6 +130,8 @@ export default {
icons: Object.freeze({
gem: gemIcon,
goldGuildBadge: goldGuildBadgeIcon,
silverGuildBadgeIcon,
bronzeGuildBadgeIcon,
}),
};
},
+57 -4
View File
@@ -7,11 +7,11 @@
.row.chat-row
.col-12
h3(v-once) {{ $t('welcomeToTavern') }}
h3(v-once) {{ $t('tavernChat') }}
.row
textarea(placeholder="Type a message to Habiticans here", v-model='newMessage')
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete")
textarea(placeholder="Type a message to Habiticans here", v-model='newMessage', @keydown='updateCarretPosition')
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete", :coords='coords', :groupId='groupId')
button.btn.btn-secondary.send-chat.float-right(v-once, @click='sendMessage()') {{ $t('send') }}
.row.community-guidelines(v-if='!communityGuidelinesAccepted')
@@ -50,6 +50,7 @@
.col-3.staff(v-for='user in staff', :class='{staff: user.type === "Staff", moderator: user.type === "Moderator", bailey: user.name === "It\'s Bailey"}')
.title {{user.name}}
.type {{user.type}}
.svg-icon(v-html="icons.tierChampionIcon")
.section-header
.row
@@ -194,7 +195,7 @@
}
.grassy-meadow-backdrop {
background-image: url('~assets/images/groups/grassy-meadow-backdrop.png');
background-image: url('~assets/images/tavern_backdrop_web.png');
width: 100%;
height: 246px;
}
@@ -296,6 +297,17 @@ import questBackground from 'assets/svg/quest-background-border.svg';
import upIcon from 'assets/svg/up.svg';
import downIcon from 'assets/svg/down.svg';
import tierChampionIcon from 'assets/svg/tier-champion-icon.svg';
import tierChampion2Icon from 'assets/svg/tier-champion-2-icon.svg';
import tierEliteIcon from 'assets/svg/tier-elite-icon.svg';
import tierElite2Icon from 'assets/svg/tier-elite-2-icon.svg';
import tierFriendIcon from 'assets/svg/tier-friend-icon.svg';
import tierFriend2Icon from 'assets/svg/tier-friend-2-icon.svg';
import tierLegendaryIcon from 'assets/svg/tier-legendary-icon.svg';
import tierModIcon from 'assets/svg/tier-mod-icon.svg';
import tierNPCIcon from 'assets/svg/tier-npc-icon.svg';
import tierStaffIcon from 'assets/svg/tier-staff-icon.svg';
export default {
components: {
chatMessage,
@@ -303,7 +315,18 @@ export default {
},
data () {
return {
groupId: TAVERN_ID,
icons: Object.freeze({
tierStaffIcon,
tierNPCIcon,
tierModIcon,
tierLegendaryIcon,
tierFriend2Icon,
tierFriendIcon,
tierElite2Icon,
tierEliteIcon,
tierChampion2Icon,
tierChampionIcon,
gem: gemIcon,
questIcon,
challengeIcon,
@@ -395,6 +418,10 @@ export default {
},
],
newMessage: '',
coords: {
TOP: 0,
LEFT: 0,
},
};
},
computed: {
@@ -407,6 +434,32 @@ export default {
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
},
methods: {
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
getCoord (e, text) {
let carPos = text.selectionEnd;
let div = document.createElement('div');
let span = document.createElement('span');
let copyStyle = getComputedStyle(text);
[].forEach.call(copyStyle, (prop) => {
div.style[prop] = copyStyle[prop];
});
div.style.position = 'absolute';
document.body.appendChild(div);
div.textContent = text.value.substr(0, carPos);
span.textContent = text.value.substr(carPos) || '.';
div.appendChild(span);
this.coords = {
TOP: span.offsetTop,
LEFT: span.offsetLeft,
};
document.body.removeChild(div);
},
updateCarretPosition (eventUpdate) {
let text = eventUpdate.target;
this.getCoord(eventUpdate, text);
},
selectedAutocomplete (newText) {
this.newMessage = newText;
},
+12 -11
View File
@@ -1,6 +1,5 @@
<template lang="pug">
div
welcome-modal
new-stuff
death
low-health
@@ -223,20 +222,22 @@ export default {
},
},
async mounted () {
if (!this.user.flags.welcomed) {
this.$root.$emit('show::modal', 'welcome');
}
Promise.all(['user.fetch', 'tasks.fetchUserTasks'])
.then(() => {
if (!this.user.flags.welcomed) {
this.$store.state.avatarEditorOptions.editingUser = false;
this.$root.$emit('show::modal', 'avatar-modal');
}
// @TODO: This is a timeout to ensure dom is loaded
window.setTimeout(() => {
this.initTour();
if (this.user.flags.tour.intro === this.TOUR_END || !this.user.flags.welcomed) return;
this.goto('intro', 0);
}, 2000);
this.runYesterDailies();
});
window.setTimeout(() => {
this.initTour();
if (this.user.flags.tour.intro === this.TOUR_END) return;
this.goto('intro', 0);
}, 2000);
},
methods: {
playSound () {
@@ -39,12 +39,14 @@ export default {
this.$root.$emit('hide::modal', 'reset');
},
async deleteAccount () {
await axios.delete('/api/v3/user/', {
password: this.password,
feedback: this.feedback,
await axios.delete('/api/v3/user', {
data: {
password: this.password,
feedback: this.feedback,
},
});
localStorage.clear();
this.$router.push('/');
this.$router.push('/home');
this.$root.$emit('hide::modal', 'reset');
},
},
+38 -14
View File
@@ -3,30 +3,54 @@
.col-6.offset-3
.page-header
h1 {{ $t('frequentlyAskedQuestions') }}
p.pagemeta
| {{ $t('lastUpdated') }}
|&nbsp;
| {{ $t('January') }}
|&nbsp;5&comma; 2016
div(v-for='(heading, index) in headings')
.faq-question(v-for='(heading, index) in headings')
h2.accordion(@click='setActivePage(heading)') {{ $t(`faqQuestion${index}`) }}
// @TODO: Markdown
div(v-if='activePage === heading', v-html="$t('webFaqAnswer' + index, replacements)")
div(v-if='pageState[heading]', v-markdown="$t('webFaqAnswer' + index, replacements)")
hr
// @TODO markdown
div(v-html="$t('webFaqStillNeedHelp')")
div(v-markdown="$t('webFaqStillNeedHelp')")
</template>
<style scoped>
.faq-question {
margin-bottom: 1em;
}
</style>
<script>
// @TODO: env.EMAILS.TECH_ASSISTANCE_EMAIL
const TECH_ASSISTANCE_EMAIL = 'admin@habitica.com';
import markdownDirective from 'client/directives/markdown';
export default {
directives: {
markdown: markdownDirective,
},
data () {
let headings = [
'overview',
'set-up-tasks',
'sample-tasks',
'task-color',
'health',
'party-with-friends',
'pets-mounts',
'character-classes',
'blue-mana-bar',
'monsters-quests',
'gems',
'bugs-features',
'world-boss',
];
let pageState = {};
for (let index in headings) {
let heading = headings[index];
pageState[heading] = false;
}
return {
activePage: '',
headings: ['overview', 'set-up-tasks', 'sample-tasks', 'task-color', 'health', 'party-with-friends', 'pets-mounts', 'character-classes', 'blue-mana-bar', 'monsters-quests', 'gems', 'bugs-features', 'world-boss'],
pageState,
headings,
replacements: {
techAssistanceEmail: TECH_ASSISTANCE_EMAIL,
wikiTechAssistanceEmail: `mailto:${TECH_ASSISTANCE_EMAIL}`,
@@ -35,7 +59,7 @@ export default {
},
methods: {
setActivePage (page) {
this.activePage = page;
this.pageState[page] = !this.pageState[page];
},
},
};
@@ -7,14 +7,18 @@
div(v-for='step in stepsNum')
h3 {{ $t('step'+step) }}
// @TODO: add markdown
p(v-html="$t('webStep'+step+'Text')")
p(v-markdown="$t('webStep'+step+'Text')")
hr
p(v-html="$t('overviewQuestions')")
p(v-markdown="$t('overviewQuestions')")
</template>
<script>
import markdownDirective from 'client/directives/markdown';
export default {
directives: {
markdown: markdownDirective,
},
data () {
return {
stepsNum: ['1', '2', '3'],