feat: One off campaign UI (#2621)

This commit is contained in:
Muhsin Keloth
2021-07-15 13:31:43 +05:30
committed by GitHub
parent aa7db90cd2
commit cf785123a5
16 changed files with 473 additions and 107 deletions

View File

@@ -0,0 +1,29 @@
@import '~vue2-datepicker/scss/index';
.mx-datepicker-popup {
z-index: 99999;
}
.date-picker {
.mx-datepicker {
width: 100%;
}
.mx-datepicker-range {
width: 320px;
}
.mx-input {
border: 1px solid var(--color-border);
border-radius: var(--border-radius-normal);
box-shadow: none;
display: flex;
height: 4.6rem;
}
.mx-input:disabled,
.mx-input[readonly] {
background-color: var(--white);
cursor: pointer;
}
}

View File

@@ -12,6 +12,7 @@
@import 'foundation-settings'; @import 'foundation-settings';
@import 'helper-classes'; @import 'helper-classes';
@import 'formulate'; @import 'formulate';
@import 'date-picker';
@import 'foundation-sites/scss/foundation'; @import 'foundation-sites/scss/foundation';
@import '~bourbon/core/bourbon'; @import '~bourbon/core/bourbon';

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="woot-date-range-picker"> <div class="date-picker">
<date-picker <date-picker
:range="true" :range="true"
:confirm="true" :confirm="true"
@@ -15,7 +15,6 @@
<script> <script>
import DatePicker from 'vue2-datepicker'; import DatePicker from 'vue2-datepicker';
import 'vue2-datepicker/index.css';
export default { export default {
components: { DatePicker }, components: { DatePicker },
props: { props: {
@@ -33,32 +32,9 @@ export default {
}, },
}, },
methods: { methods: {
updateValue(val) {
this.$emit('change', val);
},
handleChange(value) { handleChange(value) {
this.updateValue(value); this.$emit('change', value);
}, },
}, },
}; };
</script> </script>
<style lang="scss">
.woot-date-range-picker {
margin-left: var(--space-smaller);
.mx-input {
display: flex;
border: 1px solid var(--color-border);
border-radius: var(--border-radius-normal);
box-shadow: none;
height: 4.6rem;
}
.mx-input:disabled,
.mx-input[readonly] {
background-color: var(--white);
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,47 @@
<template>
<div class="date-picker">
<date-picker
type="datetime"
:confirm="true"
:clearable="false"
:editable="false"
:confirm-text="confirmText"
:placeholder="placeholder"
:value="value"
:disabled-date="disableBeforeToday"
@change="handleChange"
/>
</div>
</template>
<script>
import addDays from 'date-fns/addDays';
import DatePicker from 'vue2-datepicker';
export default {
components: { DatePicker },
props: {
confirmText: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
value: {
type: Date,
default: () => [],
},
},
methods: {
handleChange(value) {
this.$emit('change', value);
},
disableBeforeToday(date) {
const yesterdayDate = addDays(new Date(), -1);
return date < yesterdayDate;
},
},
};
</script>

View File

@@ -1,5 +1,5 @@
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import WootDateRangePicker from '../DateRangePicker'; import WootDateRangePicker from '../DateRangePicker.vue';
export default { export default {
title: 'Components/Date Picker/Date Range Picker', title: 'Components/Date Picker/Date Range Picker',
@@ -34,5 +34,5 @@ const Template = (args, { argTypes }) => ({
export const DateRangePicker = Template.bind({}); export const DateRangePicker = Template.bind({});
DateRangePicker.args = { DateRangePicker.args = {
onChange: action('applied'), onChange: action('applied'),
value: [new Date(), new Date()], value: new Date(),
}; };

View File

@@ -0,0 +1,38 @@
import { action } from '@storybook/addon-actions';
import WootDateTimePicker from '../DateTimePicker.vue';
export default {
title: 'Components/Date Picker/Date Time Picker',
argTypes: {
confirmText: {
defaultValue: 'Apply',
control: {
type: 'text',
},
},
placeholder: {
defaultValue: 'Select date time',
control: {
type: 'text',
},
},
value: {
control: {
type: 'text',
},
},
},
};
const Template = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { WootDateTimePicker },
template:
'<woot-date-time-picker v-bind="$props" @change="onChange"></woot-date-time-picker>',
});
export const DateTimePicker = Template.bind({});
DateTimePicker.args = {
onChange: action('applied'),
value: new Date(),
};

View File

@@ -14,6 +14,17 @@
"PLACEHOLDER": "Please enter the title of campaign", "PLACEHOLDER": "Please enter the title of campaign",
"ERROR": "Title is required" "ERROR": "Title is required"
}, },
"SCHEDULED_AT": {
"LABEL": "Scheduled time",
"PLACEHOLDER": "Please select the time",
"CONFIRM": "Confirm",
"ERROR": "Scheduled time is required"
},
"AUDIENCE": {
"LABEL": "Audience",
"PLACEHOLDER": "Select the customer labels",
"ERROR": "Audience is required"
},
"MESSAGE": { "MESSAGE": {
"LABEL": "Message", "LABEL": "Message",
"PLACEHOLDER": "Please enter the message of campaign", "PLACEHOLDER": "Please enter the message of campaign",
@@ -72,6 +83,7 @@
"STATUS": "Status", "STATUS": "Status",
"SENDER": "Sender", "SENDER": "Sender",
"URL": "URL", "URL": "URL",
"SCHEDULED_AT": "Scheduled time",
"TIME_ON_PAGE": "Time(Seconds)", "TIME_ON_PAGE": "Time(Seconds)",
"CREATED_AT": "Created at" "CREATED_AT": "Created at"
}, },
@@ -82,7 +94,9 @@
}, },
"STATUS": { "STATUS": {
"ENABLED": "Enabled", "ENABLED": "Enabled",
"DISABLED": "Disabled" "DISABLED": "Disabled",
"COMPLETED": "Completed",
"ACTIVE": "Active"
}, },
"SENDER": { "SENDER": {
"BOT": "Bot" "BOT": "Bot"

View File

@@ -387,7 +387,21 @@ export default {
]; ];
} }
if (this.isATwilioChannel) { if (this.isATwilioSMSChannel) {
return [
...visibleToAllChannelTabs,
{
key: 'campaign',
name: this.$t('INBOX_MGMT.TABS.CAMPAIGN'),
},
{
key: 'configuration',
name: this.$t('INBOX_MGMT.TABS.CONFIGURATION'),
},
];
}
if (this.isATwilioWhatsappChannel) {
return [ return [
...visibleToAllChannelTabs, ...visibleToAllChannelTabs,
{ {
@@ -459,6 +473,7 @@ export default {
this.selectedAgents = []; this.selectedAgents = [];
this.$store.dispatch('agents/get'); this.$store.dispatch('agents/get');
this.$store.dispatch('teams/get'); this.$store.dispatch('teams/get');
this.$store.dispatch('labels/get');
this.$store.dispatch('inboxes/get').then(() => { this.$store.dispatch('inboxes/get').then(() => {
this.fetchAttachedAgents(); this.fetchAttachedAgents();
this.avatarUrl = this.inbox.avatar_url; this.avatarUrl = this.inbox.avatar_url;

View File

@@ -30,7 +30,46 @@
</span> </span>
</label> </label>
<label :class="{ error: $v.selectedSender.$error }"> <label v-if="isOnOffType">
{{ $t('CAMPAIGN.ADD.FORM.SCHEDULED_AT.LABEL') }}
<woot-date-time-picker
:value="scheduledAt"
:confirm-text="$t('CAMPAIGN.ADD.FORM.SCHEDULED_AT.CONFIRM')"
:placeholder="$t('CAMPAIGN.ADD.FORM.SCHEDULED_AT.PLACEHOLDER')"
@change="onChange"
/>
</label>
<label
v-if="isOnOffType"
:class="{ error: $v.selectedAudience.$error }"
>
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.LABEL') }}
<multiselect
v-model="selectedAudience"
:options="audienceList"
track-by="id"
label="title"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:hide-selected="true"
:placeholder="$t('CAMPAIGN.ADD.FORM.AUDIENCE.PLACEHOLDER')"
selected-label
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
@blur="$v.selectedAudience.$touch"
@select="$v.selectedAudience.$touch"
/>
<span v-if="$v.selectedAudience.$error" class="message">
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.ERROR') }}
</span>
</label>
<label
v-if="isOngoingType"
:class="{ error: $v.selectedSender.$error }"
>
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }} {{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
<select v-model="selectedSender"> <select v-model="selectedSender">
<option <option
@@ -47,6 +86,7 @@
</label> </label>
<woot-input <woot-input
v-if="isOngoingType"
v-model="endPoint" v-model="endPoint"
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')" :label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
type="text" type="text"
@@ -58,6 +98,7 @@
@blur="$v.endPoint.$touch" @blur="$v.endPoint.$touch"
/> />
<woot-input <woot-input
v-if="isOngoingType"
v-model="timeOnPage" v-model="timeOnPage"
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')" :label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
type="text" type="text"
@@ -70,7 +111,7 @@
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')" :placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
@blur="$v.timeOnPage.$touch" @blur="$v.timeOnPage.$touch"
/> />
<label> <label v-if="isOngoingType">
<input <input
v-model="enabled" v-model="enabled"
type="checkbox" type="checkbox"
@@ -100,14 +141,23 @@
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { required, url, minLength } from 'vuelidate/lib/validators'; import { required, url, minLength } from 'vuelidate/lib/validators';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import campaignMixin from 'shared/mixins/campaignMixin';
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
export default { export default {
mixins: [alertMixin], components: { WootDateTimePicker },
mixins: [alertMixin, campaignMixin],
props: { props: {
senderList: { senderList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
audienceList: {
type: Array,
default: () => [],
},
}, },
data() { data() {
return { return {
title: '', title: '',
@@ -117,8 +167,11 @@ export default {
timeOnPage: 10, timeOnPage: 10,
show: true, show: true,
enabled: true, enabled: true,
scheduledAt: null,
selectedAudience: [],
}; };
}, },
validations: { validations: {
title: { title: {
required, required,
@@ -137,18 +190,37 @@ export default {
timeOnPage: { timeOnPage: {
required, required,
}, },
selectedAudience: {
isEmpty() {
return !!this.selectedAudience.length;
},
},
}, },
computed: { computed: {
...mapGetters({ ...mapGetters({
uiFlags: 'campaigns/getUIFlags', uiFlags: 'campaigns/getUIFlags',
}), }),
currentInboxId() {
return this.$route.params.inboxId;
},
inbox() {
return this.$store.getters['inboxes/getInbox'](this.currentInboxId);
},
buttonDisabled() { buttonDisabled() {
if (this.isOngoingType) {
return (
this.$v.message.$invalid ||
this.$v.title.$invalid ||
this.$v.selectedSender.$invalid ||
this.$v.endPoint.$invalid ||
this.$v.timeOnPage.$invalid ||
this.uiFlags.isCreating
);
}
return ( return (
this.$v.message.$invalid || this.$v.message.$invalid ||
this.$v.title.$invalid || this.$v.title.$invalid ||
this.$v.selectedSender.$invalid || this.$v.selectedAudience.$invalid ||
this.$v.endPoint.$invalid ||
this.$v.timeOnPage.$invalid ||
this.uiFlags.isCreating this.uiFlags.isCreating
); );
}, },
@@ -166,9 +238,13 @@ export default {
onClose() { onClose() {
this.$emit('on-close'); this.$emit('on-close');
}, },
async addCampaign() { onChange(value) {
try { this.scheduledAt = value;
await this.$store.dispatch('campaigns/create', { },
getCampaignDetails() {
let campaignDetails = null;
if (this.isOngoingType) {
campaignDetails = {
title: this.title, title: this.title,
message: this.message, message: this.message,
inbox_id: this.$route.params.inboxId, inbox_id: this.$route.params.inboxId,
@@ -178,11 +254,34 @@ export default {
url: this.endPoint, url: this.endPoint,
time_on_page: this.timeOnPage, time_on_page: this.timeOnPage,
}, },
};
} else {
const audience = this.selectedAudience.map(item => {
return {
id: item.id,
type: 'Label',
};
}); });
campaignDetails = {
title: this.title,
message: this.message,
inbox_id: this.$route.params.inboxId,
scheduled_at: this.scheduledAt,
audience,
};
}
return campaignDetails;
},
async addCampaign() {
try {
const campaignDetails = this.getCampaignDetails();
await this.$store.dispatch('campaigns/create', campaignDetails);
this.showAlert(this.$t('CAMPAIGN.ADD.API.SUCCESS_MESSAGE')); this.showAlert(this.$t('CAMPAIGN.ADD.API.SUCCESS_MESSAGE'));
this.onClose(); this.onClose();
} catch (error) { } catch (error) {
this.showAlert(this.$t('CAMPAIGN.ADD.API.ERROR_MESSAGE')); const errorMessage =
error?.response?.message || this.$t('CAMPAIGN.ADD.API.ERROR_MESSAGE');
this.showAlert(errorMessage);
} }
}, },
}, },

View File

@@ -9,12 +9,18 @@
:campaigns="records" :campaigns="records"
:show-empty-result="showEmptyResult" :show-empty-result="showEmptyResult"
:is-loading="uiFlags.isFetching" :is-loading="uiFlags.isFetching"
:campaign-type="type"
@on-edit-click="openEditPopup" @on-edit-click="openEditPopup"
@on-delete-click="openDeletePopup" @on-delete-click="openDeletePopup"
/> />
<woot-modal :show.sync="showAddPopup" :on-close="hideAddPopup"> <woot-modal :show.sync="showAddPopup" :on-close="hideAddPopup">
<add-campaign :sender-list="selectedAgents" @on-close="hideAddPopup" /> <add-campaign
:sender-list="selectedAgents"
:audience-list="labelList"
:campaign-type="type"
@on-close="hideAddPopup"
/>
</woot-modal> </woot-modal>
<woot-modal :show.sync="showEditPopup" :on-close="hideEditPopup"> <woot-modal :show.sync="showEditPopup" :on-close="hideEditPopup">
<edit-campaign <edit-campaign
@@ -52,6 +58,10 @@ export default {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
type: {
type: String,
default: '',
},
}, },
data() { data() {
return { return {
@@ -66,6 +76,7 @@ export default {
...mapGetters({ ...mapGetters({
records: 'campaigns/getCampaigns', records: 'campaigns/getCampaigns',
uiFlags: 'campaigns/getUIFlags', uiFlags: 'campaigns/getUIFlags',
labelList: 'labels/getLabels',
}), }),
showEmptyResult() { showEmptyResult() {
const hasEmptyResults = const hasEmptyResults =

View File

@@ -23,6 +23,8 @@ import Label from 'dashboard/components/ui/Label';
import EmptyState from 'dashboard/components/widgets/EmptyState.vue'; import EmptyState from 'dashboard/components/widgets/EmptyState.vue';
import WootButton from 'dashboard/components/ui/WootButton.vue'; import WootButton from 'dashboard/components/ui/WootButton.vue';
import UserAvatarWithName from 'dashboard/components/widgets/UserAvatarWithName'; import UserAvatarWithName from 'dashboard/components/widgets/UserAvatarWithName';
import campaignMixin from 'shared/mixins/campaignMixin';
import timeMixin from 'dashboard/mixins/time';
export default { export default {
components: { components: {
@@ -30,7 +32,7 @@ export default {
Spinner, Spinner,
VeTable, VeTable,
}, },
mixins: [clickaway], mixins: [clickaway, timeMixin, campaignMixin],
props: { props: {
campaigns: { campaigns: {
type: Array, type: Array,
@@ -46,9 +48,30 @@ export default {
}, },
}, },
data() { computed: {
return { currentInboxId() {
columns: [ return this.$route.params.inboxId;
},
inbox() {
return this.$store.getters['inboxes/getInbox'](this.currentInboxId);
},
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', field: 'title',
key: 'title', key: 'title',
@@ -76,54 +99,110 @@ export default {
); );
}, },
}, },
];
if (this.isOngoingType) {
return [
...visibleToAllTable,
{
field: 'enabled',
key: 'enabled',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.STATUS'),
align: '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: '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: 'left',
renderBodyCell: ({ row }) => (
<div class="text-truncate">
<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: 'left',
},
{
field: 'buttons',
key: 'buttons',
title: '',
align: 'left',
renderBodyCell: row => (
<div class="button-wrapper">
<WootButton
variant="clear"
icon="ion-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="ion-close-circled"
color-scheme="secondary"
onClick={() => this.$emit('on-delete-click', row)}
>
{this.$t('CAMPAIGN.LIST.BUTTONS.DELETE')}
</WootButton>
</div>
),
},
];
}
return [
...visibleToAllTable,
{ {
field: 'enabled', field: 'campaign_status',
key: 'enabled', key: 'campaign_status',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.STATUS'), title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.STATUS'),
align: 'left', align: 'left',
renderBodyCell: ({ row }) => { renderBodyCell: ({ row }) => {
const labelText = row.enabled const labelText =
? this.$t('CAMPAIGN.LIST.STATUS.ENABLED') row.campaign_status === 'completed'
: this.$t('CAMPAIGN.LIST.STATUS.DISABLED'); ? this.$t('CAMPAIGN.LIST.STATUS.COMPLETED')
const colorScheme = row.enabled ? 'success' : 'secondary'; : this.$t('CAMPAIGN.LIST.STATUS.ACTIVE');
const colorScheme =
row.campaign_status === 'completed' ? 'secondary' : 'success';
return <Label title={labelText} colorScheme={colorScheme} />; return <Label title={labelText} colorScheme={colorScheme} />;
}, },
}, },
{ {
field: 'sender', field: 'scheduledAt',
key: 'sender', key: 'scheduledAt',
title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.SENDER'), title: this.$t('CAMPAIGN.LIST.TABLE_HEADER.SCHEDULED_AT'),
align: '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: 'left',
renderBodyCell: ({ row }) => (
<div class="text-truncate">
<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: 'left', align: 'left',
}, },
{ {
field: 'buttons', field: 'buttons',
key: 'buttons', key: 'buttons',
@@ -131,15 +210,6 @@ export default {
align: 'left', align: 'left',
renderBodyCell: row => ( renderBodyCell: row => (
<div class="button-wrapper"> <div class="button-wrapper">
<WootButton
variant="clear"
icon="ion-edit"
color-scheme="secondary"
classNames="grey-btn"
onClick={() => this.$emit('on-edit-click', row)}
>
{this.$t('CAMPAIGN.LIST.BUTTONS.EDIT')}
</WootButton>
<WootButton <WootButton
variant="link" variant="link"
icon="ion-close-circled" icon="ion-close-circled"
@@ -151,21 +221,7 @@ export default {
</div> </div>
), ),
}, },
], ];
};
},
computed: {
tableData() {
if (this.isLoading) {
return [];
}
return this.campaigns.map(item => {
return {
...item,
url: item.trigger_rules.url,
timeOnPage: item.trigger_rules.time_on_page,
};
});
}, },
}, },
}; };

View File

@@ -8,6 +8,7 @@
> >
{{ $t('REPORT.DOWNLOAD_AGENT_REPORTS') }} {{ $t('REPORT.DOWNLOAD_AGENT_REPORTS') }}
</woot-button> </woot-button>
<report-date-range-selector @date-range-change="onDateRangeChange" /> <report-date-range-selector @date-range-change="onDateRangeChange" />
<div class="row"> <div class="row">
<woot-report-stats-card <woot-report-stats-card

View File

@@ -17,6 +17,7 @@
</div> </div>
<woot-date-range-picker <woot-date-range-picker
v-if="isDateRangeSelected" v-if="isDateRangeSelected"
show-range
:value="customDateRange" :value="customDateRange"
:confirm-text="$t('REPORT.CUSTOM_DATE_RANGE.CONFIRM')" :confirm-text="$t('REPORT.CUSTOM_DATE_RANGE.CONFIRM')"
:placeholder="$t('REPORT.CUSTOM_DATE_RANGE.PLACEHOLDER')" :placeholder="$t('REPORT.CUSTOM_DATE_RANGE.PLACEHOLDER')"
@@ -89,3 +90,9 @@ export default {
}, },
}; };
</script> </script>
<style lang="scss" scoped>
.date-picker {
margin-left: var(--space-smaller);
}
</style>

View File

@@ -0,0 +1,4 @@
export const CAMPAIGN_TYPES = {
ONGOING: 'ongoing',
ONE_OFF: 'one_off',
};

View File

@@ -0,0 +1,19 @@
import { CAMPAIGN_TYPES } from '../constants/campaign';
import inboxMixin from './inboxMixin';
export default {
mixins: [inboxMixin],
computed: {
campaignType() {
if (this.isAWebWidgetInbox) {
return CAMPAIGN_TYPES.ONGOING;
}
return CAMPAIGN_TYPES.ONE_OFF;
},
isOngoingType() {
return this.campaignType === CAMPAIGN_TYPES.ONGOING;
},
isOnOffType() {
return this.campaignType === CAMPAIGN_TYPES.ONE_OFF;
},
},
};

View File

@@ -0,0 +1,49 @@
import { shallowMount } from '@vue/test-utils';
import campaignMixin from '../campaignMixin';
import inboxMixin from '../inboxMixin';
describe('campaignMixin', () => {
it('returns the correct campaign type', () => {
const Component = {
render() {},
mixins: [campaignMixin, inboxMixin],
data() {
return {
inbox: {
channel_type: 'Channel::TwilioSms',
phone_number: '+91944444444',
},
};
},
};
const wrapper = shallowMount(Component);
expect(wrapper.vm.campaignType).toBe('one_off');
});
it('isOnOffType returns true if campaign type is ongoing', () => {
const Component = {
render() {},
mixins: [campaignMixin, inboxMixin],
data() {
return { inbox: { channel_type: 'Channel::WebWidget' } };
},
};
const wrapper = shallowMount(Component);
expect(wrapper.vm.isOngoingType).toBe(true);
});
it('isOngoingType returns true if campaign type is one_off', () => {
const Component = {
render() {},
mixins: [campaignMixin, inboxMixin],
data() {
return {
inbox: {
channel_type: 'Channel::TwilioSms',
phone_number: '+91944444444',
},
};
},
};
const wrapper = shallowMount(Component);
expect(wrapper.vm.isOnOffType).toBe(true);
});
});