mirror of https://github.com/chatwoot/chatwoot.git
feat: Dedicated tab for campaigns (#2741)
parent
8daf1fe033
commit
4d668d8db3
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="inbox">
|
||||
<i :class="icon" />
|
||||
<span>{{ inbox.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
|
||||
export default {
|
||||
props: {
|
||||
inbox: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
icon() {
|
||||
if (this.inbox.channel_type === INBOX_TYPES.WEB) {
|
||||
return 'icon ion-earth';
|
||||
}
|
||||
return 'icon ion-android-textsms';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.inbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
margin-right: var(--space-micro);
|
||||
min-width: var(--space-normal);
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="column content-box">
|
||||
<woot-button
|
||||
color-scheme="success"
|
||||
class-names="button--fixed-right-top"
|
||||
icon="ion-android-add-circle"
|
||||
@click="openAddPopup"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</woot-button>
|
||||
<campaign />
|
||||
<woot-modal :show.sync="showAddPopup" :on-close="hideAddPopup">
|
||||
<add-campaign @on-close="hideAddPopup" />
|
||||
</woot-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
||||
import Campaign from './Campaign.vue';
|
||||
import AddCampaign from './AddCampaign';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Campaign,
|
||||
AddCampaign,
|
||||
},
|
||||
mixins: [campaignMixin],
|
||||
data() {
|
||||
return { showAddPopup: false };
|
||||
},
|
||||
computed: {
|
||||
buttonText() {
|
||||
if (this.isOngoingType) {
|
||||
return this.$t('CAMPAIGN.HEADER_BTN_TXT.ONGOING');
|
||||
}
|
||||
return this.$t('CAMPAIGN.HEADER_BTN_TXT.ONE_OFF');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('campaigns/get');
|
||||
},
|
||||
methods: {
|
||||
openAddPopup() {
|
||||
this.showAddPopup = true;
|
||||
},
|
||||
hideAddPopup() {
|
||||
this.showAddPopup = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -0,0 +1,44 @@
|
||||
import Index from './Index';
|
||||
import SettingsContent from '../Wrapper';
|
||||
import { frontendURL } from '../../../../helper/URLHelper';
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/campaigns'),
|
||||
component: SettingsContent,
|
||||
props: {
|
||||
headerTitle: 'CAMPAIGN.ONGOING.HEADER',
|
||||
icon: 'ion-arrow-swap',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirect: 'ongoing',
|
||||
},
|
||||
{
|
||||
path: 'ongoing',
|
||||
name: 'settings_account_campaigns',
|
||||
roles: ['administrator'],
|
||||
component: { ...Index },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/campaigns'),
|
||||
component: SettingsContent,
|
||||
props: {
|
||||
headerTitle: 'CAMPAIGN.ONE_OFF.HEADER',
|
||||
icon: 'ion-radio-waves',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'one_off',
|
||||
name: 'one_off',
|
||||
roles: ['administrator'],
|
||||
component: { ...Index },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
@ -1,49 +1,38 @@
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import campaignMixin from '../campaignMixin';
|
||||
import inboxMixin from '../inboxMixin';
|
||||
|
||||
describe('campaignMixin', () => {
|
||||
beforeEach(() => {
|
||||
global.window = Object.create(window);
|
||||
});
|
||||
it('returns the correct campaign type', () => {
|
||||
const url = 'http://localhost:3000/app/accounts/1/campaigns/one_off';
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
href: url,
|
||||
},
|
||||
});
|
||||
window.location.href = url;
|
||||
const Component = {
|
||||
render() {},
|
||||
mixins: [campaignMixin, inboxMixin],
|
||||
data() {
|
||||
return {
|
||||
inbox: {
|
||||
channel_type: 'Channel::TwilioSms',
|
||||
phone_number: '+91944444444',
|
||||
},
|
||||
};
|
||||
},
|
||||
mixins: [campaignMixin],
|
||||
};
|
||||
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' } };
|
||||
it('isOnOffType returns true if campaign type is one_off', () => {
|
||||
const url = 'http://localhost:3000/app/accounts/1/campaigns/one_off';
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
href: url,
|
||||
},
|
||||
};
|
||||
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',
|
||||
},
|
||||
};
|
||||
},
|
||||
mixins: [campaignMixin],
|
||||
};
|
||||
const wrapper = shallowMount(Component);
|
||||
expect(wrapper.vm.isOnOffType).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
Reference in new issue