Merge branch 'develop' into feat/github-integration

This commit is contained in:
Muhsin Keloth
2025-06-30 20:55:13 +05:30
committed by GitHub
7 changed files with 67 additions and 41 deletions
@@ -9,20 +9,31 @@ export default {
type: String,
required: true,
},
isComingSoon: {
type: Boolean,
default: false,
},
},
};
</script>
<template>
<button
class="bg-white dark:bg-slate-900 cursor-pointer flex flex-col justify-end transition-all duration-200 ease-in -m-px py-4 px-0 items-center border border-solid border-slate-25 dark:border-slate-800 hover:border-woot-500 dark:hover:border-woot-500 hover:shadow-md hover:z-50 disabled:opacity-60"
class="relative bg-n-background cursor-pointer flex flex-col justify-end transition-all duration-200 ease-in -m-px py-4 px-0 items-center border border-solid border-n-weak hover:border-n-brand hover:shadow-md hover:z-50 disabled:opacity-60"
>
<img :src="src" :alt="title" draggable="false" class="w-1/2 my-4 mx-auto" />
<h3
class="text-slate-800 dark:text-slate-100 text-base text-center capitalize"
>
<h3 class="text-n-slate-12 text-base text-center capitalize">
{{ title }}
</h3>
<div
v-if="isComingSoon"
class="absolute inset-0 flex items-center justify-center backdrop-blur-[2px] rounded-md bg-gradient-to-br from-n-background/90 via-n-background/70 to-n-background/95"
>
<span class="text-n-slate-12 font-medium text-base">
{{ $t('CHANNEL_SELECTOR.COMING_SOON') }} 🚀
</span>
</div>
</button>
</template>
@@ -33,7 +44,7 @@ export default {
}
&:hover {
@apply border-transparent shadow-none cursor-not-allowed;
@apply border-n-strong shadow-none cursor-not-allowed;
}
}
</style>
@@ -57,6 +57,12 @@ export default {
'voice',
].includes(key);
},
isComingSoon() {
const { key } = this.channel;
// Show "Coming Soon" only if the channel is marked as coming soon
// and the corresponding feature flag is not enabled yet.
return ['voice'].includes(key) && !this.isActive;
},
},
methods: {
getChannelThumbnail() {
@@ -79,6 +85,7 @@ export default {
:class="{ inactive: !isActive }"
:title="channel.name"
:src="getChannelThumbnail()"
:is-coming-soon="isComingSoon"
@click="onItemClick"
/>
</template>
@@ -49,5 +49,8 @@
"HOURS": "Hours",
"DAYS": "Days",
"PLACEHOLDER": "Enter duration"
},
"CHANNEL_SELECTOR": {
"COMING_SOON": "Coming Soon!"
}
}
@@ -61,7 +61,7 @@ const defaultSpanRender = cellProps => {
const columnHelper = createColumnHelper();
const columns = [
const columns = computed(() => [
columnHelper.accessor('contact', {
header: t('CSAT_REPORTS.TABLE.HEADER.CONTACT_NAME'),
width: 200,
@@ -121,7 +121,7 @@ const columns = [
width: 100,
cell: cellProps => h(ConversationCell, cellProps),
}),
];
]);
const paginationParams = computed(() => {
return {
@@ -134,7 +134,9 @@ const table = useVueTable({
get data() {
return tableData.value;
},
columns,
get columns() {
return columns.value;
},
manualPagination: true,
enableSorting: false,
getCoreRowModel: getCoreRowModel(),
@@ -1,28 +1,33 @@
<script>
<script setup>
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { DATE_RANGE_OPTIONS } from '../../constants';
const EVENT_NAME = 'on-range-change';
const emit = defineEmits(['onRangeChange']);
export default {
name: 'ReportFiltersDateRange',
data() {
const translatedOptions = Object.values(DATE_RANGE_OPTIONS).map(option => ({
...option,
name: this.$t(option.translationKey),
}));
const { t } = useI18n();
return {
// relies on translations, need to move it to constants
selectedOption: translatedOptions[0],
options: translatedOptions,
};
const options = computed(() =>
Object.values(DATE_RANGE_OPTIONS).map(option => ({
...option,
name: t(option.translationKey),
}))
);
const selectedId = ref(Object.values(DATE_RANGE_OPTIONS)[0].id);
const selectedOption = computed({
get() {
return options.value.find(o => o.id === selectedId.value);
},
methods: {
updateRange(selectedRange) {
this.selectedOption = selectedRange;
this.$emit(EVENT_NAME, selectedRange);
},
set(val) {
selectedId.value = val.id;
},
});
const updateRange = range => {
selectedOption.value = range;
emit('onRangeChange', range);
};
</script>
@@ -31,7 +36,7 @@ export default {
<multiselect
v-model="selectedOption"
class="no-margin"
track-by="name"
track-by="id"
label="name"
:placeholder="$t('FORMS.MULTISELECT.SELECT_ONE')"
selected-label
@@ -12,33 +12,30 @@ const mountParams = {
};
describe('ReportFiltersDateRange.vue', () => {
it('emits "on-range-change" event when updateRange is called', () => {
it('emits "onRangeChange" event when updateRange is called', () => {
const wrapper = shallowMount(ReportFiltersDateRange, mountParams);
const selectedRange = DATE_RANGE_OPTIONS.LAST_7_DAYS;
wrapper.vm.updateRange(selectedRange);
expect(wrapper.emitted('on-range-change')).toBeTruthy();
expect(wrapper.emitted('on-range-change')[0]).toEqual([selectedRange]);
expect(wrapper.emitted('onRangeChange')).toBeTruthy();
expect(wrapper.emitted('onRangeChange')[0]).toEqual([selectedRange]);
});
it('initializes options correctly', () => {
const wrapper = shallowMount(ReportFiltersDateRange, mountParams);
const expectedOptions = Object.values(DATE_RANGE_OPTIONS).map(option => ({
...option,
name: option.translationKey,
}));
const expectedIds = Object.values(DATE_RANGE_OPTIONS).map(
option => option.id
);
const receivedIds = wrapper.vm.options.map(option => option.id);
expect(wrapper.vm.options).toEqual(expectedOptions);
expect(receivedIds).toEqual(expectedIds);
});
it('initializes selectedOption correctly', () => {
const wrapper = shallowMount(ReportFiltersDateRange, mountParams);
const expectedSelectedOption = Object.values(DATE_RANGE_OPTIONS)[0];
expect(wrapper.vm.selectedOption).toEqual({
...expectedSelectedOption,
name: expectedSelectedOption.translationKey,
});
const expectedId = Object.values(DATE_RANGE_OPTIONS)[0].id;
expect(wrapper.vm.selectedOption.id).toBe(expectedId);
});
});