Added initial inbox (#8852)

* Added initial inbox

* Minor styles

* Added more styles, selected conversations, sending messages

* Added translations and colors
This commit is contained in:
Keith Holliday
2017-07-10 21:09:31 -06:00
committed by GitHub
parent 3aa7b4b631
commit 052c653cd3
4 changed files with 282 additions and 52 deletions

View File

@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="12" viewBox="0 0 16 12"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="12" viewBox="0 0 16 12">
<path fill="#4F2A93" fill-rule="evenodd" d="M14 10H2V2l6 5 6-5v8zm0-10H2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/> <path fill-rule="evenodd" d="M14 10H2V2l6 5 6-5v8zm0-10H2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 220 B

View File

@@ -1,54 +1,56 @@
<template lang="pug"> <template lang="pug">
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm div
.navbar-header inbox-modal
.logo.svg-icon(v-html="icons.logo") nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-sm
.collapse.navbar-collapse .navbar-header
ul.navbar-nav.mr-auto .logo.svg-icon(v-html="icons.logo")
router-link.nav-item(tag="li", :to="{name: 'tasks'}", exact) .collapse.navbar-collapse
a.nav-link(v-once) {{ $t('tasks') }} ul.navbar-nav.mr-auto
router-link.nav-item.dropdown(tag="li", :to="{name: 'items'}", :class="{'active': $route.path.startsWith('/inventory')}") router-link.nav-item(tag="li", :to="{name: 'tasks'}", exact)
a.nav-link(v-once) {{ $t('inventory') }} a.nav-link(v-once) {{ $t('tasks') }}
.dropdown-menu router-link.nav-item.dropdown(tag="li", :to="{name: 'items'}", :class="{'active': $route.path.startsWith('/inventory')}")
router-link.dropdown-item(:to="{name: 'items'}", exact) {{ $t('items') }} a.nav-link(v-once) {{ $t('inventory') }}
router-link.dropdown-item(:to="{name: 'equipment'}") {{ $t('equipment') }} .dropdown-menu
router-link.dropdown-item(:to="{name: 'stable'}") {{ $t('stable') }} router-link.dropdown-item(:to="{name: 'items'}", exact) {{ $t('items') }}
router-link.nav-item(tag="li", :to="{name: 'shops'}", exact) router-link.dropdown-item(:to="{name: 'equipment'}") {{ $t('equipment') }}
a.nav-link(v-once) {{ $t('shops') }} router-link.dropdown-item(:to="{name: 'stable'}") {{ $t('stable') }}
router-link.nav-item(tag="li", :to="{name: 'party'}") router-link.nav-item(tag="li", :to="{name: 'shops'}", exact)
a.nav-link(v-once) {{ $t('party') }} a.nav-link(v-once) {{ $t('shops') }}
router-link.nav-item.dropdown(tag="li", :to="{name: 'tavern'}", :class="{'active': $route.path.startsWith('/guilds')}") router-link.nav-item(tag="li", :to="{name: 'party'}")
a.nav-link(v-once) {{ $t('guilds') }} a.nav-link(v-once) {{ $t('party') }}
.dropdown-menu router-link.nav-item.dropdown(tag="li", :to="{name: 'tavern'}", :class="{'active': $route.path.startsWith('/guilds')}")
router-link.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }} a.nav-link(v-once) {{ $t('guilds') }}
router-link.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }} .dropdown-menu
router-link.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }} router-link.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
router-link.nav-item(tag="li", :to="{name: 'challenges'}", exact) router-link.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
a.nav-link(v-once) {{ $t('challenges') }} router-link.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}") router-link.nav-item(tag="li", :to="{name: 'challenges'}", exact)
a.nav-link(v-once) {{ $t('help') }} a.nav-link(v-once) {{ $t('challenges') }}
.dropdown-menu router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}")
router-link.dropdown-item(to="/help/faq") {{ $t('faq') }} a.nav-link(v-once) {{ $t('help') }}
router-link.dropdown-item(to="/help/report-bug") {{ $t('reportBug') }} .dropdown-menu
router-link.dropdown-item(to="/help/request-feature") {{ $t('requestAF') }} router-link.dropdown-item(to="/help/faq") {{ $t('faq') }}
.item-with-icon router-link.dropdown-item(to="/help/report-bug") {{ $t('reportBug') }}
.svg-icon(v-html="icons.gem") router-link.dropdown-item(to="/help/request-feature") {{ $t('requestAF') }}
span {{userGems | roundBigNumber}} .item-with-icon
.item-with-icon .svg-icon(v-html="icons.gem")
.svg-icon(v-html="icons.gold") span {{userGems | roundBigNumber}}
span {{user.stats.gp | roundBigNumber}} .item-with-icon
.item-with-icon.item-notifications .svg-icon(v-html="icons.gold")
.svg-icon(v-html="icons.notifications") span {{user.stats.gp | roundBigNumber}}
router-link.dropdown.item-with-icon.item-user(:to="{name: 'avatar'}") .item-with-icon.item-notifications
.svg-icon(v-html="icons.user") .svg-icon(v-html="icons.notifications")
.dropdown-menu.dropdown-menu-right.user-dropdown router-link.dropdown.item-with-icon.item-user(:to="{name: 'avatar'}")
router-link.dropdown-item.edit-avatar(:to="{name: 'avatar'}") .svg-icon(v-html="icons.user")
h3 {{ user.profile.name }} .dropdown-menu.dropdown-menu-right.user-dropdown
span.small-text {{ $t('editAvatar') }} router-link.dropdown-item.edit-avatar(:to="{name: 'avatar'}")
router-link.dropdown-item(:to="{name: 'inbox'}") {{ $t('inbox') }} h3 {{ user.profile.name }}
router-link.dropdown-item(:to="{name: 'stats'}") {{ $t('stats') }} span.small-text {{ $t('editAvatar') }}
router-link.dropdown-item(:to="{name: 'achievements'}") {{ $t('achievements') }} a.nav-link.dropdown-item(@click.prevent='showInbox()') {{ $t('inbox') }}
router-link.dropdown-item(:to="{name: 'settings'}") {{ $t('settings') }} router-link.dropdown-item(:to="{name: 'stats'}") {{ $t('stats') }}
a.nav-link.dropdown-item(to="/", @click.prevent='logout()') {{ $t('logout') }} router-link.dropdown-item(:to="{name: 'achievements'}") {{ $t('achievements') }}
router-link.dropdown-item(:to="{name: 'settings'}") {{ $t('settings') }}
a.nav-link.dropdown-item(to="/", @click.prevent='logout()') {{ $t('logout') }}
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -198,8 +200,12 @@ import goldIcon from 'assets/svg/gold.svg';
import notificationsIcon from 'assets/svg/notifications.svg'; import notificationsIcon from 'assets/svg/notifications.svg';
import userIcon from 'assets/svg/user.svg'; import userIcon from 'assets/svg/user.svg';
import logo from 'assets/svg/logo.svg'; import logo from 'assets/svg/logo.svg';
import InboxModal from './userMenu/inbox.vue';
export default { export default {
components: {
InboxModal,
},
data () { data () {
return { return {
icons: Object.freeze({ icons: Object.freeze({
@@ -222,6 +228,9 @@ export default {
localStorage.removeItem('habit-mobile-settings'); localStorage.removeItem('habit-mobile-settings');
this.$router.go('/'); this.$router.go('/');
}, },
showInbox () {
this.$root.$emit('show::modal', 'inbox-modal');
},
}, },
}; };
</script> </script>

View File

@@ -0,0 +1,218 @@
<template lang="pug">
b-modal#inbox-modal(title="", :hide-footer="true", size='lg')
.header-wrap.container(slot="modal-header")
.row
.col-4
.row
.col-2
.svg-icon.envelope(v-html="icons.messageIcon")
.col-6
h2.text-center(v-once) {{$t('messages')}}
// @TODO: Implement this after we fix username bug
// .col-2.offset-1
// button.btn.btn-secondary(@click='toggleClick()') +
// .col-8.to-form(v-if='displayCreate')
// strong To:
// b-form-input
.row
.col-4.sidebar
.search-section
b-form-input(:placeholder="$t('search')", v-model='search')
.empty-messages.text-center(v-if='filtersConversations.length === 0')
.svg-icon.envelope(v-html="icons.messageIcon")
h4(v-once) {{$t('emptyMessagesLine1')}}
p(v-once) {{$t('emptyMessagesLine2')}}
.conversations(v-if='filtersConversations.length > 0')
.conversation(v-for='conversation in conversations', @click='selectConversation(conversation.key)', :class="{active: selectedConversation === conversation.key}")
div
span {{conversation.name}}
span.timeago {{conversation.date}}
div {{conversation.lastMessageText}}
.col-8.messages
.message(v-for='message in currentMessages') {{message.text}}
// @TODO: Implement new message header here when we fix the above
.new-message-row(v-if='selectedConversation')
b-form-input(v-model='newMessage')
button.btn.btn-secondary(@click='sendPrivateMessage()') Send
</template>
<style lang="scss" scoped>
@import '~client/assets/scss/colors.scss';
.envelope {
color: $gray-400 !important;
margin-top: 1em;
}
h2 {
margin-top: .5em;
}
.sidebar {
background-color: $gray-700;
min-height: 600px;
padding: 0;
.search-section {
padding: 1em;
box-shadow: 0 1px 2px 0 rgba(26, 24, 29, 0.24);
}
}
.messages {
position: relative;
padding-left: 0;
}
.to-form input {
width: 60%;
display: inline-block;
margin-left: 1em;
}
.empty-messages {
margin-top: 10em;
color: $gray-400;
padding: 1em;
h4 {
color: $gray-400;
margin-top: 1em;
}
.envelope {
width: 30px;
margin: 0 auto;
}
}
.new-message-row {
background-color: $gray-700;
position: absolute;
bottom: 0;
height: 88px;
width: 100%;
padding: 1em;
input {
display: inline-block;
width: 80%;
}
button {
box-shadow: none;
margin-left: 1em;
}
}
.conversation {
padding: 1.5em;
background: $white;
height: 80px;
.timeago {
margin-left: 1em;
}
}
.conversation.active {
border: 1px solid $purple-400;
}
.conversation:hover {
cursor: pointer;
}
</style>
<script>
import moment from 'moment';
import filter from 'lodash/filter';
import { mapState } from 'client/libs/store';
import bModal from 'bootstrap-vue/lib/components/modal';
import bFormInput from 'bootstrap-vue/lib/components/form-input';
import messageIcon from 'assets/svg/message.svg';
export default {
components: {
bModal,
bFormInput,
},
data () {
return {
icons: Object.freeze({
messageIcon,
}),
displayCreate: true,
selectedConversation: '',
search: '',
newMessage: '',
};
},
computed: {
...mapState({user: 'user.data'}),
conversations () {
let conversations = {};
for (let messageId in this.user.inbox.messages) {
let message = this.user.inbox.messages[messageId];
let userId = message.uuid;
if (!this.selectedConversation) this.selectedConversation = userId;
if (!conversations[userId]) {
conversations[userId] = {
name: message.user,
key: userId,
messages: [],
};
}
conversations[userId].messages.push({
text: message.text,
timestamp: message.timestamp,
});
conversations[userId].lastMessageText = message.text;
conversations[userId].date = moment(new Date(message.timestamp)).fromNow();
}
return conversations;
},
currentMessages () {
if (!this.selectedConversation) return;
return this.conversations[this.selectedConversation].messages;
},
filtersConversations () {
if (!this.search) return Object.values(this.conversations);
return filter(this.conversations, (conversation) => {
return conversation.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1;
});
},
},
methods: {
toggleClick () {
this.displayCreate = !this.displayCreate;
},
selectConversation (key) {
this.selectedConversation = key;
},
sendPrivateMessage () {
this.$store.dispatch('members:sendPrivateMessage', {
toUserId: this.selectedConversation,
message: this.newMessage,
});
this.conversations[this.selectedConversation].messages.push({
text: this.newMessage,
timestamp: new Date(),
});
this.conversations[this.selectedConversation].lastMessageText = this.newMessage;
this.conversations[this.selectedConversation].date = new Date();
this.newMessage = '';
},
},
};
</script>

View File

@@ -180,5 +180,8 @@
"tier7": "Tier 7 (Legendary)", "tier7": "Tier 7 (Legendary)",
"tierModerator": "Moderator (Guardian)", "tierModerator": "Moderator (Guardian)",
"tierStaff": "Staff (Heroic)", "tierStaff": "Staff (Heroic)",
"tierNPC": "NPC" "tierNPC": "NPC",
"messages": "Messages",
"emptyMessagesLine1": "You dont have any messages",
"emptyMessagesLine2": "Send a message to start a conversation!"
} }