iachat/app/javascript/dashboard/routes/dashboard/settings/campaigns/AddCampaign.vue
Fayaz Ahmed ce8e1ec93d
chore: Migrate all instances of old vuelidate to new v2 syntax [CW-3274] (#9623)
Removes all the old vuelidate syntax and replaced it with the new
`useValidate` composable and the `v$` helper.

| Component | Path | Migrated | Tested |

|------------------------------------|--------------------------------------------------------------|-----------------------------------------------|--------|
| Login page | app/javascript/v3/views/login/Index.vue |  |  |
| Custom Attributes settings page |
app/javascript/dashboard/components/CustomAttribute.vue |  |  |
| Account settings page |
app/javascript/dashboard/routes/dashboard/settings/account/Index.vue | 
|  |
| Add Account Modal |
app/javascript/dashboard/components/layout/sidebarComponents/AddAccountModal.vue
|  |  |
| AICTA Modal |
app/javascript/dashboard/components/widgets/AICTAModal.vue |  |  |
| Conversation Advanced Filters |
app/javascript/dashboard/components/widgets/conversation/ConversationAdvancedFilter.vue
| deprecated `$each` prop in validations object | |
| Email Transript Modal |
app/javascript/dashboard/components/widgets/conversation/EmailTranscriptModal.vue
|  |  |
| Linear Create Issue |
app/javascript/dashboard/components/widgets/conversation/linear/CreateIssue.vue
|  |  |
| Template Parser |
app/javascript/dashboard/components/widgets/conversation/WhatsappTemplates/TemplateParser.vue
|  | |
| Delete Confirmation Modal |
app/javascript/dashboard/components/widgets/modal/ConfirmDeleteModal.vue
|  |  |
| Add Custom Attribute |
app/javascript/dashboard/modules/contact/components/AddCustomAttribute.vue
|  |  |
| Merge Contacts |
app/javascript/dashboard/modules/contact/components/MergeContact.vue | 
|  |
| Contacts Advanced Filters |
app/javascript/dashboard/routes/dashboard/contacts/components/ContactsAdvancedFilters.vue
| deprecated `$each` prop in validations object | |
| Contact Form |
app/javascript/dashboard/routes/dashboard/conversation/contact/ContactForm.vue
|  |  |
| Conversation Form |
app/javascript/dashboard/routes/dashboard/conversation/contact/ConversationForm.vue
|  |  |
| Add Custom Views |
app/javascript/dashboard/routes/dashboard/customviews/AddCustomViews.vue
|  |  |
| Add Locale |
app/javascript/dashboard/routes/dashboard/helpcenter/components/AddLocale.vue
|  |  |
| Portal Settings Basic Form |
/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue
|  |  |
| Portal Settings Customization Form |
/app/javascript/dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue
|  |  |
| Add Category |
app/javascript/dashboard/routes/dashboard/helpcenter/pages/categories/AddCategory.vue
|  |  |
| Edit Category |
app/javascript/dashboard/routes/dashboard/helpcenter/pages/categories/EditCategory.vue
|  |  |
| CSML Bot Editor |
app/javascript/dashboard/routes/dashboard/settings/agentBots/components/CSMLBotEditor.vue
|  |  |
| Add Agent |
app/javascript/dashboard/routes/dashboard/settings/agents/AddAgent.vue |
 |  |
| Edit Agent |
app/javascript/dashboard/routes/dashboard/settings/agents/EditAgent.vue
|  |  |
| Add Attribute |
app/javascript/dashboard/routes/dashboard/settings/attributes/AddAttribute.vue
|  |  |
| Edit Attribute |
app/javascript/dashboard/routes/dashboard/settings/attributes/EditAttribute.vue
|  |  |
| Add Campaign |
app/javascript/dashboard/routes/dashboard/settings/campaigns/AddCampaign.vue
|  |  |
| Edit Campaign |
app/javascript/dashboard/routes/dashboard/settings/campaigns/EditCampaign.vue
|  |  |
| Add Canned |
app/javascript/dashboard/routes/dashboard/settings/canned/AddCanned.vue
|  |  |
| Edit Canned |
app/javascript/dashboard/routes/dashboard/settings/canned/EditCanned.vue
|  |  |
| IMAP Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/ImapSettings.vue
|  |  |
| SMTP Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/SmtpSettings.vue
|  |  |
| Widget Builder |
app/javascript/dashboard/routes/dashboard/settings/inbox/WidgetBuilder.vue
|  |  |
| 360 Dialog Whatsapp |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/360DialogWhatsapp.vue
|  |  |
| Inbox API settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Api.vue
|  |  |
| SMS Bandwidth settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/BandwidthSms.vue
|  |  |
| Cloud Whatsapp Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/CloudWhatsapp.vue
|  |  |
| Facebook Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Facebook.vue
|  |  |
| Line Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Line.vue
|  |  |
| Telegram Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Telegram.vue
|  |  |
| Twillio Settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Twilio.vue
|  |  |
| Forward To option settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/ForwardToOption.vue
|  |  |
| Microsoft settings |
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/emailChannels/Microsoft.vue
|  |  |
| Collaborators page |
app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/CollaboratorsPage.vue
|  |  |
| Configuration Page |
app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/ConfigurationPage.vue
|  |  |
| Dashboard App Modal Settings |
app/javascript/dashboard/routes/dashboard/settings/integrations/DashboardApps/DashboardAppModal.vue
|  |  |
| Settings - Webhook Form |
app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookForm.vue
|  |  |
| Macro Form |
app/javascript/dashboard/routes/dashboard/settings/macros/MacroForm.vue
| deprecated `$each` prop in validations object | |
| Change Password |
app/javascript/dashboard/routes/dashboard/settings/profile/ChangePassword.vue
|  |  |
| settings - User Basic Details |
app/javascript/dashboard/routes/dashboard/settings/profile/UserBasicDetails.vue
|  |  |
| Password Edit | app/javascript/v3/views/auth/password/Edit.vue |  | 
|
| Password Reset form |
app/javascript/v3/views/auth/reset/password/Index.vue |  |  |
| Signup form |
app/javascript/v3/views/auth/signup/components/Signup/Form.vue |  |  |
| Login form | app/javascript/v3/views/login/Index.vue |  |  |
| Custom Attributes |
app/javascript/dashboard/components/CustomAttribute.vue |  |  |
| Reply Email Head |
app/javascript/dashboard/components/widgets/conversation/ReplyEmailHead.vue
|  |  |
| Methods Mixin |
app/javascript/dashboard/mixins/automations/methodsMixin.js |  |  |
| Validations mixin |
app/javascript/dashboard/routes/dashboard/settings/labels/validationMixin.js
|  |  |
| SLA Form |
app/javascript/dashboard/routes/dashboard/settings/sla/SlaForm.vue |  |
 |
| SLA Time Input |
app/javascript/dashboard/routes/dashboard/settings/sla/SlaTimeInput.vue
|  |  |
| SLA Validation Mixin |
app/javascript/dashboard/routes/dashboard/settings/sla/validationMixin.js
|  |  |
| Team Form |
app/javascript/dashboard/routes/dashboard/settings/teams/TeamForm.vue |
 |  |
| Add Agents |
app/javascript/dashboard/routes/dashboard/settings/teams/Create/AddAgents.vue
|  |  |
| Edit Agents |
app/javascript/dashboard/routes/dashboard/settings/teams/Edit/EditAgents.vue
|  |  |


---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2024-07-30 15:08:22 +05:30

388 lines
11 KiB
Vue

<template>
<div class="flex flex-col h-auto overflow-auto">
<woot-modal-header
:header-title="$t('CAMPAIGN.ADD.TITLE')"
:header-content="$t('CAMPAIGN.ADD.DESC')"
/>
<form class="flex flex-col w-full" @submit.prevent="addCampaign">
<div class="w-full">
<woot-input
v-model="title"
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
type="text"
:class="{ error: v$.title.$error }"
:error="v$.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
@blur="v$.title.$touch"
/>
<div v-if="isOngoingType" class="editor-wrap">
<label>
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
</label>
<div>
<woot-message-editor
v-model="message"
class="message-editor"
:class="{ editor_warning: v$.message.$error }"
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
@blur="v$.message.$touch"
/>
<span v-if="v$.message.$error" class="editor-warning__message">
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
</span>
</div>
</div>
<label v-else :class="{ error: v$.message.$error }">
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
<textarea
v-model="message"
rows="5"
type="text"
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
@blur="v$.message.$touch"
/>
<span v-if="v$.message.$error" class="message">
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
</span>
</label>
<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">
{{ item.name }}
</option>
</select>
<span v-if="v$.selectedInbox.$error" class="message">
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
</span>
</label>
<label
v-if="isOneOffType"
class="multiselect-wrap--small"
:class="{ error: v$.selectedAudience.$error }"
>
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.LABEL') }}
<multiselect
v-model="selectedAudience"
:options="audienceList"
track-by="id"
label="title"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:hide-selected="true"
:placeholder="$t('CAMPAIGN.ADD.FORM.AUDIENCE.PLACEHOLDER')"
selected-label
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
@blur="v$.selectedAudience.$touch"
@select="v$.selectedAudience.$touch"
/>
<span v-if="v$.selectedAudience.$error" class="message">
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.ERROR') }}
</span>
</label>
<label
v-if="isOngoingType"
:class="{ error: v$.selectedSender.$error }"
>
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
<select v-model="selectedSender">
<option
v-for="sender in sendersAndBotList"
:key="sender.name"
:value="sender.id"
>
{{ sender.name }}
</option>
</select>
<span v-if="v$.selectedSender.$error" class="message">
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
</span>
</label>
<label v-if="isOneOffType">
{{ $t('CAMPAIGN.ADD.FORM.SCHEDULED_AT.LABEL') }}
<woot-date-time-picker
:value="scheduledAt"
:confirm-text="$t('CAMPAIGN.ADD.FORM.SCHEDULED_AT.CONFIRM')"
:placeholder="$t('CAMPAIGN.ADD.FORM.SCHEDULED_AT.PLACEHOLDER')"
@change="onChange"
/>
</label>
<woot-input
v-if="isOngoingType"
v-model="endPoint"
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
type="text"
:class="{ error: v$.endPoint.$error }"
:error="
v$.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
"
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
@blur="v$.endPoint.$touch"
/>
<woot-input
v-if="isOngoingType"
v-model="timeOnPage"
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
type="text"
:class="{ error: v$.timeOnPage.$error }"
:error="
v$.timeOnPage.$error
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
: ''
"
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
@blur="v$.timeOnPage.$touch"
/>
<label v-if="isOngoingType">
<input
v-model="enabled"
type="checkbox"
value="enabled"
name="enabled"
/>
{{ $t('CAMPAIGN.ADD.FORM.ENABLED') }}
</label>
<label v-if="isOngoingType">
<input
v-model="triggerOnlyDuringBusinessHours"
type="checkbox"
value="triggerOnlyDuringBusinessHours"
name="triggerOnlyDuringBusinessHours"
/>
{{ $t('CAMPAIGN.ADD.FORM.TRIGGER_ONLY_BUSINESS_HOURS') }}
</label>
</div>
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
<woot-button :is-loading="uiFlags.isCreating">
{{ $t('CAMPAIGN.ADD.CREATE_BUTTON_TEXT') }}
</woot-button>
<woot-button variant="clear" @click.prevent="onClose">
{{ $t('CAMPAIGN.ADD.CANCEL_BUTTON_TEXT') }}
</woot-button>
</div>
</form>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import { useVuelidate } from '@vuelidate/core';
import { required } from '@vuelidate/validators';
import { useAlert } from 'dashboard/composables';
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
import campaignMixin from 'shared/mixins/campaignMixin';
import WootDateTimePicker from 'dashboard/components/ui/DateTimePicker.vue';
import { URLPattern } from 'urlpattern-polyfill';
import { CAMPAIGNS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
export default {
components: {
WootDateTimePicker,
WootMessageEditor,
},
mixins: [campaignMixin],
setup() {
return { v$: useVuelidate() };
},
data() {
return {
title: '',
message: '',
selectedSender: 0,
selectedInbox: null,
endPoint: '',
timeOnPage: 10,
show: true,
enabled: true,
triggerOnlyDuringBusinessHours: false,
scheduledAt: null,
selectedAudience: [],
senderList: [],
};
},
validations() {
const commonValidations = {
title: {
required,
},
message: {
required,
},
selectedInbox: {
required,
},
};
if (this.isOngoingType) {
return {
...commonValidations,
selectedSender: {
required,
},
endPoint: {
required,
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,
},
};
}
return {
...commonValidations,
selectedAudience: {
isEmpty() {
return !!this.selectedAudience.length;
},
},
};
},
computed: {
...mapGetters({
uiFlags: 'campaigns/getUIFlags',
audienceList: 'labels/getLabels',
}),
inboxes() {
if (this.isOngoingType) {
return this.$store.getters['inboxes/getWebsiteInboxes'];
}
return this.$store.getters['inboxes/getSMSInboxes'];
},
sendersAndBotList() {
return [
{
id: 0,
name: 'Bot',
},
...this.senderList,
];
},
},
mounted() {
this.$track(CAMPAIGNS_EVENTS.OPEN_NEW_CAMPAIGN_MODAL, {
type: this.campaignType,
});
},
methods: {
onClose() {
this.$emit('on-close');
},
onChange(value) {
this.scheduledAt = value;
},
async onChangeInbox() {
try {
const response = await this.$store.dispatch('inboxMembers/get', {
inboxId: this.selectedInbox,
});
const {
data: { payload: inboxMembers },
} = response;
this.senderList = inboxMembers;
} catch (error) {
const errorMessage =
error?.response?.message || this.$t('CAMPAIGN.ADD.API.ERROR_MESSAGE');
useAlert(errorMessage);
}
},
getCampaignDetails() {
let campaignDetails = null;
if (this.isOngoingType) {
campaignDetails = {
title: this.title,
message: this.message,
inbox_id: this.selectedInbox,
sender_id: this.selectedSender || null,
enabled: this.enabled,
trigger_only_during_business_hours:
// eslint-disable-next-line prettier/prettier
this.triggerOnlyDuringBusinessHours,
trigger_rules: {
url: this.endPoint,
time_on_page: this.timeOnPage,
},
};
} else {
const audience = this.selectedAudience.map(item => {
return {
id: item.id,
type: 'Label',
};
});
campaignDetails = {
title: this.title,
message: this.message,
inbox_id: this.selectedInbox,
scheduled_at: this.scheduledAt,
audience,
};
}
return campaignDetails;
},
async addCampaign() {
this.v$.$touch();
if (this.v$.$invalid) {
return;
}
try {
const campaignDetails = this.getCampaignDetails();
await this.$store.dispatch('campaigns/create', campaignDetails);
// tracking this here instead of the store to track the type of campaign
this.$track(CAMPAIGNS_EVENTS.CREATE_CAMPAIGN, {
type: this.campaignType,
});
useAlert(this.$t('CAMPAIGN.ADD.API.SUCCESS_MESSAGE'));
this.onClose();
} catch (error) {
const errorMessage =
error?.response?.message || this.$t('CAMPAIGN.ADD.API.ERROR_MESSAGE');
useAlert(errorMessage);
}
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .ProseMirror-woot-style {
height: 5rem;
}
.message-editor {
@apply px-3;
::v-deep {
.ProseMirror-menubar {
@apply rounded-tl-[4px];
}
}
}
</style>