chore: Replace campaign mixin with composable [CW-3463] (#9987)
# Pull Request Template ## Description Repalces campaignMixin and its usage with the new useCampaign mixin Fixes https://linear.app/chatwoot/issue/CW-3463/rewrite-campaignmixin-mixin-to-a-composable --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { useVuelidate } from '@vuelidate/core';
|
|||||||
import { required } from '@vuelidate/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import { useCampaign } from 'shared/composables/useCampaign';
|
||||||
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
|
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
|
||||||
import { URLPattern } from 'urlpattern-polyfill';
|
import { URLPattern } from 'urlpattern-polyfill';
|
||||||
import { CAMPAIGNS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
import { CAMPAIGNS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||||
@@ -14,9 +14,9 @@ export default {
|
|||||||
WootDateTimePicker,
|
WootDateTimePicker,
|
||||||
WootMessageEditor,
|
WootMessageEditor,
|
||||||
},
|
},
|
||||||
mixins: [campaignMixin],
|
|
||||||
setup() {
|
setup() {
|
||||||
return { v$: useVuelidate() };
|
const { campaignType, isOngoingType, isOneOffType } = useCampaign();
|
||||||
|
return { v$: useVuelidate(), campaignType, isOngoingType, isOneOffType };
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import { useCampaign } from 'shared/composables/useCampaign';
|
||||||
import CampaignsTable from './CampaignsTable.vue';
|
import CampaignsTable from './CampaignsTable.vue';
|
||||||
import EditCampaign from './EditCampaign.vue';
|
import EditCampaign from './EditCampaign.vue';
|
||||||
export default {
|
export default {
|
||||||
@@ -9,13 +9,16 @@ export default {
|
|||||||
CampaignsTable,
|
CampaignsTable,
|
||||||
EditCampaign,
|
EditCampaign,
|
||||||
},
|
},
|
||||||
mixins: [campaignMixin],
|
|
||||||
props: {
|
props: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const { campaignType } = useCampaign();
|
||||||
|
return { campaignType };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showEditPopup: false,
|
showEditPopup: false,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Spinner from 'shared/components/Spinner.vue';
|
import Spinner from 'shared/components/Spinner.vue';
|
||||||
import EmptyState from 'dashboard/components/widgets/EmptyState.vue';
|
import EmptyState from 'dashboard/components/widgets/EmptyState.vue';
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import { useCampaign } from 'shared/composables/useCampaign';
|
||||||
import CampaignCard from './CampaignCard.vue';
|
import CampaignCard from './CampaignCard.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -10,9 +10,6 @@ export default {
|
|||||||
Spinner,
|
Spinner,
|
||||||
CampaignCard,
|
CampaignCard,
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [campaignMixin],
|
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
campaigns: {
|
campaigns: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@@ -27,7 +24,10 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const { isOngoingType } = useCampaign();
|
||||||
|
return { isOngoingType };
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentInboxId() {
|
currentInboxId() {
|
||||||
return this.$route.params.inboxId;
|
return this.$route.params.inboxId;
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ import { useVuelidate } from '@vuelidate/core';
|
|||||||
import { required } from '@vuelidate/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import { useCampaign } from 'shared/composables/useCampaign';
|
||||||
import { URLPattern } from 'urlpattern-polyfill';
|
import { URLPattern } from 'urlpattern-polyfill';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
WootMessageEditor,
|
WootMessageEditor,
|
||||||
},
|
},
|
||||||
mixins: [campaignMixin],
|
|
||||||
props: {
|
props: {
|
||||||
selectedCampaign: {
|
selectedCampaign: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -19,7 +18,8 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return { v$: useVuelidate() };
|
const { isOngoingType } = useCampaign();
|
||||||
|
return { v$: useVuelidate(), isOngoingType };
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import campaignMixin from 'shared/mixins/campaignMixin';
|
import { useCampaign } from 'shared/composables/useCampaign';
|
||||||
import Campaign from './Campaign.vue';
|
import Campaign from './Campaign.vue';
|
||||||
import AddCampaign from './AddCampaign.vue';
|
import AddCampaign from './AddCampaign.vue';
|
||||||
|
|
||||||
@@ -8,7 +8,10 @@ export default {
|
|||||||
Campaign,
|
Campaign,
|
||||||
AddCampaign,
|
AddCampaign,
|
||||||
},
|
},
|
||||||
mixins: [campaignMixin],
|
setup() {
|
||||||
|
const { isOngoingType } = useCampaign();
|
||||||
|
return { isOngoingType };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return { showAddPopup: false };
|
return { showAddPopup: false };
|
||||||
},
|
},
|
||||||
|
|||||||
47
app/javascript/shared/composables/specs/useCampaign.spec.js
Normal file
47
app/javascript/shared/composables/specs/useCampaign.spec.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
import { useCampaign } from '../useCampaign';
|
||||||
|
import { useRoute } from 'dashboard/composables/route';
|
||||||
|
import { CAMPAIGN_TYPES } from '../../constants/campaign';
|
||||||
|
|
||||||
|
// Mock the useRoute composable
|
||||||
|
vi.mock('dashboard/composables/route', () => ({
|
||||||
|
useRoute: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('useCampaign', () => {
|
||||||
|
it('returns the correct campaign type for ongoing campaigns', () => {
|
||||||
|
useRoute.mockReturnValue({ name: 'ongoing_campaigns' });
|
||||||
|
const { campaignType } = useCampaign();
|
||||||
|
expect(campaignType.value).toBe(CAMPAIGN_TYPES.ONGOING);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the correct campaign type for one-off campaigns', () => {
|
||||||
|
useRoute.mockReturnValue({ name: 'one_off' });
|
||||||
|
const { campaignType } = useCampaign();
|
||||||
|
expect(campaignType.value).toBe(CAMPAIGN_TYPES.ONE_OFF);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isOngoingType returns true for ongoing campaigns', () => {
|
||||||
|
useRoute.mockReturnValue({ name: 'ongoing_campaigns' });
|
||||||
|
const { isOngoingType } = useCampaign();
|
||||||
|
expect(isOngoingType.value).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isOngoingType returns false for one-off campaigns', () => {
|
||||||
|
useRoute.mockReturnValue({ name: 'one_off' });
|
||||||
|
const { isOngoingType } = useCampaign();
|
||||||
|
expect(isOngoingType.value).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isOneOffType returns true for one-off campaigns', () => {
|
||||||
|
useRoute.mockReturnValue({ name: 'one_off' });
|
||||||
|
const { isOneOffType } = useCampaign();
|
||||||
|
expect(isOneOffType.value).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('isOneOffType returns false for ongoing campaigns', () => {
|
||||||
|
useRoute.mockReturnValue({ name: 'ongoing_campaigns' });
|
||||||
|
const { isOneOffType } = useCampaign();
|
||||||
|
expect(isOneOffType.value).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
43
app/javascript/shared/composables/useCampaign.js
Normal file
43
app/javascript/shared/composables/useCampaign.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { computed } from 'vue';
|
||||||
|
import { useRoute } from 'dashboard/composables/route';
|
||||||
|
import { CAMPAIGN_TYPES } from '../constants/campaign';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composable to manage campaign types.
|
||||||
|
*
|
||||||
|
* @returns {Object} - Computed properties for campaign type and its checks.
|
||||||
|
*/
|
||||||
|
export const useCampaign = () => {
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed property to determine the current campaign type based on the route name.
|
||||||
|
*/
|
||||||
|
const campaignType = computed(() => {
|
||||||
|
const campaignTypeMap = {
|
||||||
|
ongoing_campaigns: CAMPAIGN_TYPES.ONGOING,
|
||||||
|
one_off: CAMPAIGN_TYPES.ONE_OFF,
|
||||||
|
};
|
||||||
|
return campaignTypeMap[route.name];
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed property to check if the current campaign type is 'ongoing'.
|
||||||
|
*/
|
||||||
|
const isOngoingType = computed(() => {
|
||||||
|
return campaignType.value === CAMPAIGN_TYPES.ONGOING;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed property to check if the current campaign type is 'one-off'.
|
||||||
|
*/
|
||||||
|
const isOneOffType = computed(() => {
|
||||||
|
return campaignType.value === CAMPAIGN_TYPES.ONE_OFF;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
campaignType,
|
||||||
|
isOngoingType,
|
||||||
|
isOneOffType,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { CAMPAIGN_TYPES } from '../constants/campaign';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
computed: {
|
|
||||||
campaignType() {
|
|
||||||
const campaignTypeMap = {
|
|
||||||
ongoing_campaigns: CAMPAIGN_TYPES.ONGOING,
|
|
||||||
one_off: CAMPAIGN_TYPES.ONE_OFF,
|
|
||||||
};
|
|
||||||
return campaignTypeMap[this.$route.name];
|
|
||||||
},
|
|
||||||
isOngoingType() {
|
|
||||||
return this.campaignType === CAMPAIGN_TYPES.ONGOING;
|
|
||||||
},
|
|
||||||
isOneOffType() {
|
|
||||||
return this.campaignType === CAMPAIGN_TYPES.ONE_OFF;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { shallowMount } from '@vue/test-utils';
|
|
||||||
import campaignMixin from '../campaignMixin';
|
|
||||||
|
|
||||||
const buildComponent = routeName => ({
|
|
||||||
template: '<div></div>',
|
|
||||||
computed: {
|
|
||||||
$route() {
|
|
||||||
return { name: routeName };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mixins: [campaignMixin],
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('campaignMixin', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
global.window = Object.create(window);
|
|
||||||
});
|
|
||||||
it('returns the correct campaign type', () => {
|
|
||||||
const Component = buildComponent('one_off');
|
|
||||||
const wrapper = shallowMount(Component);
|
|
||||||
expect(wrapper.vm.campaignType).toBe('one_off');
|
|
||||||
});
|
|
||||||
it('isOneOffType returns true if path is one_off', () => {
|
|
||||||
const Component = buildComponent('one_off');
|
|
||||||
const wrapper = shallowMount(Component);
|
|
||||||
expect(wrapper.vm.isOneOffType).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('isOngoingType returns true if path is ongoing_campaigns', () => {
|
|
||||||
const Component = buildComponent('ongoing_campaigns');
|
|
||||||
const wrapper = shallowMount(Component);
|
|
||||||
expect(wrapper.vm.isOngoingType).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user