feat: Update design for campaign (#7668)
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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 }"
|
||||
|
||||
@@ -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 '---';
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user