Feature: Contact Panel with conversation details (#397)
* Add Contact panel changes * Fix parent iframe blocked * Add Conversation Panel, Contact messages * Update contact panel with conversation details * Update designs in sidebar * Fix specs * Specs: Add specs for conversationMetadata and contact modules * Fix currentUrl issues * Fix spelling * Set default to empty string
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="conv-details--item">
|
||||
<div class="conv-details--item__label">
|
||||
<i :class="icon" class="conv-details--item__icon"></i>
|
||||
{{ title }}
|
||||
</div>
|
||||
<div class="conv-details--item__value">
|
||||
{{ value }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: { type: String, required: true },
|
||||
icon: { type: String, required: true },
|
||||
value: { type: [String, Number], default: '' },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~dashboard/assets/scss/variables';
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
|
||||
.conv-details--item {
|
||||
padding-bottom: $space-normal;
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.conv-details--item__icon {
|
||||
padding-right: $space-micro;
|
||||
}
|
||||
|
||||
.conv-details--item__label {
|
||||
font-weight: $font-weight-medium;
|
||||
margin-bottom: $space-micro;
|
||||
}
|
||||
|
||||
.conv-details--item__value {
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,37 +1,127 @@
|
||||
<template>
|
||||
<div class="medium-3 bg-white contact--panel">
|
||||
<thumbnail
|
||||
:src="contactImage"
|
||||
size="80px"
|
||||
:badge="contact.channel"
|
||||
:username="contact.name"
|
||||
/>
|
||||
<h4>
|
||||
{{ contact.name }}
|
||||
</h4>
|
||||
<div class="contact--profile">
|
||||
<div class="contact--info">
|
||||
<thumbnail
|
||||
:src="contact.avatar_url"
|
||||
size="56px"
|
||||
:badge="contact.channel"
|
||||
:username="contact.name"
|
||||
/>
|
||||
<div class="contact--details">
|
||||
<div class="contact--name">
|
||||
{{ contact.name }}
|
||||
</div>
|
||||
<a
|
||||
v-if="contact.email"
|
||||
:href="`mailto:${contact.email}`"
|
||||
class="contact--email"
|
||||
>
|
||||
{{ contact.email }}
|
||||
</a>
|
||||
<div class="contact--location">
|
||||
{{ contact.location }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="contact.bio" class="contact--bio">
|
||||
{{ contact.bio }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="browser" class="conversation--details">
|
||||
<contact-details-item
|
||||
v-if="browser.browser_name"
|
||||
:title="$t('CONTACT_PANEL.BROWSER')"
|
||||
:value="browserName"
|
||||
icon="ion-ios-world-outline"
|
||||
/>
|
||||
<contact-details-item
|
||||
v-if="browser.platform_name"
|
||||
:title="$t('CONTACT_PANEL.OS')"
|
||||
:value="platformName"
|
||||
icon="ion-laptop"
|
||||
/>
|
||||
<contact-details-item
|
||||
v-if="referer"
|
||||
:title="$t('CONTACT_PANEL.INITIATED_FROM')"
|
||||
:value="referer"
|
||||
icon="ion-link"
|
||||
/>
|
||||
<contact-details-item
|
||||
v-if="initiatedAt"
|
||||
:title="$t('CONTACT_PANEL.INITIATED_AT')"
|
||||
:value="initiatedAt.timestamp"
|
||||
icon="ion-clock"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||
import ContactDetailsItem from './ContactDetailsItem.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ContactDetailsItem,
|
||||
Thumbnail,
|
||||
},
|
||||
props: {
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentChat: 'getSelectedChat',
|
||||
}),
|
||||
currentConversationMetaData() {
|
||||
return this.$store.getters[
|
||||
'conversationMetadata/getConversationMetadata'
|
||||
](this.conversationId);
|
||||
},
|
||||
additionalAttributes() {
|
||||
return this.currentConversationMetaData.additional_attributes || {};
|
||||
},
|
||||
browser() {
|
||||
return this.additionalAttributes.browser || {};
|
||||
},
|
||||
referer() {
|
||||
return this.additionalAttributes.referer;
|
||||
},
|
||||
initiatedAt() {
|
||||
return this.additionalAttributes.initiated_at;
|
||||
},
|
||||
browserName() {
|
||||
return `${this.browser.browser_name || ''} ${this.browser
|
||||
.browser_version || ''}`;
|
||||
},
|
||||
platformName() {
|
||||
const {
|
||||
platform_name: platformName,
|
||||
platform_version: platformVersion,
|
||||
} = this.browser;
|
||||
return `${platformName || ''} ${platformVersion || ''}`;
|
||||
},
|
||||
contactId() {
|
||||
return this.currentConversationMetaData.contact_id;
|
||||
},
|
||||
contact() {
|
||||
const { meta: { sender = {} } = {} } = this.currentChat || {};
|
||||
return sender;
|
||||
return this.$store.getters['contacts/getContact'](this.contactId);
|
||||
},
|
||||
contactImage() {
|
||||
return `/uploads/avatar/contact/${this.contact.id}/profilepic.jpeg`;
|
||||
},
|
||||
watch: {
|
||||
contactId(newContactId, prevContactId) {
|
||||
if (newContactId && newContactId !== prevContactId) {
|
||||
this.$store.dispatch('contacts/show', {
|
||||
id: this.currentConversationMetaData.contact_id,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('contacts/show', {
|
||||
id: this.currentConversationMetaData.contact_id,
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -41,9 +131,70 @@ export default {
|
||||
|
||||
.contact--panel {
|
||||
@include border-normal-left;
|
||||
font-size: $font-size-small;
|
||||
overflow-y: auto;
|
||||
background: $color-white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.contact--profile {
|
||||
width: 100%;
|
||||
padding: $space-normal $space-medium $zero;
|
||||
align-items: center;
|
||||
|
||||
.user-thumbnail-box {
|
||||
margin-right: $space-normal;
|
||||
}
|
||||
}
|
||||
|
||||
.contact--details {
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.contact--info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: $space-large $space-normal $space-normal;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.contact--name {
|
||||
@include text-ellipsis;
|
||||
|
||||
font-weight: $font-weight-bold;
|
||||
font-size: $font-size-default;
|
||||
}
|
||||
|
||||
.contact--email {
|
||||
@include text-ellipsis;
|
||||
|
||||
color: $color-body;
|
||||
display: block;
|
||||
line-height: $space-medium;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.contact--bio {
|
||||
margin-top: $space-normal;
|
||||
}
|
||||
|
||||
.conversation--details {
|
||||
padding: $space-normal $space-medium;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.conversation--labels {
|
||||
padding: $space-medium;
|
||||
|
||||
.icon {
|
||||
margin-right: $space-micro;
|
||||
font-size: $font-size-micro;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #fff;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
@contactPanelToggle="onToggleContactPanel"
|
||||
>
|
||||
</conversation-box>
|
||||
<contact-panel v-if="isContactPanelOpen"></contact-panel>
|
||||
<contact-panel
|
||||
v-if="isContactPanelOpen"
|
||||
:conversation-id="conversationId"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user