feat: Update design for campaign (#7668)

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
Pranav Raj S
2023-08-04 11:39:59 -07:00
committed by GitHub
parent 2a1662c781
commit fde2b180fe
6 changed files with 150 additions and 262 deletions

View File

@@ -1,5 +1,5 @@
<template>
<div class="row--user-block">
<div class="flex items-center text-left">
<thumbnail
:src="user.thumbnail"
:size="size"
@@ -7,7 +7,8 @@
:status="user.availability_status"
/>
<h6
class="text-block-title user-name overflow-hidden whitespace-nowrap text-ellipsis text-capitalize"
class="my-0 mx-2 dark:text-slate-100 overflow-hidden whitespace-nowrap text-ellipsis text-capitalize"
:class="textClass"
>
{{ user.name }}
</h6>
@@ -29,16 +30,10 @@ export default {
type: String,
default: '20px',
},
textClass: {
type: String,
default: 'text-xs text-slate-600',
},
},
};
</script>
<style scoped lang="scss">
.row--user-block {
@apply items-center flex text-left;
.user-name {
@apply my-0 mx-2 text-slate-700 dark:text-slate-100;
}
}
</style>

View File

@@ -1,12 +1,12 @@
<template>
<div class="flex-1 overflow-auto p-4">
<div class="flex-1 overflow-auto">
<campaigns-table
:campaigns="campaigns"
:show-empty-result="showEmptyResult"
:is-loading="uiFlags.isFetching"
:campaign-type="type"
@on-edit-click="openEditPopup"
@on-delete-click="openDeletePopup"
@edit="openEditPopup"
@delete="openDeletePopup"
/>
<woot-modal :show.sync="showEditPopup" :on-close="hideEditPopup">
<edit-campaign
@@ -65,26 +65,23 @@ export default {
},
},
methods: {
openEditPopup(response) {
const { row: campaign } = response;
openEditPopup(campaign) {
this.selectedCampaign = campaign;
this.showEditPopup = true;
},
hideEditPopup() {
this.showEditPopup = false;
},
openDeletePopup(response) {
openDeletePopup(campaign) {
this.showDeleteConfirmationPopup = true;
this.selectedCampaign = response;
this.selectedCampaign = campaign;
},
closeDeletePopup() {
this.showDeleteConfirmationPopup = false;
},
confirmDeletion() {
this.closeDeletePopup();
const {
row: { id },
} = this.selectedCampaign;
const { id } = this.selectedCampaign;
this.deleteCampaign(id);
},
async deleteCampaign(id) {

View File

@@ -0,0 +1,109 @@
<template>
<div
class="bg-white dark:bg-slate-800 mb-2 border border-slate-50 dark:border-slate-900 rounded-md px-5 py-4"
>
<div class="flex flex-row items-start justify-between">
<div class="flex flex-col">
<div class="text-base font-medium -mt-1 mb-1">
{{ campaign.title }}
</div>
<div
v-dompurify-html="formatMessage(campaign.message)"
class="text-sm line-clamp-1 [&>p]:mb-0"
/>
</div>
<div class="flex flex-row space-x-4">
<woot-button
v-if="isOngoingType"
variant="link"
icon="edit"
color-scheme="secondary"
size="small"
@click="$emit('edit', campaign)"
>
{{ $t('CAMPAIGN.LIST.BUTTONS.EDIT') }}
</woot-button>
<woot-button
variant="link"
icon="dismiss-circle"
size="small"
color-scheme="secondary"
@click="$emit('delete', campaign)"
>
{{ $t('CAMPAIGN.LIST.BUTTONS.DELETE') }}
</woot-button>
</div>
</div>
<div class="flex flex-row mt-5 items-center space-x-3">
<woot-label
small
:title="campaignStatus"
:color-scheme="colorScheme"
class="text-xs mr-3"
/>
<inbox-name :inbox="campaign.inbox" class="ltr:ml-0 rtl:mr-0 mb-1" />
<user-avatar-with-name
v-if="campaign.sender"
:user="campaign.sender"
class="mb-1"
/>
<div
v-if="campaign.trigger_rules.url"
class="text-xs text-woot-600 mb-1 text-truncate w-1/4"
>
{{ campaign.trigger_rules.url }}
</div>
<div v-if="campaign.scheduled_at" class="text-xs text-slate-700 dark:text-slate-500 mb-1">
{{ messageStamp(new Date(campaign.scheduled_at), 'LLL d, h:mm a') }}
</div>
</div>
</div>
</template>
<script>
import UserAvatarWithName from 'dashboard/components/widgets/UserAvatarWithName';
import InboxName from 'dashboard/components/widgets/InboxName';
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
import timeMixin from 'dashboard/mixins/time';
export default {
components: {
UserAvatarWithName,
InboxName,
},
mixins: [messageFormatterMixin, timeMixin],
props: {
campaign: {
type: Object,
required: true,
},
isOngoingType: {
type: Boolean,
default: true,
},
},
computed: {
campaignStatus() {
if (this.isOngoingType) {
return this.campaign.enabled
? this.$t('CAMPAIGN.LIST.STATUS.ENABLED')
: this.$t('CAMPAIGN.LIST.STATUS.DISABLED');
}
return this.campaign.campaign_status === 'completed'
? this.$t('CAMPAIGN.LIST.STATUS.COMPLETED')
: this.$t('CAMPAIGN.LIST.STATUS.ACTIVE');
},
colorScheme() {
if (this.isOngoingType) {
return this.campaign.enabled ? 'success' : 'secondary';
}
return this.campaign.campaign_status === 'completed'
? 'secondary'
: 'success';
},
},
};
</script>

View File

@@ -1,49 +1,40 @@
<template>
<section class="campaigns-table-wrap">
<empty-state v-if="showEmptyResult" :title="emptyMessage" />
<ve-table
v-else
:columns="columns"
scroll-width="190rem"
:table-data="tableData"
:border-around="true"
style="max-width: calc(100vw - 18rem)"
/>
<div class="flex items-center flex-col">
<div v-if="isLoading" class="items-center flex text-base justify-center">
<spinner />
<spinner color-scheme="primary" />
<span>{{ $t('CAMPAIGN.LIST.LOADING_MESSAGE') }}</span>
</div>
</section>
<div v-else class="w-full">
<empty-state v-if="showEmptyResult" :title="emptyMessage" />
<div v-else class="w-full">
<campaign-card
v-for="campaign in campaigns"
:key="campaign.id"
:campaign="campaign"
:is-ongoing-type="isOngoingType"
@edit="campaign => $emit('edit', campaign)"
@delete="campaign => $emit('delete', campaign)"
/>
</div>
</div>
</div>
</template>
<script>
import { mixin as clickaway } from 'vue-clickaway';
import { VeTable } from 'vue-easytable';
import Spinner from 'shared/components/Spinner.vue';
import Label from 'dashboard/components/ui/Label';
import EmptyState from 'dashboard/components/widgets/EmptyState.vue';
import WootButton from 'dashboard/components/ui/WootButton.vue';
import messageFormatterMixin from 'shared/mixins/messageFormatterMixin';
import UserAvatarWithName from 'dashboard/components/widgets/UserAvatarWithName';
import campaignMixin from 'shared/mixins/campaignMixin';
import timeMixin from 'dashboard/mixins/time';
import rtlMixin from 'shared/mixins/rtlMixin';
import InboxName from 'dashboard/components/widgets/InboxName';
import CampaignCard from './CampaignCard.vue';
export default {
components: {
EmptyState,
Spinner,
VeTable,
CampaignCard,
},
mixins: [
clickaway,
timeMixin,
campaignMixin,
messageFormatterMixin,
rtlMixin,
],
mixins: [clickaway, campaignMixin],
props: {
campaigns: {
@@ -84,216 +75,6 @@ export default {
? this.$t('CAMPAIGN.ONE_OFF.404')
: this.$t('CAMPAIGN.ONE_OFF.INBOXES_NOT_FOUND');
},
tableData() {
if (this.isLoading) {
return [];
}
return this.campaigns.map(item => {
return {
...item,
url: item.trigger_rules.url,
timeOnPage: item.trigger_rules.time_on_page,
scheduledAt: item.scheduled_at
? this.messageStamp(new Date(item.scheduled_at), 'LLL d, h:mm a')
: '---',
};
});
},
columns() {
const visibleToAllTable = [
{
field: 'title',
key: 'title',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.TITLE'),
fixed: 'left',
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: ({ row }) => (
<div class="row--title-block">
<h6 class="text-sm m-0 capitalize text-slate-900 dark:text-slate-100 overflow-hidden whitespace-nowrap text-ellipsis">
{row.title}
</h6>
</div>
),
},
{
field: 'message',
key: 'message',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.MESSAGE'),
align: this.isRTLView ? 'right' : 'left',
width: 350,
renderBodyCell: ({ row }) => {
if (row.message) {
return (
<div class="overflow-hidden whitespace-nowrap text-ellipsis">
<span
domPropsInnerHTML={this.formatMessage(row.message)}
></span>
</div>
);
}
return '';
},
},
{
field: 'inbox',
key: 'inbox',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.INBOX'),
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: ({ row }) => {
return <InboxName inbox={row.inbox} />;
},
},
];
if (this.isOngoingType) {
return [
...visibleToAllTable,
{
field: 'enabled',
key: 'enabled',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.STATUS'),
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: ({ row }) => {
const labelText = row.enabled
? this.$t('CAMPAIGN.LIST.STATUS.ENABLED')
: this.$t('CAMPAIGN.LIST.STATUS.DISABLED');
const colorScheme = row.enabled ? 'success' : 'secondary';
return <Label title={labelText} colorScheme={colorScheme} />;
},
},
{
field: 'sender',
key: 'sender',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.SENDER'),
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: ({ row }) => {
if (row.sender) return <UserAvatarWithName user={row.sender} />;
return this.$t('CAMPAIGN.LIST.SENDER.BOT');
},
},
{
field: 'url',
key: 'url',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.URL'),
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: ({ row }) => (
<div class="overflow-hidden whitespace-nowrap text-ellipsis">
<a
target="_blank"
rel="noopener noreferrer nofollow"
href={row.url}
title={row.url}
>
{row.url}
</a>
</div>
),
},
{
field: 'timeOnPage',
key: 'timeOnPage',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.TIME_ON_PAGE'),
align: this.isRTLView ? 'right' : 'left',
},
{
field: 'buttons',
key: 'buttons',
title: '',
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: row => (
<div class="justify-evenly flex flex-row min-w-[12.5rem]">
<WootButton
variant="clear"
icon="edit"
color-scheme="secondary"
classNames="grey-btn"
onClick={() => this.$emit('on-edit-click', row)}
>
{this.$t('CAMPAIGN.LIST.BUTTONS.EDIT')}
</WootButton>
<WootButton
variant="link"
icon="dismiss-circle"
color-scheme="secondary"
onClick={() => this.$emit('on-delete-click', row)}
>
{this.$t('CAMPAIGN.LIST.BUTTONS.DELETE')}
</WootButton>
</div>
),
},
];
}
return [
...visibleToAllTable,
{
field: 'campaign_status',
key: 'campaign_status',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.STATUS'),
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: ({ row }) => {
const labelText =
row.campaign_status === 'completed'
? this.$t('CAMPAIGN.LIST.STATUS.COMPLETED')
: this.$t('CAMPAIGN.LIST.STATUS.ACTIVE');
const colorScheme =
row.campaign_status === 'completed' ? 'secondary' : 'success';
return <Label title={labelText} colorScheme={colorScheme} />;
},
},
{
field: 'scheduledAt',
key: 'scheduledAt',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.SCHEDULED_AT'),
align: this.isRTLView ? 'right' : 'left',
},
{
field: 'buttons',
key: 'buttons',
title: '',
align: this.isRTLView ? 'right' : 'left',
renderBodyCell: row => (
<div class="justify-evenly flex flex-row min-w-[12.5rem]">
<WootButton
variant="link"
icon="dismiss-circle"
color-scheme="secondary"
onClick={() => this.$emit('on-delete-click', row)}
>
{this.$t('CAMPAIGN.LIST.BUTTONS.DELETE')}
</WootButton>
</div>
),
},
];
},
},
};
</script>
<style lang="scss" scoped>
.campaigns-table-wrap::v-deep {
.ve-table {
@apply pb-12;
thead.ve-table-header .ve-table-header-tr .ve-table-header-th {
@apply text-xs py-2 px-5;
}
tbody.ve-table-body .ve-table-body-tr .ve-table-body-td {
@apply py-3 px-5;
.inbox--name {
@apply m-0;
}
}
}
.row--title-block {
@apply items-center flex text-left;
}
.label {
@apply py-1 px-2;
}
}
</style>

View File

@@ -15,7 +15,7 @@
<label class="editor-wrap">
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
<woot-message-editor
v-model.trim="message"
v-model="message"
class="message-editor"
:is-format-mode="true"
:class="{ editor_warning: $v.message.$error }"

View File

@@ -57,7 +57,13 @@ export default {
width: 200,
renderBodyCell: ({ row }) => {
if (row.contact) {
return <UserAvatarWithName size="24px" user={row.contact} />;
return (
<UserAvatarWithName
textClass="text-sm !pl-2 text-slate-800"
size="24px"
user={row.contact}
/>
);
}
return '---';
},