feat: Improve email rendering, introduce a new layout for emails (#5039)

Co-authored-by: Fayaz Ahmed <15716057+fayazara@users.noreply.github.com>
This commit is contained in:
Pranav Raj S
2022-08-01 10:53:50 +05:30
committed by GitHub
parent ef9ea99b91
commit 2c372fe315
19 changed files with 282 additions and 71 deletions

View File

@@ -1,5 +1,11 @@
<template>
<div class="conversations-list-wrap">
<div
class="conversations-list-wrap"
:class="{
hide: !showConversationList,
'list--full-width': isOnExpandedLayout,
}"
>
<slot />
<div
class="chat-list__top"
@@ -46,7 +52,7 @@
<woot-button
v-else
v-tooltip.top-end="$t('FILTER.TOOLTIP_LABEL')"
v-tooltip.right="$t('FILTER.TOOLTIP_LABEL')"
variant="clear"
color-scheme="secondary"
icon="filter"
@@ -210,6 +216,14 @@ export default {
type: [String, Number],
default: 0,
},
showConversationList: {
default: true,
type: Boolean,
},
isOnExpandedLayout: {
default: false,
type: Boolean,
},
},
data() {
return {
@@ -696,6 +710,17 @@ export default {
@include breakpoint(xxxlarge up) {
flex-basis: 46rem;
}
&.hide {
display: none;
}
&.list--full-width {
width: 100%;
@include breakpoint(xxxlarge up) {
flex-basis: 100%;
}
}
}
.filter--actions {
display: flex;

View File

@@ -1,9 +1,13 @@
<template>
<div class="conversation-details-wrap">
<div
class="conversation-details-wrap"
:class="{ 'with-border-left': !isOnExpandedLayout }"
>
<conversation-header
v-if="currentChat.id"
:chat="currentChat"
:is-contact-panel-open="isContactPanelOpen"
:show-back-button="isOnExpandedLayout"
@contact-panel-toggle="onToggleContactPanel"
/>
<woot-tabs
@@ -26,7 +30,7 @@
:is-contact-panel-open="isContactPanelOpen"
@contact-panel-toggle="onToggleContactPanel"
/>
<empty-state v-else />
<empty-state v-else :is-on-expanded-layout="isOnExpandedLayout" />
<div v-show="showContactPanel" class="conversation-sidebar-wrap">
<contact-panel
v-if="showContactPanel"
@@ -71,6 +75,10 @@ export default {
type: Boolean,
default: true,
},
isOnExpandedLayout: {
type: Boolean,
default: true,
},
},
data() {
return { activeIndex: 0 };
@@ -134,8 +142,11 @@ export default {
flex-direction: column;
min-width: 0;
width: 100%;
border-left: 1px solid var(--color-border);
background: var(--color-background-light);
&.with-border-left {
border-left: 1px solid var(--color-border);
}
}
.dashboard-app--tabs {

View File

@@ -1,6 +1,7 @@
<template>
<div class="conv-header">
<div class="user">
<back-button v-if="showBackButton" :back-url="backButtonUrl" />
<Thumbnail
:src="currentContact.thumbnail"
size="40px"
@@ -47,19 +48,21 @@
</div>
</template>
<script>
import { hasPressedAltAndOKey } from 'shared/helpers/KeyboardHelpers';
import { mapGetters } from 'vuex';
import MoreActions from './MoreActions';
import Thumbnail from '../Thumbnail';
import agentMixin from '../../../mixins/agentMixin.js';
import BackButton from '../BackButton';
import differenceInHours from 'date-fns/differenceInHours';
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
import inboxMixin from 'shared/mixins/inboxMixin';
import { hasPressedAltAndOKey } from 'shared/helpers/KeyboardHelpers';
import wootConstants from '../../../constants';
import differenceInHours from 'date-fns/differenceInHours';
import InboxName from '../InboxName';
import MoreActions from './MoreActions';
import Thumbnail from '../Thumbnail';
import wootConstants from '../../../constants';
import { conversationListPageURL } from 'dashboard/helper/URLHelper';
export default {
components: {
BackButton,
InboxName,
MoreActions,
Thumbnail,
@@ -74,6 +77,10 @@ export default {
type: Boolean,
default: false,
},
showBackButton: {
type: Boolean,
default: false,
},
},
computed: {
...mapGetters({
@@ -83,6 +90,19 @@ export default {
chatMetadata() {
return this.chat.meta;
},
backButtonUrl() {
const {
params: { accountId, inbox_id: inboxId, label, teamId },
name,
} = this.$route;
return conversationListPageURL({
accountId,
inboxId,
label,
teamId,
conversationType: name === 'conversation_mentions' ? 'mention' : '',
});
},
isHMACVerified() {
if (!this.isAWebWidgetInbox) {
return true;

View File

@@ -35,7 +35,7 @@
<!-- No conversation selected -->
<div v-else-if="allConversations.length && !currentChat.id">
<img src="~dashboard/assets/images/chat.svg" alt="No Chat" />
<span>{{ $t('CONVERSATION.404') }}</span>
<span>{{ conversationMissingMessage }}</span>
</div>
</div>
</div>
@@ -51,6 +51,12 @@ export default {
OnboardingView,
},
mixins: [accountMixin, adminMixin],
props: {
isOnExpandedLayout: {
type: Boolean,
default: false,
},
},
computed: {
...mapGetters({
currentChat: 'getSelectedChat',
@@ -65,6 +71,12 @@ export default {
}
return this.$t('CONVERSATION.LOADING_CONVERSATIONS');
},
conversationMissingMessage() {
if (!this.isOnExpandedLayout) {
return this.$t('CONVERSATION.SELECT_A_CONVERSATION');
}
return this.$t('CONVERSATION.404');
},
newInboxURL() {
return this.addAccountScoping('settings/inboxes/new');
},

View File

@@ -170,7 +170,7 @@ export default {
};
},
computed: {
contentToBeParsed() {
emailMessageContent() {
const {
html_content: { full: fullHTMLContent } = {},
text_content: { full: fullTextContent } = {},
@@ -182,13 +182,19 @@ export default {
return false;
}
if (this.contentToBeParsed.includes('<blockquote')) {
if (this.emailMessageContent.includes('<blockquote')) {
return true;
}
return false;
},
message() {
// If the message is an email, emailMessageContent would be present
// In that case, we would use letter package to render the email
if (this.emailMessageContent && this.isIncoming) {
return this.emailMessageContent;
}
const botMessageContent = generateBotMessageContent(
this.contentType,
this.contentAttributes,
@@ -200,21 +206,6 @@ export default {
},
}
);
const {
email: { content_type: contentType = '' } = {},
} = this.contentAttributes;
if (this.contentToBeParsed && this.isIncoming) {
const parsedContent = this.stripStyleCharacters(this.contentToBeParsed);
if (parsedContent) {
// This is a temporary fix for line-breaks in text/plain emails
// Now, It is not rendered properly in the email preview.
// FIXME: Remove this once we have a better solution for rendering text/plain emails
return contentType.includes('text/plain')
? parsedContent.replace(/\n/g, '<br />')
: parsedContent;
}
}
return (
this.formatMessage(
this.data.content,
@@ -331,6 +322,7 @@ export default {
'activity-wrap': !this.isBubble,
'is-pending': this.isPending,
'is-failed': this.isFailed,
'is-email': this.isEmailContentType,
};
},
bubbleClass() {
@@ -342,6 +334,7 @@ export default {
'is-text': this.hasText,
'is-from-bot': this.isSentByBot,
'is-failed': this.isFailed,
'is-email': this.isEmailContentType,
};
},
isPending() {
@@ -518,6 +511,10 @@ export default {
}
}
.wrap.is-email {
--bubble-max-width: 84% !important;
}
.sender--info {
align-items: center;
color: var(--b-700);

View File

@@ -6,7 +6,8 @@
'hide--quoted': !showQuotedContent,
}"
>
<div v-dompurify-html="message" class="text-content" />
<div v-if="!isEmail" v-dompurify-html="message" class="text-content" />
<letter v-else class="text-content" :html="message" />
<button
v-if="displayQuotedButton"
class="quoted-text--button"
@@ -25,7 +26,10 @@
</template>
<script>
import Letter from 'vue-letter';
export default {
components: { Letter },
props: {
message: {
type: String,
@@ -65,14 +69,16 @@ export default {
padding-left: var(--space-two);
}
table {
all: revert;
margin: 0;
border: 0;
td {
all: revert;
margin: 0;
border: 0;
}
tr {
all: revert;
border-bottom: 0 !important;
}
}