fix: Trigger campaigns only during business hours (#3085)

Fixes #2433
This commit is contained in:
Muhsin Keloth
2021-10-12 17:58:33 +05:30
committed by GitHub
parent 7c21cf2255
commit 6bfa551c85
16 changed files with 142 additions and 38 deletions

View File

@@ -19,12 +19,14 @@ import Router from './views/Router';
import { getLocale } from './helpers/urlParamsHelper';
import { BUS_EVENTS } from 'shared/constants/busEvents';
import { isEmptyObject } from 'widget/helpers/utils';
import availabilityMixin from 'widget/mixins/availability';
export default {
name: 'App',
components: {
Router,
},
mixins: [availabilityMixin],
data() {
return {
showUnreadView: false,
@@ -219,7 +221,11 @@ export default {
this.scrollConversationToBottom();
} else if (message.event === 'change-url') {
const { referrerURL, referrerHost } = message;
this.initCampaigns({ currentURL: referrerURL, websiteToken });
this.initCampaigns({
currentURL: referrerURL,
websiteToken,
isInBusinessHours: this.isInBusinessHours,
});
window.referrerURL = referrerURL;
bus.$emit(BUS_EVENTS.SET_REFERRER_HOST, referrerHost);
} else if (message.event === 'toggle-close-button') {

View File

@@ -7,17 +7,24 @@ export const formatCampaigns = ({ campaigns }) => {
return campaigns.map(item => {
return {
id: item.id,
triggerOnlyDuringBusinessHours:
item.trigger_only_during_business_hours || false,
timeOnPage: item?.trigger_rules?.time_on_page,
url: item?.trigger_rules?.url,
};
});
};
// Find all campaigns that matches the current URL
export const filterCampaigns = ({ campaigns, currentURL }) => {
return campaigns.filter(
item =>
stripTrailingSlash({ URL: item.url }) ===
stripTrailingSlash({ URL: currentURL })
// Filter all campaigns based on current URL and business availability time
export const filterCampaigns = ({
campaigns,
currentURL,
isInBusinessHours,
}) => {
return campaigns.filter(item =>
item.triggerOnlyDuringBusinessHours
? isInBusinessHours
: stripTrailingSlash({ URL: item.url }) ===
stripTrailingSlash({ URL: currentURL })
);
};

View File

@@ -1,6 +1,7 @@
export default [
{
id: 1,
trigger_only_during_business_hours: false,
trigger_rules: {
time_on_page: 3,
url: 'https://www.chatwoot.com/pricing',
@@ -8,6 +9,7 @@ export default [
},
{
id: 2,
trigger_only_during_business_hours: false,
trigger_rules: {
time_on_page: 6,
url: 'https://www.chatwoot.com/about',

View File

@@ -3,8 +3,12 @@ import {
formatCampaigns,
filterCampaigns,
} from '../campaignHelper';
import campaigns from './camapginFixtures';
describe('#Campagin Helper', () => {
import campaigns from './campaignFixtures';
global.chatwootWebChannel = {
workingHoursEnabled: false,
};
describe('#Campaigns Helper', () => {
describe('stripTrailingSlash', () => {
it('should return striped trailing slash if url with trailing slash is passed', () => {
expect(
@@ -14,15 +18,17 @@ describe('#Campagin Helper', () => {
});
describe('formatCampaigns', () => {
it('should return formated campaigns if camapgins are passed', () => {
it('should return formatted campaigns if campaigns are passed', () => {
expect(formatCampaigns({ campaigns })).toStrictEqual([
{
id: 1,
timeOnPage: 3,
triggerOnlyDuringBusinessHours: false,
url: 'https://www.chatwoot.com/pricing',
},
{
id: 2,
triggerOnlyDuringBusinessHours: false,
timeOnPage: 6,
url: 'https://www.chatwoot.com/about',
},
@@ -30,7 +36,7 @@ describe('#Campagin Helper', () => {
});
});
describe('filterCampaigns', () => {
it('should return filtered campaigns if formatted camapgins are passed', () => {
it('should return filtered campaigns if formatted campaigns are passed', () => {
expect(
filterCampaigns({
campaigns: [

View File

@@ -58,5 +58,9 @@ export default {
closeMinute: workingHourConfig.close_minutes,
};
},
isInBusinessHours() {
const { workingHoursEnabled } = window.chatwootWebChannel;
return workingHoursEnabled ? this.isInBetweenTheWorkingHours : true;
},
},
};

View File

@@ -14,12 +14,18 @@ const state = {
activeCampaign: {},
};
const resetCampaignTimers = (campaigns, currentURL, websiteToken) => {
const resetCampaignTimers = (
campaigns,
currentURL,
websiteToken,
isInBusinessHours
) => {
const formattedCampaigns = formatCampaigns({ campaigns });
// Find all campaigns that matches the current URL
const filteredCampaigns = filterCampaigns({
campaigns: formattedCampaigns,
currentURL,
isInBusinessHours,
});
campaignTimer.initTimers({ campaigns: filteredCampaigns }, websiteToken);
};
@@ -31,13 +37,21 @@ export const getters = {
};
export const actions = {
fetchCampaigns: async ({ commit }, { websiteToken, currentURL }) => {
fetchCampaigns: async (
{ commit },
{ websiteToken, currentURL, isInBusinessHours }
) => {
try {
const { data: campaigns } = await getCampaigns(websiteToken);
commit('setCampaigns', campaigns);
commit('setError', false);
commit('setHasFetched', true);
resetCampaignTimers(campaigns, currentURL, websiteToken);
resetCampaignTimers(
campaigns,
currentURL,
websiteToken,
isInBusinessHours
);
} catch (error) {
commit('setError', true);
commit('setHasFetched', true);
@@ -45,12 +59,21 @@ export const actions = {
},
initCampaigns: async (
{ getters: { getCampaigns: campaigns }, dispatch },
{ currentURL, websiteToken }
{ currentURL, websiteToken, isInBusinessHours }
) => {
if (!campaigns.length) {
dispatch('fetchCampaigns', { websiteToken, currentURL });
dispatch('fetchCampaigns', {
websiteToken,
currentURL,
isInBusinessHours,
});
} else {
resetCampaignTimers(campaigns, currentURL, websiteToken);
resetCampaignTimers(
campaigns,
currentURL,
websiteToken,
isInBusinessHours
);
}
},
startCampaign: async ({ commit }, { websiteToken, campaignId }) => {

View File

@@ -15,7 +15,11 @@ describe('#actions', () => {
API.get.mockResolvedValue({ data: campaigns });
await actions.fetchCampaigns(
{ commit },
{ websiteToken: 'XDsafmADasd', currentURL: 'https://chatwoot.com' }
{
websiteToken: 'XDsafmADasd',
currentURL: 'https://chatwoot.com',
isInBusinessHours: true,
}
);
expect(commit.mock.calls).toEqual([
['setCampaigns', campaigns],
@@ -25,7 +29,12 @@ describe('#actions', () => {
expect(campaignTimer.initTimers).toHaveBeenCalledWith(
{
campaigns: [
{ id: 11, timeOnPage: '20', url: 'https://chatwoot.com' },
{
id: 11,
timeOnPage: '20',
url: 'https://chatwoot.com',
triggerOnlyDuringBusinessHours: false,
},
],
},
'XDsafmADasd'
@@ -35,7 +44,11 @@ describe('#actions', () => {
API.get.mockRejectedValue({ message: 'Authentication required' });
await actions.fetchCampaigns(
{ commit },
{ websiteToken: 'XDsafmADasd', currentURL: 'https://www.chatwoot.com' }
{
websiteToken: 'XDsafmADasd',
currentURL: 'https://www.chatwoot.com',
isInBusinessHours: true,
}
);
expect(commit.mock.calls).toEqual([
['setError', true],
@@ -65,7 +78,12 @@ describe('#actions', () => {
expect(campaignTimer.initTimers).toHaveBeenCalledWith(
{
campaigns: [
{ id: 11, timeOnPage: '20', url: 'https://chatwoot.com' },
{
id: 11,
timeOnPage: '20',
url: 'https://chatwoot.com',
triggerOnlyDuringBusinessHours: false,
},
],
},
'XDsafmADasd'