feat: Update design for report pages (#10506)

<img width="1440" alt="Screenshot 2024-11-26 at 8 38 57 PM"
src="https://github.com/user-attachments/assets/f752157c-6134-42cb-8211-ce636ea9e4d6">
<img width="1439" alt="Screenshot 2024-11-26 at 8 40 47 PM"
src="https://github.com/user-attachments/assets/580b1f61-68bc-489b-9081-b0aeb402f31d">

---------

Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
This commit is contained in:
Pranav
2024-11-27 02:10:15 -08:00
committed by GitHub
parent d569713b66
commit 35702457ed
43 changed files with 361 additions and 363 deletions

View File

@@ -25,7 +25,7 @@
}
.mx-input {
@apply h-[2.5rem] flex border border-solid border-slate-200 dark:border-slate-600 rounded-md shadow-none;
@apply h-[2.5rem] flex border border-solid border-n-weak rounded-md shadow-none;
}
.mx-input:disabled,
@@ -39,7 +39,7 @@
}
.mx-datepicker-main {
@apply border-0 bg-white dark:bg-slate-800;
@apply border-0 bg-n-solid-2 rounded-xl;
.cell {
&.disabled {
@@ -53,6 +53,14 @@
}
}
.mx-calendar+.mx-calendar {
@apply border-l border-n-weak;
}
.mx-datepicker-footer {
@apply border border-n-weak;
}
.mx-time {
@apply border-0 bg-white dark:bg-slate-800;

View File

@@ -22,7 +22,7 @@ const handleButtonClick = () => {
<template>
<section class="flex flex-col w-full h-full overflow-hidden bg-n-background">
<header class="sticky top-0 z-10 px-6 lg:px-0">
<div class="w-full max-w-[900px] mx-auto">
<div class="w-full max-w-[960px] mx-auto">
<div class="flex items-center justify-between w-full h-20 gap-2">
<span class="text-xl font-medium text-n-slate-12">
{{ headerTitle }}
@@ -44,7 +44,7 @@ const handleButtonClick = () => {
</div>
</header>
<main class="flex-1 px-6 overflow-y-auto lg:px-0">
<div class="w-full max-w-[900px] mx-auto py-4">
<div class="w-full max-w-[960px] mx-auto py-4">
<slot name="default" />
</div>
</main>

View File

@@ -46,7 +46,7 @@ const emit = defineEmits([
<template>
<header class="sticky top-0 z-10 px-6 xl:px-0">
<div
class="flex items-center justify-between w-full h-20 gap-2 mx-auto max-w-[900px]"
class="flex items-center justify-between w-full h-20 gap-2 mx-auto max-w-[960px]"
>
<span class="text-xl font-medium truncate text-n-slate-12">
{{ headerTitle }}

View File

@@ -60,7 +60,7 @@ const togglePortalSwitcher = () => {
<template>
<section class="flex flex-col w-full h-full overflow-hidden bg-n-background">
<header class="sticky top-0 z-10 px-6 pb-3 lg:px-0">
<div class="w-full max-w-[900px] mx-auto">
<div class="w-full max-w-[960px] mx-auto">
<div
v-if="showHeaderTitle"
class="flex items-center justify-start h-20 gap-2"
@@ -95,7 +95,7 @@ const togglePortalSwitcher = () => {
</div>
</header>
<main class="flex-1 px-6 overflow-y-auto lg:px-0">
<div class="w-full max-w-[900px] mx-auto py-3">
<div class="w-full max-w-[960px] mx-auto py-3">
<slot name="content" />
</div>
</main>

View File

@@ -14,22 +14,22 @@ const menuItems = ref([
{
label: 'Contact Support',
icon: 'i-lucide-life-buoy',
click: () => window.alert('Contact Support'),
click: () => console.log('Contact Support'),
},
{
label: 'Keyboard Shortcuts',
icon: 'i-lucide-keyboard',
click: () => window.alert('Keyboard Shortcuts'),
click: () => console.log('Keyboard Shortcuts'),
},
{
label: 'Profile Settings',
icon: 'i-lucide-user-pen',
click: () => window.alert('Profile Settings'),
click: () => console.log('Profile Settings'),
},
{
label: 'Change Appearance',
icon: 'i-lucide-swatch-book',
click: () => window.alert('Change Appearance'),
click: () => console.log('Change Appearance'),
},
{
label: 'Open SuperAdmin',
@@ -40,7 +40,7 @@ const menuItems = ref([
{
label: 'Log Out',
icon: 'i-lucide-log-out',
click: () => window.alert('Log Out'),
click: () => console.log('Log Out'),
},
]);
</script>

View File

@@ -249,11 +249,6 @@ const menuItems = computed(() => {
label: t('SIDEBAR.CSAT'),
to: accountScopedRoute('csat_reports'),
},
{
name: 'Reports Bot',
label: t('SIDEBAR.REPORTS_BOT'),
to: accountScopedRoute('bot_reports'),
},
{
name: 'Reports Agent',
label: t('SIDEBAR.REPORTS_AGENT'),
@@ -279,6 +274,11 @@ const menuItems = computed(() => {
label: t('SIDEBAR.REPORTS_SLA'),
to: accountScopedRoute('sla_reports'),
},
{
name: 'Reports Bot',
label: t('SIDEBAR.REPORTS_BOT'),
to: accountScopedRoute('bot_reports'),
},
],
},
{

View File

@@ -54,7 +54,7 @@ const end = computed(() => {
<div class="flex items-center justify-between">
<div class="flex flex-1 items-center justify-between">
<div>
<p class="text-sm text-gray-700">
<p class="text-sm text-n-slate-11 mb-0">
{{ $t('REPORT.PAGINATION.RESULTS', { start, end, total }) }}
</p>
</div>
@@ -62,7 +62,7 @@ const end = computed(() => {
<woot-button
:disabled="!table.getCanPreviousPage()"
variant="clear"
class="size-8 flex items-center border border-slate-50"
class="h-8 border-0 flex items-center"
color-scheme="secondary"
@click="table.setPageIndex(0)"
>
@@ -70,7 +70,7 @@ const end = computed(() => {
</woot-button>
<woot-button
variant="clear"
class="size-8 flex items-center border border-slate-50"
class="h-8 border-0 flex items-center"
color-scheme="secondary"
:disabled="!table.getCanPreviousPage()"
@click="table.previousPage()"
@@ -81,22 +81,22 @@ const end = computed(() => {
v-for="page in visiblePages"
:key="page"
variant="clear"
class="size-8 flex items-center justify-center border text-xs leading-none text-center"
:class="page == currentPage ? 'border-woot-500' : 'border-slate-50'"
class="h-8 flex items-center justify-center text-xs leading-none text-center"
:class="page == currentPage ? 'border-n-brand' : 'border-slate-50'"
color-scheme="secondary"
@click="table.setPageIndex(page - 1)"
>
<div
<span
class="text-center"
:class="{ 'text-woot-500': page == currentPage }"
:class="{ 'text-n-brand': page == currentPage }"
>
{{ page }}
</div>
</span>
</woot-button>
<woot-button
:disabled="!table.getCanNextPage()"
variant="clear"
class="size-8 flex items-center border border-slate-50"
class="h-8 border-0 flex items-center"
color-scheme="secondary"
@click="table.nextPage()"
>
@@ -105,7 +105,7 @@ const end = computed(() => {
<woot-button
:disabled="!table.getCanNextPage()"
variant="clear"
class="size-8 flex items-center border border-slate-50"
class="h-8 border-0 flex items-center"
color-scheme="secondary"
@click="table.setPageIndex(table.getPageCount() - 1)"
>

View File

@@ -1,8 +1,9 @@
<script setup>
import { FlexRender } from '@tanstack/vue-table';
import SortButton from './SortButton.vue';
import { computed } from 'vue';
defineProps({
const props = defineProps({
table: {
type: Object,
required: true,
@@ -11,22 +12,36 @@ defineProps({
type: Boolean,
default: false,
},
type: {
type: String,
default: 'relaxed',
},
});
const isRelaxed = computed(() => props.type === 'relaxed');
const headerClass = computed(() =>
isRelaxed.value
? 'first:rounded-bl-lg first:rounded-tl-lg last:rounded-br-lg last:rounded-tr-lg'
: ''
);
</script>
<template>
<table :class="{ 'table-fixed': fixed }">
<thead
class="sticky top-0 z-10 border-b border-slate-50 dark:border-slate-800 bg-slate-25 dark:bg-slate-800"
>
<tr v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
<thead class="sticky top-0 z-10 bg-n-slate-1">
<tr
v-for="headerGroup in table.getHeaderGroups()"
:key="headerGroup.id"
class="rounded-xl"
>
<th
v-for="header in headerGroup.headers"
:key="header.id"
:style="{
width: `${header.getSize()}px`,
}"
class="text-left py-3 px-5 dark:bg-slate-800 text-slate-800 dark:text-slate-200 font-normal text-xs"
class="text-left py-3 px-5 font-normal text-sm"
:class="headerClass"
@click="header.column.getCanSort() && header.column.toggleSorting()"
>
<div
@@ -43,16 +58,12 @@ defineProps({
</tr>
</thead>
<tbody class="divide-y divide-slate-25 dark:divide-slate-900">
<tr
v-for="row in table.getRowModel().rows"
:key="row.id"
class="hover:bg-slate-25 dark:hover:bg-slate-800"
>
<tbody class="divide-y divide-n-slate-2">
<tr v-for="row in table.getRowModel().rows" :key="row.id">
<td
v-for="cell in row.getVisibleCells()"
:key="cell.id"
class="py-2 px-5"
:class="isRelaxed ? 'py-4 px-5' : 'py-2 px-5'"
>
<FlexRender
:render="cell.column.columnDef.cell"

View File

@@ -29,7 +29,7 @@ const spanClass = computed(() => {
<template>
<div
class="flex items-center px-0 py-2 text-xs font-medium text-left uppercase text-slate-700 dark:text-slate-100 rtl:text-right"
class="flex items-center px-0 py-2 text-xs font-medium text-right uppercase text-n-slate-11 rtl:text-left"
:class="spanClass"
>
<slot>

View File

@@ -4,7 +4,7 @@ import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
defineProps({
user: {
type: Object,
default: () => {},
default: () => ({}),
},
size: {
type: String,
@@ -12,7 +12,7 @@ defineProps({
},
textClass: {
type: String,
default: 'text-xs text-slate-600',
default: 'text-sm text-n-slate-12',
},
});
</script>
@@ -25,11 +25,11 @@ defineProps({
:username="user.name"
:status="user.availability_status"
/>
<h6
class="my-0 dark:text-slate-100 overflow-hidden whitespace-nowrap text-ellipsis text-capitalize"
<span
class="my-0 overflow-hidden whitespace-nowrap text-ellipsis text-capitalize"
:class="textClass"
>
{{ user.name }}
</h6>
</span>
</div>
</template>

View File

@@ -18,7 +18,7 @@ const formatDate = timestamp =>
<template>
<div class="flex justify-between w-full">
<span
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-slate-600 dark:text-slate-200"
class="text-sm sticky top-0 h-fit font-normal tracking-[-0.6%] min-w-[140px] truncate text-n-slate-11"
>
{{ label }}
</span>
@@ -26,7 +26,7 @@ const formatDate = timestamp =>
<span
v-for="item in items"
:key="item.id"
class="text-sm font-normal text-slate-900 dark:text-slate-25 text-right tabular-nums"
class="text-sm font-normal text-n-slate-12 text-right tabular-nums"
>
{{ formatDate(item.created_at) }}
</span>

View File

@@ -40,9 +40,9 @@ const toggleShowAllNRT = () => {
<template>
<div
class="absolute flex flex-col items-start bg-white dark:bg-slate-800 z-50 p-4 border border-solid border-slate-75 dark:border-slate-700 w-[384px] rounded-xl gap-4 max-h-96 overflow-auto"
class="absolute flex flex-col items-start border-n-strong bg-n-solid-3 w-96 backdrop-blur-[100px] px-6 py-5 z-50 shadow rounded-xl gap-4 max-h-96 overflow-auto"
>
<span class="text-sm font-medium text-slate-900 dark:text-slate-25">
<span class="text-sm font-medium text-n-slate-12">
{{ $t('SLA.EVENTS.TITLE') }}
</span>
<SLAEventItem

View File

@@ -171,7 +171,7 @@ const table = useVueTable({
<template>
<section class="flex-1 h-full overflow-auto bg-white dark:bg-slate-900">
<section class="overflow-x-auto">
<Table fixed :table="table" />
<Table fixed :table="table" type="compact" />
</section>
<EmptyState

View File

@@ -1,11 +1,5 @@
<script>
<script setup>
import WootReports from './components/WootReports.vue';
export default {
components: {
WootReports,
},
};
</script>
<template>
@@ -15,5 +9,6 @@ export default {
getter-key="agents/getAgents"
action-key="agents/get"
:download-button-label="$t('REPORT.DOWNLOAD_AGENT_REPORTS')"
:report-title="$t('AGENT_REPORTS.HEADER')"
/>
</template>

View File

@@ -5,11 +5,13 @@ import ReportFilterSelector from './components/FilterSelector.vue';
import { GROUP_BY_FILTER } from './constants';
import ReportContainer from './ReportContainer.vue';
import { REPORTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
import ReportHeader from './components/ReportHeader.vue';
export default {
name: 'BotReports',
components: {
BotMetrics,
ReportHeader,
ReportFilterSelector,
ReportContainer,
},
@@ -84,7 +86,8 @@ export default {
</script>
<template>
<div class="flex-1 p-4 overflow-auto">
<ReportHeader :header-title="$t('BOT_REPORTS.HEADER')" />
<div class="flex flex-col gap-4">
<ReportFilterSelector
:show-agents-filter="false"
show-group-by-filter

View File

@@ -7,6 +7,8 @@ import ReportFilterSelector from './components/FilterSelector.vue';
import { generateFileName } from '../../../../helper/downloadHelper';
import { REPORTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
import { FEATURE_FLAGS } from '../../../../featureFlags';
import V4Button from 'dashboard/components-next/button/Button.vue';
import ReportHeader from './components/ReportHeader.vue';
export default {
name: 'CsatResponses',
@@ -14,6 +16,8 @@ export default {
CsatMetrics,
CsatTable,
ReportFilterSelector,
ReportHeader,
V4Button,
},
data() {
return {
@@ -108,7 +112,16 @@ export default {
</script>
<template>
<div class="flex-1 p-4 overflow-auto">
<ReportHeader :header-title="$t('CSAT_REPORTS.HEADER')">
<V4Button
:label="$t('CSAT_REPORTS.DOWNLOAD')"
icon="i-ph-download-simple"
size="sm"
@click="downloadReports"
/>
</ReportHeader>
<div class="flex flex-col gap-4">
<ReportFilterSelector
show-agents-filter
show-inbox-filter
@@ -117,14 +130,7 @@ export default {
:show-business-hours-switch="false"
@filter-change="onFilterChange"
/>
<woot-button
color-scheme="success"
class-names="button--fixed-top"
icon="arrow-download"
@click="downloadReports"
>
{{ $t('CSAT_REPORTS.DOWNLOAD') }}
</woot-button>
<CsatMetrics :filters="requestPayload" />
<CsatTable :page-index="pageIndex" @page-change="onPageNumberChange" />
</div>

View File

@@ -1,11 +1,5 @@
<script>
<script setup>
import WootReports from './components/WootReports.vue';
export default {
components: {
WootReports,
},
};
</script>
<template>
@@ -15,5 +9,6 @@ export default {
getter-key="inboxes/getInboxes"
action-key="inboxes/get"
:download-button-label="$t('INBOX_REPORTS.DOWNLOAD_INBOX_REPORTS')"
:report-title="$t('INBOX_REPORTS.HEADER')"
/>
</template>

View File

@@ -1,4 +1,5 @@
<script>
import V4Button from 'dashboard/components-next/button/Button.vue';
import { useAlert, useTrack } from 'dashboard/composables';
import fromUnixTime from 'date-fns/fromUnixTime';
import format from 'date-fns/format';
@@ -6,6 +7,7 @@ import ReportFilterSelector from './components/FilterSelector.vue';
import { GROUP_BY_FILTER } from './constants';
import { REPORTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
import ReportContainer from './ReportContainer.vue';
import ReportHeader from './components/ReportHeader.vue';
const REPORTS_KEYS = {
CONVERSATIONS: 'conversations_count',
@@ -20,8 +22,10 @@ const REPORTS_KEYS = {
export default {
name: 'ConversationReports',
components: {
ReportHeader,
ReportFilterSelector,
ReportContainer,
V4Button,
},
data() {
return {
@@ -98,15 +102,15 @@ export default {
</script>
<template>
<div class="flex-1 p-4 overflow-auto">
<woot-button
color-scheme="success"
class-names="button--fixed-top"
icon="arrow-download"
<ReportHeader :header-title="$t('REPORT.HEADER')">
<V4Button
:label="$t('REPORT.DOWNLOAD_AGENT_REPORTS')"
icon="i-ph-download-simple"
size="sm"
@click="downloadAgentReports"
>
{{ $t('REPORT.DOWNLOAD_AGENT_REPORTS') }}
</woot-button>
/>
</ReportHeader>
<div class="flex flex-col gap-3">
<ReportFilterSelector
:show-agents-filter="false"
show-group-by-filter

View File

@@ -1,11 +1,5 @@
<script>
<script setup>
import WootReports from './components/WootReports.vue';
export default {
components: {
WootReports,
},
};
</script>
<template>
@@ -15,5 +9,6 @@ export default {
getter-key="labels/getLabels"
action-key="labels/get"
:download-button-label="$t('LABEL_REPORTS.DOWNLOAD_LABEL_REPORTS')"
:report-title="$t('LABEL_REPORTS.HEADER')"
/>
</template>

View File

@@ -10,10 +10,12 @@ import getUnixTime from 'date-fns/getUnixTime';
import startOfDay from 'date-fns/startOfDay';
import subDays from 'date-fns/subDays';
import { emitter } from 'shared/helpers/mitt';
import ReportHeader from './components/ReportHeader.vue';
export default {
name: 'LiveReports',
components: {
ReportHeader,
AgentTable,
MetricCard,
ReportHeatmap,
@@ -123,8 +125,9 @@ export default {
</script>
<template>
<div class="flex-1 p-4 overflow-auto">
<div class="flex flex-col items-center md:flex-row">
<ReportHeader :header-title="$t('OVERVIEW_REPORTS.HEADER')" />
<div class="flex flex-col gap-4 pb-6">
<div class="flex flex-col items-center md:flex-row gap-4">
<div
class="flex-1 w-full max-w-full md:w-[65%] md:max-w-[65%] conversation-metric"
>
@@ -140,10 +143,10 @@ export default {
:key="index"
class="flex-1 min-w-0 pb-2"
>
<h3 class="text-base text-slate-700 dark:text-slate-100">
<h3 class="text-base text-n-slate-11">
{{ name }}
</h3>
<p class="text-woot-800 dark:text-woot-300 text-3xl mb-0 mt-1">
<p class="text-n-slate-12 text-3xl mb-0 mt-1">
{{ metric }}
</p>
</div>
@@ -156,17 +159,17 @@ export default {
:key="index"
class="flex-1 min-w-0 pb-2"
>
<h3 class="text-base text-slate-700 dark:text-slate-100">
<h3 class="text-base text-n-slate-11">
{{ name }}
</h3>
<p class="text-woot-800 dark:text-woot-300 text-3xl mb-0 mt-1">
<p class="text-n-slate-12 text-3xl mb-0 mt-1">
{{ metric }}
</p>
</div>
</MetricCard>
</div>
</div>
<div class="flex flex-row flex-wrap max-w-full ml-auto mr-auto">
<div class="flex flex-row flex-wrap max-w-full">
<MetricCard :header="$t('OVERVIEW_REPORTS.CONVERSATION_HEATMAP.HEADER')">
<template #control>
<woot-button
@@ -185,7 +188,7 @@ export default {
/>
</MetricCard>
</div>
<div class="flex flex-row flex-wrap max-w-full ml-auto mr-auto">
<div class="flex flex-row flex-wrap max-w-full">
<MetricCard :header="$t('OVERVIEW_REPORTS.AGENT_CONVERSATIONS.HEADER')">
<AgentTable
:agents="agents"

View File

@@ -135,7 +135,7 @@ export default {
<template>
<div
class="grid grid-cols-1 p-2 bg-white border rounded-md md:grid-cols-2 lg:grid-cols-3 dark:bg-slate-800 border-slate-100 dark:border-slate-700"
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 px-6 py-5 shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2"
>
<div
v-for="metric in metrics"

View File

@@ -1,13 +1,17 @@
<script>
import V4Button from 'dashboard/components-next/button/Button.vue';
import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import SLAMetrics from './components/SLA/SLAMetrics.vue';
import SLATable from './components/SLA/SLATable.vue';
import SLAReportFilters from './components/SLA/SLAReportFilters.vue';
import { generateFileName } from 'dashboard/helper/downloadHelper';
import ReportHeader from './components/ReportHeader.vue';
export default {
name: 'SLAReports',
components: {
V4Button,
ReportHeader,
SLAMetrics,
SLATable,
SLAReportFilters,
@@ -77,30 +81,28 @@ export default {
</script>
<template>
<div class="flex flex-col flex-1 gap-6 px-4 pt-4 overflow-auto">
<SLAReportFilters @filter-change="onFilterChange" />
<woot-button
color-scheme="success"
class-names="button--fixed-top"
icon="arrow-download"
<ReportHeader :header-title="$t('SLA_REPORTS.HEADER')">
<V4Button
:label="$t('SLA_REPORTS.DOWNLOAD_SLA_REPORTS')"
icon="i-ph-download-simple"
size="sm"
@click="downloadReports"
>
{{ $t('SLA_REPORTS.DOWNLOAD_SLA_REPORTS') }}
</woot-button>
<div class="flex flex-col gap-6">
<SLAMetrics
:hit-rate="slaMetrics.hitRate"
:no-of-breaches="slaMetrics.numberOfSLAMisses"
:no-of-conversations="slaMetrics.numberOfConversations"
:is-loading="uiFlags.isFetchingMetrics"
/>
<SLATable
:sla-reports="slaReports"
:is-loading="uiFlags.isFetching"
:current-page="Number(slaMeta.currentPage)"
:total-count="Number(slaMeta.count)"
@page-change="onPageChange"
/>
</div>
/>
</ReportHeader>
<div class="flex flex-col flex-1 gap-6">
<SLAReportFilters @filter-change="onFilterChange" />
<SLAMetrics
:hit-rate="slaMetrics.hitRate"
:no-of-breaches="slaMetrics.numberOfSLAMisses"
:no-of-conversations="slaMetrics.numberOfConversations"
:is-loading="uiFlags.isFetchingMetrics"
/>
<SLATable
:sla-reports="slaReports"
:is-loading="uiFlags.isFetching"
:current-page="Number(slaMeta.currentPage)"
:total-count="Number(slaMeta.count)"
@page-change="onPageChange"
/>
</div>
</template>

View File

@@ -1,11 +1,5 @@
<script>
<script setup>
import WootReports from './components/WootReports.vue';
export default {
components: {
WootReports,
},
};
</script>
<template>
@@ -15,5 +9,6 @@ export default {
getter-key="teams/getTeams"
action-key="teams/get"
:download-button-label="$t('TEAM_REPORTS.DOWNLOAD_TEAM_REPORTS')"
:report-title="$t('TEAM_REPORTS.HEADER')"
/>
</template>

View File

@@ -38,7 +38,7 @@ onMounted(fetchMetrics);
<template>
<div
class="flex flex-wrap mx-0 bg-white dark:bg-slate-800 rounded-[4px] p-4 mb-5 border border-solid border-slate-75 dark:border-slate-700"
class="flex flex-wrap mx-0 shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2 px-6 py-5"
>
<ReportMetricCard
:label="$t('BOT_REPORTS.METRIC.TOTAL_CONVERSATIONS.LABEL')"

View File

@@ -29,11 +29,11 @@ const trendColor = (value, key) => {
</script>
<template>
<div class="text-slate-900 dark:text-slate-100">
<div class="text-n-slate-11">
<span class="text-sm">
{{ metric.NAME }}
</span>
<div class="flex items-end">
<div class="flex items-end text-n-slate-12">
<div class="text-xl font-medium">
{{ displayMetric(metric.KEY) }}
</div>

View File

@@ -86,7 +86,7 @@ export default {
<!-- Added ref for writing specs -->
<template>
<div
class="flex-col lg:flex-row flex flex-wrap mx-0 bg-white dark:bg-slate-800 rounded-[4px] p-4 mb-5 border border-solid border-slate-75 dark:border-slate-700"
class="flex-col lg:flex-row flex flex-wrap mx-0 shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2 px-6 py-8 gap-4"
>
<CsatMetricCard
:label="$t('CSAT_REPORTS.METRIC.TOTAL_RESPONSES.LABEL')"
@@ -111,10 +111,10 @@ export default {
<div
v-if="metrics.totalResponseCount && !ratingFilterEnabled"
ref="csatBarChart"
class="w-full md:w-1/2 md:max-w-[50%] flex-1 rtl:[direction:initial] p-4"
class="w-full md:w-1/2 md:max-w-[50%] flex-1 rtl:[direction:initial]"
>
<h3
class="flex items-center m-0 text-xs font-medium md:text-sm text-slate-800 dark:text-slate-100"
class="flex items-center m-0 text-xs font-medium md:text-sm text-n-slate-12"
>
<div class="flex flex-row-reverse justify-end">
<div

View File

@@ -145,14 +145,13 @@ const table = useVueTable({
</script>
<template>
<div class="csat--table-container">
<Table
:table="table"
class="max-h-[calc(100vh-21.875rem)] border bg-white dark:bg-slate-900 border-slate-50 dark:border-slate-800"
/>
<div
class="shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2 px-6 py-5"
>
<Table :table="table" class="max-h-[calc(100vh-21.875rem)]" />
<div
v-show="!tableData.length"
class="csat--empty-records text-slate-600 dark:text-slate-200 bg-white dark:bg-slate-900 border border-t-0 border-solid border-slate-75 dark:border-slate-700"
class="h-48 flex items-center justify-center text-n-slate-12 text-sm"
>
{{ $t('CSAT_REPORTS.NO_RECORDS') }}
</div>
@@ -161,17 +160,3 @@ const table = useVueTable({
</div>
</div>
</template>
<style lang="scss" scoped>
.csat--empty-records {
align-items: center;
// border: 1px solid var(--color-border);
border-top: 0;
display: flex;
font-size: var(--font-size-small);
height: 12.5rem;
justify-content: center;
margin-top: -1px;
width: 100%;
}
</style>

View File

@@ -178,7 +178,7 @@ export default {
</script>
<template>
<div class="flex flex-col justify-between gap-3 mb-4 md:flex-row">
<div class="flex flex-col justify-between gap-3 md:flex-row">
<div
class="w-full grid gap-y-2 gap-x-1.5 grid-cols-[repeat(auto-fill,minmax(250px,1fr))]"
>

View File

@@ -53,7 +53,6 @@ const closeDropdown = () => emit('closeDropdown');
<FilterButton
right-icon="chevron-down"
:button-text="name"
class="bg-slate-50 dark:bg-slate-800 hover:bg-slate-75 dark:hover:bg-slate-800"
@click="toggleDropdown"
>
<template v-if="showMenu && activeFilterType === type" #dropdown>

View File

@@ -63,8 +63,7 @@ function getDayOfTheWeek(date) {
return days[dayIndex];
}
function getHeatmapLevelClass(value) {
if (!value)
return 'outline-slate-100 dark:outline-slate-700 dark:bg-slate-700/40 bg-slate-50/50';
if (!value) return 'outline-n-container dark:bg-slate-700/40 bg-slate-50/50';
let level = [...quantileRange.value, Infinity].findIndex(
range => value <= range && value > 0
@@ -73,7 +72,7 @@ function getHeatmapLevelClass(value) {
if (level > 6) level = 5;
if (level === 0) {
return 'outline-slate-100 dark:outline-slate-700 dark:bg-slate-700/40 bg-slate-50/50';
return 'outline-n-container dark:bg-slate-700/40 bg-slate-50/50';
}
const classes = [

View File

@@ -0,0 +1,17 @@
<script setup>
defineProps({
headerTitle: {
required: true,
type: String,
},
});
</script>
<template>
<div class="flex items-center justify-between w-full h-20 gap-2">
<span class="text-xl font-medium text-n-slate-12">
{{ headerTitle }}
</span>
<slot />
</div>
</template>

View File

@@ -22,26 +22,23 @@ defineProps({
<template>
<div
data-test-id="reportMetricContainer"
class="p-4 m-0"
:class="{
'grayscale pointer-events-none opacity-30': disabled,
}"
>
<h3
class="flex items-center m-0 text-sm font-medium text-slate-800 dark:text-slate-100"
>
<h3 class="flex items-center m-0 text-sm font-medium text-n-slate-11">
<span data-test-id="reportMetricLabel">{{ label }}</span>
<fluent-icon
v-tooltip="infoText"
data-test-id="reportMetricInfo"
size="14"
icon="info"
class="text-slate-500 dark:text-slate-200 my-0 mx-1 mt-0.5"
class="text-n-slate-11 my-0 mx-1 mt-0.5"
/>
</h3>
<h4
data-test-id="reportMetricValue"
class="mt-1 mb-0 text-3xl font-thin text-slate-700 dark:text-slate-100"
class="mt-1 mb-0 text-2xl text-n-slate-12"
>
{{ value }}
</h4>

View File

@@ -0,0 +1,85 @@
<template>
<div
class="reports--wrapper overflow-auto bg-n-background w-full px-8 xl:px-0"
>
<div class="max-w-[960px] mx-auto pb-12">
<router-view />
</div>
</div>
</template>
<style scoped lang="scss">
.reports--wrapper {
::v-deep {
.multiselect--disabled {
@apply opacity-50 border border-n-weak rounded-md cursor-not-allowed;
}
.multiselect__content-wrapper {
@apply bg-n-solid-2 border border-n-weak text-n-slate-12;
}
.multiselect__tags {
@apply bg-n-slate-1 border border-n-weak m-0 min-h-[2.875rem] pt-0;
input[type='text'] {
@apply bg-n-alpha-3 border-n-weak !min-h-[2.375rem] !h-[2.375rem] !ps-0.5 !py-0 !text-sm;
}
}
.multiselect__placeholder {
@apply text-n-slate-11;
}
.multiselect__select {
@apply min-h-0;
}
.multiselect__single {
@apply bg-n-alpha-3 text-n-slate-11;
}
.multiselect__input {
@apply text-sm !h-[2.375rem] mb-0 !py-0;
}
.multiselect__tags,
.multiselect__input,
.multiselect {
@apply bg-n-alpha-3 !border-n-weak text-n-slate-12 rounded-lg text-sm min-h-[2.5rem];
}
.mx-input-wrapper {
@apply bg-n-alpha-3 !border-n-weak text-n-slate-12 rounded-lg text-sm;
input {
@apply border-n-weak text-sm;
}
}
.multiselect__option {
@apply flex items-center;
}
.mx-datepicker {
.mx-input {
@apply bg-n-alpha-3;
}
.mx-input-wrapper input::placeholder {
@apply text-n-slate-11;
}
.mx-input-wrapper input {
@apply text-n-slate-11;
}
}
.multiselect--active:not(.multiselect--above) .multiselect__current,
.multiselect--active:not(.multiselect--above) .multiselect__input,
.multiselect--active:not(.multiselect--above) .multiselect__tags {
@apply rounded-b-none;
}
}
}
</style>

View File

@@ -24,7 +24,7 @@ export default {
<template>
<div class="flex flex-col gap-2 items-start justify-center min-w-[10rem]">
<span
class="inline-flex items-center gap-1 text-sm font-medium text-slate-700 dark:text-slate-200"
class="inline-flex items-center gap-1 text-sm font-medium text-n-slate-11"
>
{{ label }}
<fluent-icon
@@ -32,15 +32,15 @@ export default {
size="14"
icon="information"
type="outline"
class="flex flex-shrink-0 text-sm font-normal sm:font-medium text-slate-500 dark:text-slate-500"
class="flex flex-shrink-0 text-sm font-normal sm:font-medium text-n-slate-10"
/>
</span>
<div
v-if="isLoading"
class="w-12 h-6 mb-0.5 rounded-md bg-slate-50 dark:bg-slate-800 animate-pulse"
class="w-12 h-6 mb-0.5 rounded-md bg-n-slate-3 animate-pulse"
/>
<span v-else class="text-2xl font-medium text-slate-900 dark:text-slate-25">
<span v-else class="text-2xl font-medium text-n-slate-12">
{{ value }}
</span>
</div>

View File

@@ -22,7 +22,7 @@ defineProps({
<template>
<div
class="flex sm:flex-row flex-col w-full gap-4 sm:gap-14 bg-white dark:bg-slate-900 rounded-xl border border-slate-75 dark:border-slate-700/50 px-6 py-4"
class="flex sm:flex-row flex-col w-full gap-4 sm:gap-14 shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2 px-6 py-5"
>
<SLAMetricCard
:label="$t('SLA_REPORTS.METRICS.HIT_RATE.LABEL')"
@@ -31,18 +31,14 @@ defineProps({
:is-loading="isLoading"
/>
<div
class="w-full sm:w-px h-full border border-slate-75 dark:border-slate-700/50"
/>
<div class="w-full sm:w-px bg-n-strong" />
<SLAMetricCard
:label="$t('SLA_REPORTS.METRICS.NO_OF_MISSES.LABEL')"
:value="noOfBreaches"
:tool-tip="$t('SLA_REPORTS.METRICS.NO_OF_MISSES.TOOLTIP')"
:is-loading="isLoading"
/>
<div
class="w-full sm:w-px h-full border border-slate-75 dark:border-slate-700/50"
/>
<div class="w-full sm:w-px bg-n-strong" />
<SLAMetricCard
:label="$t('SLA_REPORTS.METRICS.NO_OF_CONVERSATIONS.LABEL')"
:value="noOfConversations"

View File

@@ -31,22 +31,23 @@ const conversationLabels = computed(() => {
<template>
<div
class="grid items-center content-center w-full h-16 grid-cols-12 gap-4 px-6 py-0 bg-white border-b last:border-b-0 last:rounded-b-xl border-slate-75 dark:border-slate-800/50 dark:bg-slate-900"
class="grid items-center content-center w-full h-16 grid-cols-12 gap-4 px-6 py-0 border-b last:border-b-0 last:rounded-b-xl border-n-weak"
>
<div
class="flex items-center gap-2 col-span-6 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
>
<span class="text-slate-700 dark:text-slate-200">
<span class="text-n-slate-12">
{{ `#${conversationId} ` }}
</span>
<span class="text-slate-600 dark:text-slate-300">
<span class="text-slate-11">
{{ $t('SLA_REPORTS.WITH') }}
</span>
<span class="capitalize truncate text-slate-700 dark:text-slate-200">{{
<span class="capitalize truncate text-n-slate-12">{{
conversation.contact.name
}}</span>
<CardLabels
class="w-[80%]"
v-if="conversationLabels.length"
class="w-[60%]"
:conversation-id="conversationId"
:conversation-labels="conversationLabels"
/>
@@ -61,7 +62,7 @@ const conversationLabels = computed(() => {
v-if="conversation.assignee"
:user="conversation.assignee"
/>
<span v-else class="text-slate-600 dark:text-slate-200"> --- </span>
<span v-else class="text-n-slate-11"> --- </span>
</div>
<SLAViewDetails :sla-events="slaEvents" />
</div>

View File

@@ -57,10 +57,10 @@ export default {
<template>
<div>
<div
class="min-w-full border rounded-xl border-slate-75 dark:border-slate-700/50"
class="min-w-full shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2 p-6"
>
<div
class="grid content-center h-12 grid-cols-12 gap-4 px-6 py-0 border-b bg-slate-25 border-slate-75 dark:border-slate-800 rounded-t-xl dark:bg-slate-900"
class="grid content-center h-12 grid-cols-12 gap-4 px-6 py-0 bg-n-slate-2 rounded-md"
>
<TableHeaderCell
:span="6"
@@ -74,13 +74,10 @@ export default {
:span="2"
:label="$t('SLA_REPORTS.TABLE.HEADER.AGENT')"
/>
<TableHeaderCell :span="2" label="" />
<TableHeaderCell :span="1" label="" />
</div>
<div
v-if="isLoading"
class="flex items-center justify-center h-32 bg-white rounded-b-xl dark:bg-slate-900"
>
<div v-if="isLoading" class="flex items-center justify-center h-32">
<Spinner />
<span>{{ $t('SLA_REPORTS.LOADING') }}</span>
</div>
@@ -94,10 +91,7 @@ export default {
:sla-events="slaReport.sla_events"
/>
</div>
<div
v-else
class="flex items-center justify-center h-32 bg-white rounded-b-xl dark:bg-slate-900"
>
<div v-else class="flex items-center justify-center h-32">
{{ $t('SLA_REPORTS.NO_RECORDS') }}
</div>
</div>

View File

@@ -29,24 +29,23 @@ export default {
</script>
<template>
<div v-on-clickaway="closeSlaEvents" class="label-wrap">
<div
class="flex items-center col-span-2 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
>
<div class="relative">
<woot-button
color-scheme="secondary"
variant="link"
@click="openSlaEvents"
>
{{ $t('SLA_REPORTS.TABLE.VIEW_DETAILS') }}
</woot-button>
<SLAPopoverCard
v-if="showSlaPopoverCard"
:sla-missed-events="slaEvents"
class="right-0"
/>
</div>
<div
v-on-clickaway="closeSlaEvents"
class="flex items-center col-span-2 text-slate-11 justify-end"
>
<div class="relative">
<woot-button
color-scheme="secondary"
variant="link"
@click="openSlaEvents"
>
{{ $t('SLA_REPORTS.TABLE.VIEW_DETAILS') }}
</woot-button>
<SLAPopoverCard
v-if="showSlaPopoverCard"
:sla-missed-events="slaEvents"
class="right-0"
/>
</div>
</div>
</template>

View File

@@ -1,10 +1,12 @@
<script>
import V4Button from 'dashboard/components-next/button/Button.vue';
import { useAlert, useTrack } from 'dashboard/composables';
import ReportFilters from './ReportFilters.vue';
import ReportContainer from '../ReportContainer.vue';
import { GROUP_BY_FILTER } from '../constants';
import { generateFileName } from '../../../../../helper/downloadHelper';
import { REPORTS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
import ReportHeader from './ReportHeader.vue';
const GROUP_BY_OPTIONS = {
DAY: [{ id: 1, groupByKey: 'REPORT.GROUPING_OPTIONS.DAY' }],
@@ -26,6 +28,8 @@ const GROUP_BY_OPTIONS = {
export default {
components: {
ReportHeader,
V4Button,
ReportFilters,
ReportContainer,
},
@@ -46,6 +50,10 @@ export default {
type: String,
default: 'Download Reports',
},
reportTitle: {
type: String,
default: 'Download Reports',
},
},
data() {
return {
@@ -198,30 +206,29 @@ export default {
</script>
<template>
<div class="flex-1 p-4 overflow-auto">
<woot-button
color-scheme="success"
class-names="button--fixed-top"
icon="arrow-download"
<ReportHeader :header-title="reportTitle">
<V4Button
:label="downloadButtonLabel"
icon="i-ph-download-simple"
size="sm"
@click="downloadReports"
>
{{ downloadButtonLabel }}
</woot-button>
<ReportFilters
v-if="filterItemsList"
:type="type"
:filter-items-list="filterItemsList"
:group-by-filter-items-list="groupByfilterItemsList"
:selected-group-by-filter="selectedGroupByFilter"
@date-range-change="onDateRangeChange"
@filter-change="onFilterChange"
@group-by-filter-change="onGroupByFilterChange"
@business-hours-toggle="onBusinessHoursToggle"
/>
<ReportContainer
v-if="filterItemsList.length"
:group-by="groupBy"
:report-keys="reportKeys"
/>
</div>
</ReportHeader>
<ReportFilters
v-if="filterItemsList"
:type="type"
:filter-items-list="filterItemsList"
:group-by-filter-items-list="groupByfilterItemsList"
:selected-group-by-filter="selectedGroupByFilter"
@date-range-change="onDateRangeChange"
@filter-change="onFilterChange"
@group-by-filter-change="onGroupByFilterChange"
@business-hours-toggle="onBusinessHoursToggle"
/>
<ReportContainer
v-if="filterItemsList.length"
:group-by="groupBy"
:report-keys="reportKeys"
/>
</template>

View File

@@ -144,10 +144,7 @@ const table = useVueTable({
<template>
<div class="agent-table-container">
<Table
:table="table"
class="max-h-[calc(100vh-21.875rem)] border border-slate-50 dark:border-slate-800"
/>
<Table :table="table" class="max-h-[calc(100vh-21.875rem)]" />
<Pagination class="mt-2" :table="table" />
<div v-if="isLoading" class="agents-loader">
<Spinner />
@@ -169,7 +166,7 @@ const table = useVueTable({
.ve-table {
&::v-deep {
th.ve-table-header-th {
font-size: var(--font-size-mini) !important;
@apply text-sm rounded-xl;
padding: var(--space-small) var(--space-two) !important;
}

View File

@@ -25,25 +25,23 @@ export default {
<template>
<div
class="metric-card mb-2 p flex flex-col m-2 p-4 border border-solid overflow-hidden rounded-md flex-grow shadow-sm text-slate-700 dark:text-slate-100 bg-white dark:bg-slate-800 border-slate-75 dark:border-slate-700 min-h-[10rem]"
class="flex flex-col m-0.5 px-6 py-5 overflow-hidden rounded-xl flex-grow text-n-slate-12 shadow outline-1 outline outline-n-container bg-n-solid-2 min-h-[10rem]"
>
<div
class="card-header grid w-full mb-6 grid-cols-[repeat(auto-fit,minmax(max-content,50%))] gap-y-2"
>
<slot name="header">
<div class="flex items-center gap-0.5 flex-row">
<h5
class="mb-0 text-slate-800 dark:text-slate-100 font-medium text-xl"
>
<div class="flex items-center gap-2 flex-row">
<h5 class="mb-0 text-n-slate-12 font-medium text-lg">
{{ header }}
</h5>
<span
class="flex flex-row items-center pr-2 pl-2 m-1 rounded-sm text-green-400 dark:text-green-400 text-xs bg-green-100/30 dark:bg-green-100/20"
class="flex flex-row items-center py-0.5 px-2 rounded bg-n-teal-3 text-xs"
>
<span
class="bg-green-500 dark:bg-green-500 h-1 w-1 rounded-full mr-1 rtl:mr-0 rtl:ml-0"
class="bg-n-teal-9 h-1 w-1 rounded-full mr-1 rtl:mr-0 rtl:ml-0"
/>
<span>
<span class="text-xs text-n-teal-11">
{{ $t('OVERVIEW_REPORTS.LIVE') }}
</span>
</span>
@@ -66,7 +64,7 @@ export default {
class="items-center flex text-base justify-center px-12 py-6"
>
<Spinner />
<span class="text-slate-300 dark:text-slate-200">
<span class="text-n-slate-11">
{{ loadingMessage }}
</span>
</div>

View File

@@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`CsatMetrics.vue > computes response count correctly 1`] = `
"<div class="flex-col lg:flex-row flex flex-wrap mx-0 bg-white dark:bg-slate-800 rounded-[4px] p-4 mb-5 border border-solid border-slate-75 dark:border-slate-700">
"<div class="flex-col lg:flex-row flex flex-wrap mx-0 shadow outline-1 outline outline-n-container rounded-xl bg-n-solid-2 px-6 py-8 gap-4">
<csat-metric-card-stub label="CSAT_REPORTS.METRIC.TOTAL_RESPONSES.LABEL" infotext="CSAT_REPORTS.METRIC.TOTAL_RESPONSES.TOOLTIP" disabled="false" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]" value="100"></csat-metric-card-stub>
<csat-metric-card-stub label="CSAT_REPORTS.METRIC.SATISFACTION_SCORE.LABEL" infotext="CSAT_REPORTS.METRIC.SATISFACTION_SCORE.TOOLTIP" disabled="true" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]" value="--"></csat-metric-card-stub>
<csat-metric-card-stub label="CSAT_REPORTS.METRIC.RESPONSE_RATE.LABEL" infotext="CSAT_REPORTS.METRIC.RESPONSE_RATE.TOOLTIP" disabled="false" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]" value="90%"></csat-metric-card-stub>

View File

@@ -1,7 +1,7 @@
import { frontendURL } from '../../../../helper/URLHelper';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import SettingsContent from '../Wrapper.vue';
import ReportsWrapper from './components/ReportsWrapper.vue';
import Index from './Index.vue';
import AgentReports from './AgentReports.vue';
import LabelReports from './LabelReports.vue';
@@ -16,12 +16,7 @@ export default {
routes: [
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'OVERVIEW_REPORTS.HEADER',
icon: 'arrow-trending-lines',
keepAlive: false,
},
component: ReportsWrapper,
children: [
{
path: '',
@@ -37,17 +32,6 @@ export default {
},
component: LiveReports,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'REPORT.HEADER',
icon: 'chat',
keepAlive: false,
},
children: [
{
path: 'conversation',
name: 'conversation_reports',
@@ -56,56 +40,6 @@ export default {
},
component: Index,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'CSAT_REPORTS.HEADER',
icon: 'emoji',
keepAlive: false,
},
children: [
{
path: 'csat',
name: 'csat_reports',
meta: {
permissions: ['administrator', 'report_manage'],
},
component: CsatResponses,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'BOT_REPORTS.HEADER',
icon: 'bot',
keepAlive: false,
},
children: [
{
path: 'bot',
name: 'bot_reports',
meta: {
permissions: ['administrator', 'report_manage'],
featureFlag: FEATURE_FLAGS.RESPONSE_BOT,
},
component: BotReports,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'AGENT_REPORTS.HEADER',
icon: 'people',
keepAlive: false,
},
children: [
{
path: 'agent',
name: 'agent_reports',
@@ -114,17 +48,6 @@ export default {
},
component: AgentReports,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'LABEL_REPORTS.HEADER',
icon: 'tag',
keepAlive: false,
},
children: [
{
path: 'label',
name: 'label_reports',
@@ -133,17 +56,6 @@ export default {
},
component: LabelReports,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'INBOX_REPORTS.HEADER',
icon: 'mail-inbox-all',
keepAlive: false,
},
children: [
{
path: 'inboxes',
name: 'inbox_reports',
@@ -152,16 +64,6 @@ export default {
},
component: InboxReports,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'TEAM_REPORTS.HEADER',
icon: 'people-team',
},
children: [
{
path: 'teams',
name: 'team_reports',
@@ -170,17 +72,6 @@ export default {
},
component: TeamReports,
},
],
},
{
path: frontendURL('accounts/:accountId/reports'),
component: SettingsContent,
props: {
headerTitle: 'SLA_REPORTS.HEADER',
icon: 'document-list-clock',
keepAlive: false,
},
children: [
{
path: 'sla',
name: 'sla_reports',
@@ -190,6 +81,22 @@ export default {
},
component: SLAReports,
},
{
path: 'csat',
name: 'csat_reports',
meta: {
permissions: ['administrator', 'report_manage'],
},
component: CsatResponses,
},
{
path: 'bot',
name: 'bot_reports',
meta: {
permissions: ['administrator', 'report_manage'],
},
component: BotReports,
},
],
},
],