Restructure omni services and add Chatwoot research snapshot
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { frontendURL } from 'dashboard/helper/URLHelper.js';
|
||||
|
||||
import CampaignsPageRouteView from './pages/CampaignsPageRouteView.vue';
|
||||
import LiveChatCampaignsPage from './pages/LiveChatCampaignsPage.vue';
|
||||
import SMSCampaignsPage from './pages/SMSCampaignsPage.vue';
|
||||
import WhatsAppCampaignsPage from './pages/WhatsAppCampaignsPage.vue';
|
||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||
|
||||
const meta = {
|
||||
featureFlag: FEATURE_FLAGS.CAMPAIGNS,
|
||||
permissions: ['administrator'],
|
||||
};
|
||||
|
||||
const campaignsRoutes = {
|
||||
routes: [
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/campaigns'),
|
||||
component: CampaignsPageRouteView,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirect: to => {
|
||||
return { name: 'campaigns_ongoing_index', params: to.params };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'ongoing',
|
||||
name: 'campaigns_ongoing_index',
|
||||
meta,
|
||||
redirect: to => {
|
||||
return { name: 'campaigns_livechat_index', params: to.params };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'one_off',
|
||||
name: 'campaigns_one_off_index',
|
||||
meta,
|
||||
redirect: to => {
|
||||
return { name: 'campaigns_sms_index', params: to.params };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'live_chat',
|
||||
name: 'campaigns_livechat_index',
|
||||
meta,
|
||||
component: LiveChatCampaignsPage,
|
||||
},
|
||||
{
|
||||
path: 'sms',
|
||||
name: 'campaigns_sms_index',
|
||||
meta,
|
||||
component: SMSCampaignsPage,
|
||||
},
|
||||
{
|
||||
path: 'whatsapp',
|
||||
name: 'campaigns_whatsapp_index',
|
||||
meta: {
|
||||
...meta,
|
||||
featureFlag: FEATURE_FLAGS.WHATSAPP_CAMPAIGNS,
|
||||
},
|
||||
component: WhatsAppCampaignsPage,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default campaignsRoutes;
|
||||
@@ -0,0 +1,28 @@
|
||||
<script setup>
|
||||
import { onMounted } from 'vue';
|
||||
import { useStore } from 'dashboard/composables/store';
|
||||
|
||||
defineProps({
|
||||
keepAlive: { type: Boolean, default: true },
|
||||
});
|
||||
|
||||
const store = useStore();
|
||||
|
||||
onMounted(() => {
|
||||
store.dispatch('campaigns/get');
|
||||
store.dispatch('labels/get');
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col justify-between flex-1 h-full m-0 overflow-auto bg-n-surface-1"
|
||||
>
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive v-if="keepAlive">
|
||||
<component :is="Component" />
|
||||
</keep-alive>
|
||||
<component :is="Component" v-else />
|
||||
</router-view>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,87 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
import { useStoreGetters, useMapGetter } from 'dashboard/composables/store';
|
||||
|
||||
import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
|
||||
import CampaignLayout from 'dashboard/components-next/Campaigns/CampaignLayout.vue';
|
||||
import CampaignList from 'dashboard/components-next/Campaigns/Pages/CampaignPage/CampaignList.vue';
|
||||
import LiveChatCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/LiveChatCampaign/LiveChatCampaignDialog.vue';
|
||||
import EditLiveChatCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/LiveChatCampaign/EditLiveChatCampaignDialog.vue';
|
||||
import ConfirmDeleteCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/ConfirmDeleteCampaignDialog.vue';
|
||||
import LiveChatCampaignEmptyState from 'dashboard/components-next/Campaigns/EmptyState/LiveChatCampaignEmptyState.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const getters = useStoreGetters();
|
||||
|
||||
const editLiveChatCampaignDialogRef = ref(null);
|
||||
const confirmDeleteCampaignDialogRef = ref(null);
|
||||
const selectedCampaign = ref(null);
|
||||
|
||||
const uiFlags = useMapGetter('campaigns/getUIFlags');
|
||||
const isFetchingCampaigns = computed(() => uiFlags.value.isFetching);
|
||||
|
||||
const [showLiveChatCampaignDialog, toggleLiveChatCampaignDialog] = useToggle();
|
||||
|
||||
const liveChatCampaigns = computed(
|
||||
() => getters['campaigns/getLiveChatCampaigns'].value
|
||||
);
|
||||
|
||||
const hasNoLiveChatCampaigns = computed(
|
||||
() => liveChatCampaigns.value?.length === 0 && !isFetchingCampaigns.value
|
||||
);
|
||||
|
||||
const handleEdit = campaign => {
|
||||
selectedCampaign.value = campaign;
|
||||
editLiveChatCampaignDialogRef.value.dialogRef.open();
|
||||
};
|
||||
const handleDelete = campaign => {
|
||||
selectedCampaign.value = campaign;
|
||||
confirmDeleteCampaignDialogRef.value.dialogRef.open();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CampaignLayout
|
||||
:header-title="t('CAMPAIGN.LIVE_CHAT.HEADER_TITLE')"
|
||||
:button-label="t('CAMPAIGN.LIVE_CHAT.NEW_CAMPAIGN')"
|
||||
@click="toggleLiveChatCampaignDialog()"
|
||||
@close="toggleLiveChatCampaignDialog(false)"
|
||||
>
|
||||
<template #action>
|
||||
<LiveChatCampaignDialog
|
||||
v-if="showLiveChatCampaignDialog"
|
||||
@close="toggleLiveChatCampaignDialog(false)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-if="isFetchingCampaigns"
|
||||
class="flex justify-center items-center py-10 text-n-slate-11"
|
||||
>
|
||||
<Spinner />
|
||||
</div>
|
||||
<CampaignList
|
||||
v-else-if="!hasNoLiveChatCampaigns"
|
||||
:campaigns="liveChatCampaigns"
|
||||
is-live-chat-type
|
||||
@edit="handleEdit"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
<LiveChatCampaignEmptyState
|
||||
v-else
|
||||
:title="t('CAMPAIGN.LIVE_CHAT.EMPTY_STATE.TITLE')"
|
||||
:subtitle="t('CAMPAIGN.LIVE_CHAT.EMPTY_STATE.SUBTITLE')"
|
||||
class="pt-14"
|
||||
/>
|
||||
<EditLiveChatCampaignDialog
|
||||
ref="editLiveChatCampaignDialogRef"
|
||||
:selected-campaign="selectedCampaign"
|
||||
/>
|
||||
<ConfirmDeleteCampaignDialog
|
||||
ref="confirmDeleteCampaignDialogRef"
|
||||
:selected-campaign="selectedCampaign"
|
||||
/>
|
||||
</CampaignLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,72 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
import { useStoreGetters, useMapGetter } from 'dashboard/composables/store';
|
||||
|
||||
import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
|
||||
import CampaignLayout from 'dashboard/components-next/Campaigns/CampaignLayout.vue';
|
||||
import CampaignList from 'dashboard/components-next/Campaigns/Pages/CampaignPage/CampaignList.vue';
|
||||
import SMSCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/SMSCampaign/SMSCampaignDialog.vue';
|
||||
import ConfirmDeleteCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/ConfirmDeleteCampaignDialog.vue';
|
||||
import SMSCampaignEmptyState from 'dashboard/components-next/Campaigns/EmptyState/SMSCampaignEmptyState.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const getters = useStoreGetters();
|
||||
|
||||
const selectedCampaign = ref(null);
|
||||
const [showSMSCampaignDialog, toggleSMSCampaignDialog] = useToggle();
|
||||
|
||||
const uiFlags = useMapGetter('campaigns/getUIFlags');
|
||||
const isFetchingCampaigns = computed(() => uiFlags.value.isFetching);
|
||||
|
||||
const confirmDeleteCampaignDialogRef = ref(null);
|
||||
|
||||
const SMSCampaigns = computed(() => getters['campaigns/getSMSCampaigns'].value);
|
||||
|
||||
const hasNoSMSCampaigns = computed(
|
||||
() => SMSCampaigns.value?.length === 0 && !isFetchingCampaigns.value
|
||||
);
|
||||
|
||||
const handleDelete = campaign => {
|
||||
selectedCampaign.value = campaign;
|
||||
confirmDeleteCampaignDialogRef.value.dialogRef.open();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CampaignLayout
|
||||
:header-title="t('CAMPAIGN.SMS.HEADER_TITLE')"
|
||||
:button-label="t('CAMPAIGN.SMS.NEW_CAMPAIGN')"
|
||||
@click="toggleSMSCampaignDialog()"
|
||||
@close="toggleSMSCampaignDialog(false)"
|
||||
>
|
||||
<template #action>
|
||||
<SMSCampaignDialog
|
||||
v-if="showSMSCampaignDialog"
|
||||
@close="toggleSMSCampaignDialog(false)"
|
||||
/>
|
||||
</template>
|
||||
<div
|
||||
v-if="isFetchingCampaigns"
|
||||
class="flex items-center justify-center py-10 text-n-slate-11"
|
||||
>
|
||||
<Spinner />
|
||||
</div>
|
||||
<CampaignList
|
||||
v-else-if="!hasNoSMSCampaigns"
|
||||
:campaigns="SMSCampaigns"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
<SMSCampaignEmptyState
|
||||
v-else
|
||||
:title="t('CAMPAIGN.SMS.EMPTY_STATE.TITLE')"
|
||||
:subtitle="t('CAMPAIGN.SMS.EMPTY_STATE.SUBTITLE')"
|
||||
class="pt-14"
|
||||
/>
|
||||
<ConfirmDeleteCampaignDialog
|
||||
ref="confirmDeleteCampaignDialogRef"
|
||||
:selected-campaign="selectedCampaign"
|
||||
/>
|
||||
</CampaignLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,74 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
import { useStoreGetters, useMapGetter } from 'dashboard/composables/store';
|
||||
|
||||
import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
|
||||
import CampaignLayout from 'dashboard/components-next/Campaigns/CampaignLayout.vue';
|
||||
import CampaignList from 'dashboard/components-next/Campaigns/Pages/CampaignPage/CampaignList.vue';
|
||||
import WhatsAppCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/WhatsAppCampaign/WhatsAppCampaignDialog.vue';
|
||||
import ConfirmDeleteCampaignDialog from 'dashboard/components-next/Campaigns/Pages/CampaignPage/ConfirmDeleteCampaignDialog.vue';
|
||||
import WhatsAppCampaignEmptyState from 'dashboard/components-next/Campaigns/EmptyState/WhatsAppCampaignEmptyState.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const getters = useStoreGetters();
|
||||
|
||||
const selectedCampaign = ref(null);
|
||||
const [showWhatsAppCampaignDialog, toggleWhatsAppCampaignDialog] = useToggle();
|
||||
|
||||
const uiFlags = useMapGetter('campaigns/getUIFlags');
|
||||
const isFetchingCampaigns = computed(() => uiFlags.value.isFetching);
|
||||
|
||||
const confirmDeleteCampaignDialogRef = ref(null);
|
||||
|
||||
const WhatsAppCampaigns = computed(
|
||||
() => getters['campaigns/getWhatsAppCampaigns'].value
|
||||
);
|
||||
|
||||
const hasNoWhatsAppCampaigns = computed(
|
||||
() => WhatsAppCampaigns.value?.length === 0 && !isFetchingCampaigns.value
|
||||
);
|
||||
|
||||
const handleDelete = campaign => {
|
||||
selectedCampaign.value = campaign;
|
||||
confirmDeleteCampaignDialogRef.value.dialogRef.open();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CampaignLayout
|
||||
:header-title="t('CAMPAIGN.WHATSAPP.HEADER_TITLE')"
|
||||
:button-label="t('CAMPAIGN.WHATSAPP.NEW_CAMPAIGN')"
|
||||
@click="toggleWhatsAppCampaignDialog()"
|
||||
@close="toggleWhatsAppCampaignDialog(false)"
|
||||
>
|
||||
<template #action>
|
||||
<WhatsAppCampaignDialog
|
||||
v-if="showWhatsAppCampaignDialog"
|
||||
@close="toggleWhatsAppCampaignDialog(false)"
|
||||
/>
|
||||
</template>
|
||||
<div
|
||||
v-if="isFetchingCampaigns"
|
||||
class="flex items-center justify-center py-10 text-n-slate-11"
|
||||
>
|
||||
<Spinner />
|
||||
</div>
|
||||
<CampaignList
|
||||
v-else-if="!hasNoWhatsAppCampaigns"
|
||||
:campaigns="WhatsAppCampaigns"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
<WhatsAppCampaignEmptyState
|
||||
v-else
|
||||
:title="t('CAMPAIGN.WHATSAPP.EMPTY_STATE.TITLE')"
|
||||
:subtitle="t('CAMPAIGN.WHATSAPP.EMPTY_STATE.SUBTITLE')"
|
||||
class="pt-14"
|
||||
/>
|
||||
<ConfirmDeleteCampaignDialog
|
||||
ref="confirmDeleteCampaignDialogRef"
|
||||
:selected-campaign="selectedCampaign"
|
||||
/>
|
||||
</CampaignLayout>
|
||||
</template>
|
||||
Reference in New Issue
Block a user