feat: Allow wildcard URL in the campaigns (#6056)

This commit is contained in:
Pranav Raj S
2022-12-09 16:43:09 -08:00
committed by GitHub
parent 6200559123
commit 823c836906
8 changed files with 104 additions and 19 deletions

View File

@@ -171,11 +171,12 @@
<script>
import { mapGetters } from 'vuex';
import { required, url, minLength } from 'vuelidate/lib/validators';
import { required } from 'vuelidate/lib/validators';
import alertMixin from 'shared/mixins/alertMixin';
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor';
import campaignMixin from 'shared/mixins/campaignMixin';
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
import { URLPattern } from 'urlpattern-polyfill';
export default {
components: {
@@ -221,8 +222,23 @@ export default {
},
endPoint: {
required,
minLength: minLength(7),
url,
shouldBeAValidURLPattern(value) {
try {
// eslint-disable-next-line
new URLPattern(value);
return true;
} catch (error) {
return false;
}
},
shouldStartWithHTTP(value) {
if (value) {
return (
value.startsWith('https://') || value.startsWith('http://')
);
}
return false;
},
},
timeOnPage: {
required,

View File

@@ -30,7 +30,7 @@
<label :class="{ error: $v.selectedInbox.$error }">
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
<select v-model="selectedInbox" @change="onChangeInbox($event)">
<option v-for="item in inboxes" :key="item.name" :value="item.id">
<option v-for="item in inboxes" :key="item.id" :value="item.id">
{{ item.name }}
</option>
</select>
@@ -111,10 +111,12 @@
<script>
import { mapGetters } from 'vuex';
import { required, url, minLength } from 'vuelidate/lib/validators';
import { required } from 'vuelidate/lib/validators';
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor';
import alertMixin from 'shared/mixins/alertMixin';
import campaignMixin from 'shared/mixins/campaignMixin';
import { URLPattern } from 'urlpattern-polyfill';
export default {
components: {
WootMessageEditor,
@@ -152,8 +154,21 @@ export default {
},
endPoint: {
required,
minLength: minLength(7),
url,
shouldBeAValidURLPattern(value) {
try {
// eslint-disable-next-line
new URLPattern(value);
return true;
} catch (error) {
return false;
}
},
shouldStartWithHTTP(value) {
if (value) {
return value.startsWith('https://') || value.startsWith('http://');
}
return false;
},
},
timeOnPage: {
required,

View File

@@ -14,6 +14,12 @@
<div v-if="error" class="text-red-400 mt-2 text-xs font-medium">
{{ error }}
</div>
<div
v-if="!error && helpText"
class="text-red-400 mt-2 text-xs font-medium"
>
{{ helpText }}
</div>
</label>
</template>
<script>
@@ -41,6 +47,10 @@ export default {
type: String,
default: '',
},
helpText: {
type: String,
default: '',
},
},
computed: {
labelClass() {

View File

@@ -1,5 +1,19 @@
export const stripTrailingSlash = ({ URL }) => {
return URL.replace(/\/$/, '');
import { URLPattern } from 'urlpattern-polyfill';
export const isPatternMatchingWithURL = (urlPattern, url) => {
let updatedUrlPattern = urlPattern;
const locationObj = new URL(url);
if (updatedUrlPattern.endsWith('/')) {
updatedUrlPattern = updatedUrlPattern.slice(0, -1) + '*\\?*\\#*';
}
if (locationObj.pathname.endsWith('/')) {
locationObj.pathname = locationObj.pathname.slice(0, -1);
}
const pattern = new URLPattern(updatedUrlPattern);
return pattern.test(locationObj.toString());
};
// Format all campaigns
@@ -22,10 +36,7 @@ export const filterCampaigns = ({
isInBusinessHours,
}) => {
return campaigns.filter(campaign => {
const hasMatchingURL =
stripTrailingSlash({ URL: campaign.url }) ===
stripTrailingSlash({ URL: currentURL });
if (!hasMatchingURL) {
if (!isPatternMatchingWithURL(campaign.url, currentURL)) {
return false;
}
if (campaign.triggerOnlyDuringBusinessHours) {

View File

@@ -1,7 +1,7 @@
import {
stripTrailingSlash,
formatCampaigns,
filterCampaigns,
isPatternMatchingWithURL,
} from '../campaignHelper';
import campaigns from './campaignFixtures';
@@ -9,11 +9,35 @@ global.chatwootWebChannel = {
workingHoursEnabled: false,
};
describe('#Campaigns Helper', () => {
describe('stripTrailingSlash', () => {
it('should return striped trailing slash if url with trailing slash is passed', () => {
describe('#isPatternMatchingWithURL', () => {
it('returns correct value if a valid URL is passed', () => {
expect(
stripTrailingSlash({ URL: 'https://www.chatwoot.com/pricing/' })
).toBe('https://www.chatwoot.com/pricing');
isPatternMatchingWithURL(
'https://chatwoot.com/pricing*',
'https://chatwoot.com/pricing/'
)
).toBe(true);
expect(
isPatternMatchingWithURL(
'https://*.chatwoot.com/pricing/',
'https://app.chatwoot.com/pricing/'
)
).toBe(true);
expect(
isPatternMatchingWithURL(
'https://{*.}?chatwoot.com/pricing?test=true',
'https://app.chatwoot.com/pricing/?test=true'
)
).toBe(true);
expect(
isPatternMatchingWithURL(
'https://{*.}?chatwoot.com/pricing*\\?*',
'https://chatwoot.com/pricing/?test=true'
)
).toBe(true);
});
});