Sept 21 fixes (#9061)

* Fixed analytics when party is not defined:

* Waited to set Stripe

* Added popovers to danger zone

* Added date format to next cron

* Redirect user back to home for static

* Removed old settings

* Fixed show bailey

* Fixed close button on inbox

* Fixed sending blank message

* Changed input to text area in inbox

* Fixed deleting messages in inbox

* Allowed user to delete other user message in inbox

* Fixed joined date

* Fixed count styling

* Fixed display of pet and mount

* Removed white box when using base_0 items

* Fixed your profile to show when clicking from menu

* Prevented user from pinning already purchased backgroud

* Added user last log in

* Added date refresh for yesterdailies modal

* Updatd eyewear

* Fixed start a quest button

* Fixed styles on home page footer

* Added checklist sorting

* Added support for if card type is missing computed field

* Fixed linting
This commit is contained in:
Keith Holliday
2017-09-21 18:53:45 -05:00
committed by GitHub
parent 81fc727d41
commit 744090e652
14 changed files with 147 additions and 59 deletions
+1
View File
@@ -364,6 +364,7 @@ export default {
this.$root.$emit('show::modal', 'avatar-modal');
},
showProfile (startingPage) {
this.$store.state.profileUser = this.user;
this.$store.state.profileOptions.startingPage = startingPage;
this.$root.$emit('show::modal', 'profile');
},
@@ -40,7 +40,7 @@
span.action(v-if='user.contributor.admin || (msg.uuid !== user._id && user.flags.communityGuidelinesAccepted)', @click='report(msg)')
.svg-icon(v-html="icons.report")
| {{$t('report')}}
span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)')
span.action(v-if='msg.uuid === user._id || inbox', @click='remove(msg, index)')
.svg-icon(v-html="icons.delete")
| {{$t('delete')}}
span.action.float-right(v-if='likeCount(msg) > 0')
@@ -375,6 +375,12 @@ export default {
},
async remove (message, index) {
this.chat.splice(index, 1);
if (this.inbox) {
axios.delete(`/api/v3/user/messages/${message.id}`);
return;
}
await this.$store.dispatch('chat:deleteChat', {
groupId: this.groupId,
chatId: message.id,
+18 -8
View File
@@ -189,13 +189,8 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
strong(v-once) {{$t('flower')}}
.row(v-if='activeSubPage === "glasses"')
.col-12.customize-options
.eyewear_special_blackTopFrame.option(@click='equip("eyewear_special_blackTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_blackTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_blackTopFrame"}')
.eyewear_special_blueTopFrame.option(@click='equip("eyewear_special_blueTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_blueTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_blueTopFrame"}')
.eyewear_special_greenTopFrame.option(@click='equip("eyewear_special_greenTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_greenTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_greenTopFrame"}')
.eyewear_special_pinkTopFrame.option(@click='equip("eyewear_special_pinkTopFrame")', :class='{active: user.preferences.costume ? user.items.gear.costume.eyewear === "eyewear_special_pinkTopFrame" : user.items.gear.equipped.eyewear === "eyewear_special_pinkTopFrame"}')
.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"}')
.option(v-for='option in eyewear', :class='{active: option.active}')
.sprite.customize-option(:class="`eyewear_special_${option.key}`", @click='option.click')
#animal-ears.col-12.customize-options(v-if='editing')
.option(v-for='option in animalEars',
:class='{active: option.active, locked: option.locked}')
@@ -262,7 +257,8 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru
span 7
span.badge.badge-pill.badge-item.badge-svg(
:class="{'item-selected-badge': isBackgroundPinned(bg), 'hide': !isBackgroundPinned(bg)}",
@click.prevent.stop="togglePinned(bg)"
@click.prevent.stop="togglePinned(bg)",
v-if='!user.purchased.background[bg.key]'
)
span.svg-icon.inline.icon-12.color(v-html="icons.pin")
@@ -979,6 +975,20 @@ export default {
},
computed: {
...mapState({user: 'user.data'}),
eyewear () {
let keys = ['blackTopFrame', 'blueTopFrame', 'greenTopFrame', 'pinkTopFrame', 'redTopFrame', 'whiteTopFrame', 'yellowTopFrame'];
let options = keys.map(key => {
let newKey = `eyewear_special_${key}`;
let option = {};
option.key = key;
option.active = this.user.preferences.costume ? this.user.items.gear.costume.eyewear === newKey : this.user.items.gear.equipped.eyewear === newKey;
option.click = () => {
return this.equip(newKey);
};
return option;
});
return options;
},
animalEarsUnlockString () {
let animalItemKeys = this.animalEarsKeys.map(key => {
return `items.gear.owned.headAccessory_special_${key}`;
@@ -12,7 +12,7 @@
div(v-if='questData')
questDialogContent(:item="questData")
div.text-center
button.btn.btn-primary(@click='questInit()', :disabled="Boolean(group.quest)") {{$t('inviteToPartyOrQuest')}}
button.btn.btn-primary(@click='questInit()', :disabled="!Boolean(selectedQuest)") {{$t('inviteToPartyOrQuest')}}
div.text-center
p {{$t('inviteInformation')}}
.side-panel(v-if='questData')
@@ -321,8 +321,8 @@ export default {
}
for (let type in this.content.cardTypes) {
if (this.user.items.special[type] > 0) {
let card = this.user.items.special[`${this.cardType}Received`];
let card = this.user.items.special[`${type}Received`] || [];
if (this.user.items.special[type] > 0 || card.length > 0) {
specialArray.push({
type: 'card',
key: type,
+8 -17
View File
@@ -41,18 +41,6 @@
hr
div
.checkbox
label
input(type='checkbox', @click='hideHeader() ', v-model='user.preferences.hideHeader')
span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('showHeaderPop')") {{ $t('showHeader') }}
.checkbox
label
input(type='checkbox', @click='toggleStickyHeader()', v-model='user.preferences.stickyHeader', :disabled="user.preferences.hideHeader")
span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('stickyHeaderPop')") {{ $t('stickyHeader') }}
.checkbox
label
input(type='checkbox', v-model='user.preferences.newTaskEdit', @click='set("newTaskEdit")')
span.hint(popover-trigger='mouseenter', popover-placement='right', :popover="$t('newTaskEditPop')") {{ $t('newTaskEdit') }}
.checkbox
label
input(type='checkbox', v-model='user.preferences.tagsCollapsed', @change='set("tagsCollapsed")')
@@ -186,9 +174,9 @@
h5 {{ $t('dangerZone') }}
div
button.btn.btn-danger(@click='openResetModal()',
popover-trigger='mouseenter', popover-placement='right', :popover="$t('resetAccPop')") {{ $t('resetAccount') }}
popover-trigger='mouseenter', popover-placement='right', v-b-popover.hover.auto="$t('resetAccPop')") {{ $t('resetAccount') }}
button.btn.btn-danger(@click='openDeleteModal()',
popover-trigger='mouseenter', :popover="$t('deleteAccPop')") {{ $t('deleteAccount') }}
popover-trigger='mouseenter', v-b-popover.hover.auto="$t('deleteAccPop')") {{ $t('deleteAccount') }}
</template>
<style scoped>
@@ -203,6 +191,7 @@ import moment from 'moment';
import axios from 'axios';
import { mapState } from 'client/libs/store';
import bPopover from 'bootstrap-vue/lib/directives/popover';
import restoreModal from './restoreModal';
import resetModal from './resetModal';
import deleteModal from './deleteModal';
@@ -217,6 +206,9 @@ export default {
resetModal,
deleteModal,
},
directives: {
bPopover,
},
data () {
let dayStartOptions = [];
for (let number = 0; number < 24; number += 1) {
@@ -298,8 +290,7 @@ export default {
// Guide.goto('intro', 0, true);
},
showBailey () {
this.user.flags.newStuff = true;
this.set('flags', 'newStuff');
this.$root.$emit('show::modal', 'new-stuff');
},
hasBackupAuthOption (networkKeyToCheck) {
if (this.user.auth.local.username) {
@@ -322,7 +313,7 @@ export default {
nextCron = nextCron.add(1, 'day');
}
return nextCron.format('x');
return nextCron.format(this.user.preferences.dateFormat.toUpperCase());
},
openDayStartModal () {
let nextCron = this.calculateNextCron();
@@ -157,8 +157,18 @@ export default {
}),
};
},
computed: {
isUserLoggedIn () {
return this.$store.state.isUserLoggedIn;
},
},
methods: {
playButtonClick () {
if (this.isUserLoggedIn) {
this.$router.push('/');
return;
}
// @TODO duplicate of code in home.vue
Analytics.track({
hitType: 'event',
+3 -2
View File
@@ -125,7 +125,7 @@
#purple-footer {
background-color: #271b3d;
footer, footer a {
footer, footer a, footer h3 {
background: transparent;
color: #d5c8ff;
}
@@ -451,7 +451,7 @@
.svg-icon {
vertical-align: bottom;
color: #fff;
color: #d5c8ff;
display: inline-block;
margin-right: 1em;
}
@@ -517,6 +517,7 @@
position: absolute;
height: 500px;
width: 100%;
opacity: .5;
}
}
</style>
+24 -4
View File
@@ -30,10 +30,12 @@
.option(v-if="['daily', 'todo'].indexOf(task.type) > -1")
label(v-once) {{ $t('checklist') }}
br
.inline-edit-input-group.checklist-group.input-group(v-for="(item, $index) in task.checklist")
input.inline-edit-input.checklist-item.form-control(type="text", v-model="item.text")
span.input-group-btn(@click="removeChecklistItem($index)")
.svg-icon.destroy-icon(v-html="icons.destroy")
| {{checklist}}
div(v-sortable='', @onsort='sortedChecklist')
.inline-edit-input-group.checklist-group.input-group(v-for="(item, $index) in checklist")
input.inline-edit-input.checklist-item.form-control(type="text", v-model="item.text")
span.input-group-btn(@click="removeChecklistItem($index)")
.svg-icon.destroy-icon(v-html="icons.destroy")
input.inline-edit-input.checklist-item.form-control(type="text", :placeholder="$t('newChecklistItem')", @keydown.enter="addChecklistItem($event)", v-model="newChecklistItem")
.d-flex.justify-content-center(v-if="task.type === 'habit'")
.option-item(:class="optionClass(task.up === true)", @click="task.up = !task.up")
@@ -401,6 +403,8 @@ import { mapGetters, mapActions, mapState } from 'client/libs/store';
import bDropdown from 'bootstrap-vue/lib/components/dropdown';
import bDropdownItem from 'bootstrap-vue/lib/components/dropdown-item';
import toggleSwitch from 'client/components/ui/toggleSwitch';
import sortable from 'client/directives/sortable.directive';
import clone from 'lodash/clone';
import Datepicker from 'vuejs-datepicker';
import moment from 'moment';
import uuid from 'uuid';
@@ -423,6 +427,9 @@ export default {
Datepicker,
toggleSwitch,
},
directives: {
sortable,
},
props: ['task', 'purpose', 'challengeId', 'groupId'], // purpose is either create or edit, task is the task created or edited
data () {
return {
@@ -444,6 +451,7 @@ export default {
members: [],
memberNamesById: {},
assignedMembers: [],
checklist: [],
};
},
watch: {
@@ -464,6 +472,9 @@ export default {
this.assignedMembers = [];
if (this.task.group && this.task.group.assignedUsers) this.assignedMembers = this.task.group.assignedUsers;
}
// @TODO: This whole component is mutating a prop and that causes issues. We need to not copy the prop similar to group modals
if (this.task) this.checklist = clone(this.task.checklist);
},
},
computed: {
@@ -534,6 +545,13 @@ export default {
},
methods: {
...mapActions({saveTask: 'tasks:save', destroyTask: 'tasks:destroy', createTask: 'tasks:create'}),
sortedChecklist (data) {
let sorting = clone(this.checklist);
let movingItem = sorting[data.oldIndex];
sorting.splice(data.oldIndex, 1);
sorting.splice(data.newIndex, 0, movingItem);
this.task.checklist = sorting;
},
optionClass (activeCondition) {
if (activeCondition) {
return [`${this.cssClass}-color`, 'option-item-selected'];
@@ -547,11 +565,13 @@ export default {
text: this.newChecklistItem,
completed: false,
});
this.checklist = clone(this.task.checklist);
this.newChecklistItem = null;
if (e) e.preventDefault();
},
removeChecklistItem (i) {
this.task.checklist.splice(i, 1);
this.checklist = clone(this.task.checklist);
},
weekdaysMin (dayNumber) {
return moment.weekdaysMin(dayNumber);
+21 -2
View File
@@ -11,6 +11,8 @@
// @TODO: Implement this after we fix username bug
// .col-2.offset-1
// button.btn.btn-secondary(@click='toggleClick()') +
.col-4.offset-4
.svg-icon.close(v-html="icons.svgClose", @click='close()')
// .col-8.to-form(v-if='displayCreate')
// strong To:
// b-form-input
@@ -39,7 +41,7 @@
// @TODO: Implement new message header here when we fix the above
.new-message-row(v-if='selectedConversation')
input(v-model='newMessage')
textarea(v-model='newMessage')
button.btn.btn-secondary(@click='sendPrivateMessage()') Send
</template>
@@ -51,6 +53,11 @@
margin-top: 1em;
}
.close {
margin-top: .5em;
width: 15px;
}
h2 {
margin-top: .5em;
}
@@ -107,12 +114,16 @@
width: 100%;
padding: 1em;
input {
textarea {
height: 80%;
display: inline-block;
vertical-align: bottom;
width: 80%;
}
button {
vertical-align: bottom;
display: inline-block;
box-shadow: none;
margin-left: 1em;
}
@@ -155,6 +166,7 @@ import bFormInput from 'bootstrap-vue/lib/components/form-input';
import messageIcon from 'assets/svg/message.svg';
import chatMessage from '../chat/chatMessages';
import svgClose from 'assets/svg/close.svg';
export default {
mixins: [styleHelper],
@@ -167,6 +179,7 @@ export default {
return {
icons: Object.freeze({
messageIcon,
svgClose,
}),
displayCreate: true,
selectedConversation: '',
@@ -201,6 +214,7 @@ export default {
timestamp: message.timestamp,
user: message.user,
uuid: message.uuid,
id: message.id,
};
if (message.sent) {
@@ -256,6 +270,8 @@ export default {
});
},
sendPrivateMessage () {
if (!this.newMessage) return;
let convoFound = this.conversations.find((conversation) => {
return conversation.key === this.selectedConversation;
});
@@ -284,6 +300,9 @@ export default {
chatscroll.scrollTop = chatscroll.scrollHeight;
});
},
close () {
this.$root.$emit('hide::modal', 'inbox-modal');
},
},
};
</script>
+30 -15
View File
@@ -47,7 +47,10 @@ div
h2 {{ $t('info') }}
div
strong {{ $t('joined') }}:
| {{user.auth.timestamps.created}}
| {{userJoinedDate}}
div
strong {{ $t('lastLoggedIn') }}:
| {{userLastLoggedIn}}
div
strong {{ $t('totalLogins') }}:
span {{ $t('totalCheckins', {count: user.loginIncentives}) }}
@@ -100,7 +103,7 @@ div
h4.popover-content-title {{ achievement.title }}
div.popover-content-text(v-html="achievement.text")
.achievement(:class='achievement.icon + "2x"', v-if='achievement.earned')
.counter.badge.badge-info.stack-count(v-if='achievement.optionalCount') {{achievement.optionalCount}}
.counter.badge.badge-info.stack-count(v-if='achievement.optionalCount') {{achievement.optionalCount}}
.achievement.achievement-unearned(class='achievement-unearned2x', v-if='!achievement.earned')
hr.col-12
.row
@@ -126,7 +129,7 @@ div
div(:class="`shop_${equippedItems.eyewear}`")
h3 {{$t('eyewear')}}
.col-4.item-wrapper
.box(:class='{white: equippedItems.head}')
.box(:class='{white: equippedItems.head && equippedItems.head.indexOf("base_0") === -1}')
div(:class="`shop_${equippedItems.head}`")
h3 {{$t('headGear')}}
.col-4.item-wrapper
@@ -138,7 +141,7 @@ div
div(:class="`shop_${equippedItems.backAccessory}`")
h3 {{$t('backAccess')}}
.col-4.item-wrapper
.box(:class='{white: equippedItems.armor}')
.box(:class='{white: equippedItems.armor && equippedItems.armor.indexOf("base_0") === -1}')
div(:class="`shop_${equippedItems.armor}`")
h3 {{$t('armor')}}
.col-4.item-wrapper
@@ -146,12 +149,12 @@ div
div(:class="`shop_${equippedItems.bodyAccessory}`")
h3 {{$t('bodyAccess')}}
.col-4.item-wrapper
.box(:class='{white: equippedItems.weapon}')
.box(:class='{white: equippedItems.weapon && equippedItems.weapon.indexOf("base_0") === -1}')
div(:class="`shop_${equippedItems.weapon}`")
h3 {{$t('mainHand')}}
.col-4.item-wrapper
.col-4.item-wrapper
.box(:class='{white: equippedItems.shield}')
.box(:class='{white: equippedItems.shield && equippedItems.shield.indexOf("base_0") === -1}')
div(:class="`shop_${equippedItems.shield}`")
h3 {{$t('offHand')}}
.col-6
@@ -162,7 +165,7 @@ div
div(:class="`shop_${costumeItems.eyewear}`")
h3 {{$t('eyewear')}}
.col-4.item-wrapper
.box(:class='{white: costumeItems.head}')
.box(:class='{white: costumeItems.head && costumeItems.head.indexOf("base_0") === -1}')
div(:class="`shop_${costumeItems.head}`")
h3 {{$t('headGear')}}
.col-4.item-wrapper
@@ -174,7 +177,7 @@ div
div(:class="`shop_${costumeItems.backAccessory}`")
h3 {{$t('backAccess')}}
.col-4.item-wrapper
.box(:class='{white: costumeItems.armor}')
.box(:class='{white: costumeItems.armor && costumeItems.armor.indexOf("base_0") === -1}')
div(:class="`shop_${costumeItems.armor}`")
h3 {{$t('armor')}}
.col-4.item-wrapper
@@ -182,7 +185,7 @@ div
div(:class="`shop_${costumeItems.bodyAccessory}`")
h3 {{$t('bodyAccess')}}
.col-4.item-wrapper
.box(:class='{white: costumeItems.weapon}')
.box(:class='{white: costumeItems.weapon && costumeItems.weapon.indexOf("base_0") === -1}')
div(:class="`shop_${costumeItems.weapon}`")
h3 {{$t('mainHand')}}
.col-4.item-wrapper
@@ -190,7 +193,7 @@ div
div(:class="user.preferences.background")
h3 {{$t('background')}}
.col-4.item-wrapper
.box(:class='{white: costumeItems.shield}')
.box(:class='{white: costumeItems.shield && costumeItems.shield.indexOf("base_0") === -1}')
div(:class="`shop_${costumeItems.shield}`")
h3 {{$t('offHand')}}
.row.pet-mount-row
@@ -200,7 +203,7 @@ div
.row.col-12
.col-4
.box(:class='{white: user.items.currentPet}')
div(:class="user.items.currentPet")
.pet(:class="`Pet-${user.items.currentPet}`")
.col-8
div
| {{ formatAnimal(user.items.currentPet, 'pet') }}
@@ -216,7 +219,7 @@ div
.row.col-12
.col-4
.box(:class='{white: user.items.currentMount}')
div(:class="user.items.currentMount")
.mount(:class="`Mount-${user.items.currentMount}`")
.col-8
div
| {{ formatAnimal(user.items.currentMount, 'mount') }}
@@ -322,6 +325,10 @@ div
margin-bottom: 2em;
}
.pet, .mount {
margin-top: -1.6em;
}
.header {
h1 {
color: #4f2a93;
@@ -399,9 +406,10 @@ div
color: #fff;
background-color: #ff944c;
box-shadow: 0 1px 1px 0 rgba(26, 24, 29, 0.12);
width: 24px;
height: 24px;
border-radius: 50%;
min-width: 24px;
min-height: 24px;
border-radius: 2em;
padding: .5em;
}
.achievement-icon {
@@ -537,6 +545,7 @@ div
</style>
<script>
import moment from 'moment';
import axios from 'axios';
import bModal from 'bootstrap-vue/lib/components/modal';
import each from 'lodash/each';
@@ -629,6 +638,12 @@ export default {
userLoggedIn: 'user.data',
flatGear: 'content.gear.flat',
}),
userJoinedDate () {
return moment(this.user.auth.timestamps.created).format(this.userLoggedIn.preferences.dateFormat.toUpperCase());
},
userLastLoggedIn () {
return moment(this.user.auth.timestamps.loggedin).format(this.userLoggedIn.preferences.dateFormat.toUpperCase());
},
equippedItems () {
return this.user.items.gear.equipped;
},
@@ -1,7 +1,7 @@
<template lang="pug">
b-modal#yesterdaily(
size="m",
:hide-header="true",
size="m",
:hide-header="true",
:hide-footer="true",
:no-close-on-backdrop="true",
:no-close-on-esc="true",
@@ -70,6 +70,8 @@ export default {
computed: {
...mapState({user: 'user.data'}),
tasksByType () {
this.dueDate = moment().subtract(1, 'days');
return {
daily: this.yesterDailies,
};
+4 -1
View File
@@ -5,10 +5,13 @@ import subscriptionBlocks from '../../common/script/content/subscriptionBlocks';
import { mapState } from 'client/libs/store';
import notificationsMixin from 'client/mixins/notifications';
let StripeCheckout = window.StripeCheckout;
let StripeCheckout;
export default {
mixins: [notificationsMixin],
created () {
StripeCheckout = window.StripeCheckout;
},
computed: {
...mapState(['credentials']),
paypalCheckoutLink () {
+14 -4
View File
@@ -5,10 +5,20 @@ import * as Analytics from 'client/libs/analytics';
// }
export async function sendAction (store, payload) {
Analytics.updateUser({
partyID: store.state.party.data._id,
partySize: store.state.party.data.memberCount,
});
// @TODO: Maybe move this to server
let partyData = {
partyID: store.state.user.data.party._id,
partySize: store.state.party.members.data.length,
};
if (store.state.party) {
partyData = {
partyID: store.state.party.data._id,
partySize: store.state.party.data.memberCount,
};
}
Analytics.updateUser(partyData);
let response = await axios.post(`/api/v3/groups/${payload.groupId}/${payload.action}`);