mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 19:48:08 +00:00
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>
This commit is contained in:
@@ -2,7 +2,6 @@ import { addDecorator } from '@storybook/vue';
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import VueI18n from 'vue-i18n';
|
import VueI18n from 'vue-i18n';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import Multiselect from 'vue-multiselect';
|
import Multiselect from 'vue-multiselect';
|
||||||
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
||||||
import FluentIcon from 'shared/components/FluentIcon/DashboardIcon';
|
import FluentIcon from 'shared/components/FluentIcon/DashboardIcon';
|
||||||
@@ -14,7 +13,6 @@ import { domPurifyConfig } from 'shared/helpers/HTMLSanitizer';
|
|||||||
import '../app/javascript/dashboard/assets/scss/storybook.scss';
|
import '../app/javascript/dashboard/assets/scss/storybook.scss';
|
||||||
|
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
Vue.use(Vuelidate);
|
|
||||||
Vue.use(WootUiKit);
|
Vue.use(WootUiKit);
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
||||||
@@ -32,7 +30,7 @@ addDecorator(() => ({
|
|||||||
template: '<story/>',
|
template: '<story/>',
|
||||||
i18n: i18nConfig,
|
i18n: i18nConfig,
|
||||||
store,
|
store,
|
||||||
beforeCreate: function() {
|
beforeCreate: function () {
|
||||||
this.$root._i18n = this.$i18n;
|
this.$root._i18n = this.$i18n;
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<span
|
<span
|
||||||
class="w-full inline-flex gap-1.5 items-start font-medium whitespace-nowrap text-sm mb-0"
|
class="w-full inline-flex gap-1.5 items-start font-medium whitespace-nowrap text-sm mb-0"
|
||||||
:class="
|
:class="
|
||||||
$v.editedValue.$error
|
v$.editedValue.$error
|
||||||
? 'text-red-400 dark:text-red-500'
|
? 'text-red-400 dark:text-red-500'
|
||||||
: 'text-slate-800 dark:text-slate-100'
|
: 'text-slate-800 dark:text-slate-100'
|
||||||
"
|
"
|
||||||
@@ -48,8 +48,8 @@
|
|||||||
:type="inputType"
|
:type="inputType"
|
||||||
class="!h-8 ltr:!rounded-r-none rtl:!rounded-l-none !mb-0 !text-sm"
|
class="!h-8 ltr:!rounded-r-none rtl:!rounded-l-none !mb-0 !text-sm"
|
||||||
autofocus="true"
|
autofocus="true"
|
||||||
:class="{ error: $v.editedValue.$error }"
|
:class="{ error: v$.editedValue.$error }"
|
||||||
@blur="$v.editedValue.$touch"
|
@blur="v$.editedValue.$touch"
|
||||||
@keyup.enter="onUpdate"
|
@keyup.enter="onUpdate"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
@@ -136,12 +136,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { format, parseISO } from 'date-fns';
|
import { format, parseISO } from 'date-fns';
|
||||||
import { required, url } from 'vuelidate/lib/validators';
|
import { required, url } from '@vuelidate/validators';
|
||||||
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||||
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
||||||
import HelperTextPopup from 'dashboard/components/ui/HelperTextPopup.vue';
|
import HelperTextPopup from 'dashboard/components/ui/HelperTextPopup.vue';
|
||||||
import { isValidURL } from '../helper/URLHelper';
|
import { isValidURL } from '../helper/URLHelper';
|
||||||
import customAttributeMixin from '../mixins/customAttributeMixin';
|
import customAttributeMixin from '../mixins/customAttributeMixin';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
const DATE_FORMAT = 'yyyy-MM-dd';
|
const DATE_FORMAT = 'yyyy-MM-dd';
|
||||||
|
|
||||||
@@ -167,6 +168,9 @@ export default {
|
|||||||
attributeKey: { type: String, required: true },
|
attributeKey: { type: String, required: true },
|
||||||
contactId: { type: Number, default: null },
|
contactId: { type: Number, default: null },
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
@@ -225,13 +229,13 @@ export default {
|
|||||||
return this.isAttributeTypeLink ? 'url' : this.attributeType;
|
return this.isAttributeTypeLink ? 'url' : this.attributeType;
|
||||||
},
|
},
|
||||||
shouldShowErrorMessage() {
|
shouldShowErrorMessage() {
|
||||||
return this.$v.editedValue.$error;
|
return this.v$.editedValue.$error;
|
||||||
},
|
},
|
||||||
errorMessage() {
|
errorMessage() {
|
||||||
if (this.$v.editedValue.url) {
|
if (this.v$.editedValue.url) {
|
||||||
return this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_URL');
|
return this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_URL');
|
||||||
}
|
}
|
||||||
if (!this.$v.editedValue.regexValidation) {
|
if (!this.v$.editedValue.regexValidation) {
|
||||||
return this.regexCue
|
return this.regexCue
|
||||||
? this.regexCue
|
? this.regexCue
|
||||||
: this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_INPUT');
|
: this.$t('CUSTOM_ATTRIBUTES.VALIDATIONS.INVALID_INPUT');
|
||||||
@@ -246,7 +250,7 @@ export default {
|
|||||||
},
|
},
|
||||||
contactId() {
|
contactId() {
|
||||||
// Fix to solve validation not resetting when contactId changes in contact page
|
// Fix to solve validation not resetting when contactId changes in contact page
|
||||||
this.$v.$reset();
|
this.v$.$reset();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -287,7 +291,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClickAway() {
|
onClickAway() {
|
||||||
this.$v.$reset();
|
this.v$.$reset();
|
||||||
this.isEditing = false;
|
this.isEditing = false;
|
||||||
},
|
},
|
||||||
onEdit() {
|
onEdit() {
|
||||||
@@ -307,8 +311,8 @@ export default {
|
|||||||
this.attributeType === 'date'
|
this.attributeType === 'date'
|
||||||
? parseISO(this.editedValue)
|
? parseISO(this.editedValue)
|
||||||
: this.editedValue;
|
: this.editedValue;
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isEditing = false;
|
this.isEditing = false;
|
||||||
@@ -316,7 +320,7 @@ export default {
|
|||||||
},
|
},
|
||||||
onDelete() {
|
onDelete() {
|
||||||
this.isEditing = false;
|
this.isEditing = false;
|
||||||
this.$v.$reset();
|
this.v$.$reset();
|
||||||
this.$emit('delete', this.attributeKey);
|
this.$emit('delete', this.attributeKey);
|
||||||
},
|
},
|
||||||
onCopy() {
|
onCopy() {
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
|
|
||||||
<form class="flex flex-col w-full" @submit.prevent="addAccount">
|
<form class="flex flex-col w-full" @submit.prevent="addAccount">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.accountName.$error }">
|
<label :class="{ error: v$.accountName.$error }">
|
||||||
{{ $t('CREATE_ACCOUNT.FORM.NAME.LABEL') }}
|
{{ $t('CREATE_ACCOUNT.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="accountName"
|
v-model.trim="accountName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CREATE_ACCOUNT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('CREATE_ACCOUNT.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.accountName.$touch"
|
@input="v$.accountName.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.accountName.$invalid ||
|
v$.accountName.$invalid ||
|
||||||
$v.accountName.$invalid ||
|
v$.accountName.$invalid ||
|
||||||
uiFlags.isCreating
|
uiFlags.isCreating
|
||||||
"
|
"
|
||||||
:button-text="$t('CREATE_ACCOUNT.FORM.SUBMIT')"
|
:button-text="$t('CREATE_ACCOUNT.FORM.SUBMIT')"
|
||||||
@@ -49,7 +49,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
|
||||||
@@ -64,6 +65,9 @@ export default {
|
|||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
accountName: '',
|
accountName: '',
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model="value"
|
v-model="value"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.value.$error }"
|
:class="{ error: v$.value.$error }"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.KEY_PLACEHOLDER')
|
$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.KEY_PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.value.$touch"
|
@blur="v$.value.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-between w-full gap-2 px-0 py-2">
|
<div class="flex flex-row justify-between w-full gap-2 px-0 py-2">
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<woot-button variant="clear" @click.prevent="onDismiss">
|
<woot-button variant="clear" @click.prevent="onDismiss">
|
||||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS') }}
|
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
<woot-button :is-disabled="$v.value.$invalid">
|
<woot-button :is-disabled="v$.value.$invalid">
|
||||||
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.FINISH') }}
|
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.FINISH') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,7 +37,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||||
@@ -48,10 +49,9 @@ export default {
|
|||||||
mixins: [aiMixin],
|
mixins: [aiMixin],
|
||||||
setup() {
|
setup() {
|
||||||
const { updateUISettings } = useUISettings();
|
const { updateUISettings } = useUISettings();
|
||||||
|
const v$ = useVuelidate();
|
||||||
|
|
||||||
return {
|
return { updateUISettings, v$ };
|
||||||
updateUISettings,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -96,11 +96,8 @@
|
|||||||
:placeholder="$t('AUTOMATION.ACTION.TEAM_MESSAGE_INPUT_PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ACTION.TEAM_MESSAGE_INPUT_PLACEHOLDER')"
|
||||||
class="action-message"
|
class="action-message"
|
||||||
/>
|
/>
|
||||||
<p
|
<p v-if="errorMessage" class="filter-error">
|
||||||
v-if="v.action_params.$dirty && v.action_params.$error"
|
{{ errorMessage }}
|
||||||
class="filter-error"
|
|
||||||
>
|
|
||||||
{{ $t('FILTER.EMPTY_VALUE_ERROR') }}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -128,9 +125,9 @@ export default {
|
|||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
v: {
|
errorMessage: {
|
||||||
type: Object,
|
type: String,
|
||||||
default: () => null,
|
default: '',
|
||||||
},
|
},
|
||||||
showActionInput: {
|
showActionInput: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -172,7 +169,7 @@ export default {
|
|||||||
},
|
},
|
||||||
actionInputStyles() {
|
actionInputStyles() {
|
||||||
return {
|
return {
|
||||||
'has-error': this.v.action_params.$dirty && this.v.action_params.$error,
|
'has-error': this.errorMessage,
|
||||||
'is-a-macro': this.isMacro,
|
'is-a-macro': this.isMacro,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="rounded-md p-2 border border-solid"
|
class="rounded-md p-2 border border-solid"
|
||||||
:class="getInputErrorClass(v.values.$dirty, v.values.$error)"
|
:class="getInputErrorClass(errorMessage)"
|
||||||
>
|
>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<select
|
<select
|
||||||
@@ -115,8 +115,8 @@
|
|||||||
@click="removeFilter"
|
@click="removeFilter"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="v.values.$dirty && v.values.$error" class="filter-error">
|
<p v-if="errorMessage" class="filter-error">
|
||||||
{{ $t('FILTER.EMPTY_VALUE_ERROR') }}
|
{{ errorMessage }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -173,10 +173,6 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
v: {
|
|
||||||
type: Object,
|
|
||||||
default: () => null,
|
|
||||||
},
|
|
||||||
showUserInput: {
|
showUserInput: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@@ -193,6 +189,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
errorMessage: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
attributeKey: {
|
attributeKey: {
|
||||||
@@ -271,8 +271,8 @@ export default {
|
|||||||
resetFilter() {
|
resetFilter() {
|
||||||
this.$emit('resetFilter');
|
this.$emit('resetFilter');
|
||||||
},
|
},
|
||||||
getInputErrorClass(isDirty, hasError) {
|
getInputErrorClass(errorMessage) {
|
||||||
return isDirty && hasError
|
return errorMessage
|
||||||
? 'bg-red-50 dark:bg-red-800/50 border-red-100 dark:border-red-700/50'
|
? 'bg-red-50 dark:bg-red-800/50 border-red-100 dark:border-red-700/50'
|
||||||
: 'bg-slate-50 dark:bg-slate-800 border-slate-75 dark:border-slate-700/50';
|
: 'bg-slate-50 dark:bg-slate-800 border-slate-75 dark:border-slate-700/50';
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<input
|
<input
|
||||||
v-model="activeFolderNewName"
|
v-model="activeFolderNewName"
|
||||||
type="text"
|
type="text"
|
||||||
class="folder-input border-slate-75 dark:border-slate-600 bg-white dark:bg-slate-900 text-slate-900 dark:text-slate-100"
|
class="bg-white folder-input border-slate-75 dark:border-slate-600 dark:bg-slate-900 text-slate-900 dark:text-slate-100"
|
||||||
/>
|
/>
|
||||||
<span v-if="!activeFolderNewName" class="message">
|
<span v-if="!activeFolderNewName" class="message">
|
||||||
{{ $t('FILTER.EMPTY_VALUE_ERROR') }}
|
{{ $t('FILTER.EMPTY_VALUE_ERROR') }}
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="p-4 rounded-lg bg-slate-25 dark:bg-slate-900 border border-solid border-slate-50 dark:border-slate-700/50 mb-4"
|
class="p-4 mb-4 border border-solid rounded-lg bg-slate-25 dark:bg-slate-900 border-slate-50 dark:border-slate-700/50"
|
||||||
>
|
>
|
||||||
<filter-input-box
|
<filter-input-box
|
||||||
v-for="(filter, i) in appliedFilters"
|
v-for="(filter, i) in appliedFilters"
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
:show-query-operator="i !== appliedFilters.length - 1"
|
:show-query-operator="i !== appliedFilters.length - 1"
|
||||||
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
||||||
:grouped-filters="true"
|
:grouped-filters="true"
|
||||||
:v="$v.appliedFilters.$each[i]"
|
:error-message="validationErrors[`filter_${i}`]"
|
||||||
@resetFilter="resetFilter(i, appliedFilters[i])"
|
@resetFilter="resetFilter(i, appliedFilters[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button class="button clear" @click.prevent="onClose">
|
<woot-button class="button clear" @click.prevent="onClose">
|
||||||
{{ $t('FILTER.CANCEL_BUTTON_LABEL') }}
|
{{ $t('FILTER.CANCEL_BUTTON_LABEL') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
@@ -80,7 +80,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
|
||||||
import FilterInputBox from '../FilterInput/Index.vue';
|
import FilterInputBox from '../FilterInput/Index.vue';
|
||||||
import languages from './advancedFilterItems/languages';
|
import languages from './advancedFilterItems/languages';
|
||||||
import countries from 'shared/constants/countries.js';
|
import countries from 'shared/constants/countries.js';
|
||||||
@@ -89,6 +88,7 @@ import { filterAttributeGroups } from './advancedFilterItems';
|
|||||||
import filterMixin from 'shared/mixins/filterMixin';
|
import filterMixin from 'shared/mixins/filterMixin';
|
||||||
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
||||||
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
import { CONVERSATION_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||||
|
import { validateConversationOrContactFilters } from 'dashboard/helper/validations.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -117,27 +117,6 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validations: {
|
|
||||||
appliedFilters: {
|
|
||||||
required,
|
|
||||||
$each: {
|
|
||||||
values: {
|
|
||||||
ensureBetween0to999(value, prop) {
|
|
||||||
if (prop.filter_operator === 'days_before') {
|
|
||||||
return parseInt(value, 10) > 0 && parseInt(value, 10) < 999;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
required: requiredIf(prop => {
|
|
||||||
return !(
|
|
||||||
prop.filter_operator === 'is_present' ||
|
|
||||||
prop.filter_operator === 'is_not_present'
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -149,6 +128,7 @@ export default {
|
|||||||
allCustomAttributes: [],
|
allCustomAttributes: [],
|
||||||
attributeModel: 'conversation_attribute',
|
attributeModel: 'conversation_attribute',
|
||||||
filtersFori18n: 'FILTER',
|
filtersFori18n: 'FILTER',
|
||||||
|
validationErrors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -347,20 +327,23 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitFilterQuery() {
|
submitFilterQuery() {
|
||||||
this.$v.$touch();
|
this.validationErrors = validateConversationOrContactFilters(
|
||||||
if (this.$v.$invalid) return;
|
this.appliedFilters
|
||||||
this.$store.dispatch(
|
|
||||||
'setConversationFilters',
|
|
||||||
JSON.parse(JSON.stringify(this.appliedFilters))
|
|
||||||
);
|
);
|
||||||
this.$emit('applyFilter', this.appliedFilters);
|
if (Object.keys(this.validationErrors).length === 0) {
|
||||||
this.$track(CONVERSATION_EVENTS.APPLY_FILTER, {
|
this.$store.dispatch(
|
||||||
applied_filters: this.appliedFilters.map(filter => ({
|
'setConversationFilters',
|
||||||
key: filter.attribute_key,
|
JSON.parse(JSON.stringify(this.appliedFilters))
|
||||||
operator: filter.filter_operator,
|
);
|
||||||
query_operator: filter.query_operator,
|
this.$emit('applyFilter', this.appliedFilters);
|
||||||
})),
|
this.$track(CONVERSATION_EVENTS.APPLY_FILTER, {
|
||||||
});
|
applied_filters: this.appliedFilters.map(filter => ({
|
||||||
|
key: filter.attribute_key,
|
||||||
|
operator: filter.filter_operator,
|
||||||
|
query_operator: filter.query_operator,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateSavedCustomViews() {
|
updateSavedCustomViews() {
|
||||||
this.$emit('updateFolder', this.appliedFilters, this.activeFolderNewName);
|
this.$emit('updateFolder', this.appliedFilters, this.activeFolderNewName);
|
||||||
|
|||||||
@@ -48,14 +48,14 @@
|
|||||||
}}</label>
|
}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="sentToOtherEmailAddress" class="w-[50%] mt-1">
|
<div v-if="sentToOtherEmailAddress" class="w-[50%] mt-1">
|
||||||
<label :class="{ error: $v.email.$error }">
|
<label :class="{ error: v$.email.$error }">
|
||||||
<input
|
<input
|
||||||
v-model.trim="email"
|
v-model.trim="email"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('EMAIL_TRANSCRIPT.FORM.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('EMAIL_TRANSCRIPT.FORM.EMAIL.PLACEHOLDER')"
|
||||||
@input="$v.email.$touch"
|
@input="v$.email.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.email.$error" class="message">
|
<span v-if="v$.email.$error" class="message">
|
||||||
{{ $t('EMAIL_TRANSCRIPT.FORM.EMAIL.ERROR') }}
|
{{ $t('EMAIL_TRANSCRIPT.FORM.EMAIL.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -76,7 +76,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -89,6 +90,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: '',
|
email: '',
|
||||||
@@ -110,7 +114,7 @@ export default {
|
|||||||
isFormValid() {
|
isFormValid() {
|
||||||
if (this.selectedType) {
|
if (this.selectedType) {
|
||||||
if (this.sentToOtherEmailAddress) {
|
if (this.sentToOtherEmailAddress) {
|
||||||
return !!this.email && !this.$v.email.$error;
|
return !!this.email && !this.v$.email.$error;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="toEmails">
|
<div v-if="toEmails">
|
||||||
<div class="input-group small" :class="{ error: $v.toEmailsVal.$error }">
|
<div class="input-group small" :class="{ error: v$.toEmailsVal.$error }">
|
||||||
<label class="input-group-label">
|
<label class="input-group-label">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap">
|
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="$v.toEmailsVal.$model"
|
v-model.trim="v$.toEmailsVal.$model"
|
||||||
type="text"
|
type="text"
|
||||||
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none"
|
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none"
|
||||||
:class="{ error: $v.toEmailsVal.$error }"
|
:class="{ error: v$.toEmailsVal.$error }"
|
||||||
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
/>
|
/>
|
||||||
@@ -18,16 +18,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group-wrap">
|
<div class="input-group-wrap">
|
||||||
<div class="input-group small" :class="{ error: $v.ccEmailsVal.$error }">
|
<div class="input-group small" :class="{ error: v$.ccEmailsVal.$error }">
|
||||||
<label class="input-group-label">
|
<label class="input-group-label">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap">
|
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="$v.ccEmailsVal.$model"
|
v-model.trim="v$.ccEmailsVal.$model"
|
||||||
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none"
|
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.ccEmailsVal.$error }"
|
:class="{ error: v$.ccEmailsVal.$error }"
|
||||||
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
/>
|
/>
|
||||||
@@ -41,21 +41,21 @@
|
|||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.ADD_BCC') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.ADD_BCC') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="$v.ccEmailsVal.$error" class="message">
|
<span v-if="v$.ccEmailsVal.$error" class="message">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.ERROR') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showBcc" class="input-group-wrap">
|
<div v-if="showBcc" class="input-group-wrap">
|
||||||
<div class="input-group small" :class="{ error: $v.bccEmailsVal.$error }">
|
<div class="input-group small" :class="{ error: v$.bccEmailsVal.$error }">
|
||||||
<label class="input-group-label">
|
<label class="input-group-label">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap">
|
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="$v.bccEmailsVal.$model"
|
v-model.trim="v$.bccEmailsVal.$model"
|
||||||
type="text"
|
type="text"
|
||||||
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none"
|
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none"
|
||||||
:class="{ error: $v.bccEmailsVal.$error }"
|
:class="{ error: v$.bccEmailsVal.$error }"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER')
|
$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="$v.bccEmailsVal.$error" class="message">
|
<span v-if="v$.bccEmailsVal.$error" class="message">
|
||||||
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.ERROR') }}
|
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,6 +72,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { validEmailsByComma } from './helpers/emailHeadHelper';
|
import { validEmailsByComma } from './helpers/emailHeadHelper';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -88,6 +89,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showBcc: false,
|
showBcc: false,
|
||||||
@@ -140,7 +144,7 @@ export default {
|
|||||||
this.showBcc = true;
|
this.showBcc = true;
|
||||||
},
|
},
|
||||||
onBlur() {
|
onBlur() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
this.$emit('update:bccEmails', this.bccEmailsVal);
|
this.$emit('update:bccEmails', this.bccEmailsVal);
|
||||||
this.$emit('update:ccEmails', this.ccEmailsVal);
|
this.$emit('update:ccEmails', this.ccEmailsVal);
|
||||||
this.$emit('update:toEmails', this.toEmailsVal);
|
this.$emit('update:toEmails', this.toEmailsVal);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
:styles="{ marginBottom: 0 }"
|
:styles="{ marginBottom: 0 }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="$v.$dirty && $v.$invalid" class="error">
|
<p v-if="v$.$dirty && v$.$invalid" class="error">
|
||||||
{{ $t('WHATSAPP_TEMPLATES.PARSER.FORM_ERROR_MESSAGE') }}
|
{{ $t('WHATSAPP_TEMPLATES.PARSER.FORM_ERROR_MESSAGE') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,11 +41,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { requiredIf } from '@vuelidate/validators';
|
||||||
const allKeysRequired = value => {
|
const allKeysRequired = value => {
|
||||||
const keys = Object.keys(value);
|
const keys = Object.keys(value);
|
||||||
return keys.every(key => value[key]);
|
return keys.every(key => value[key]);
|
||||||
};
|
};
|
||||||
import { requiredIf } from 'vuelidate/lib/validators';
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
template: {
|
template: {
|
||||||
@@ -53,6 +54,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
processedParams: {
|
processedParams: {
|
||||||
requiredIfKeysPresent: requiredIf('variables'),
|
requiredIfKeysPresent: requiredIf('variables'),
|
||||||
@@ -86,8 +90,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
sendMessage() {
|
sendMessage() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) return;
|
if (this.v$.$invalid) return;
|
||||||
const payload = {
|
const payload = {
|
||||||
message: this.processedString,
|
message: this.processedString,
|
||||||
templateParams: {
|
templateParams: {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import emailValidator from 'vuelidate/lib/validators/email';
|
import { email as emailValidator } from '@vuelidate/validators';
|
||||||
|
|
||||||
export const validEmailsByComma = value => {
|
export const validEmailsByComma = value => {
|
||||||
if (!value.length) return true;
|
if (!value.length) return true;
|
||||||
const emails = value.replace(/\s+/g, '').split(',');
|
const emails = value.replace(/\s+/g, '').split(',');
|
||||||
return emails.every(email => emailValidator(email));
|
return emails.every(email => emailValidator.$validator(email));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model="value"
|
v-model="value"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.value.$error }"
|
:class="{ error: v$.value.$error }"
|
||||||
:placeholder="confirmPlaceHolderText"
|
:placeholder="confirmPlaceHolderText"
|
||||||
@blur="$v.value.$touch"
|
@blur="v$.value.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="button-wrapper">
|
<div class="button-wrapper">
|
||||||
<woot-button color-scheme="alert" :is-disabled="$v.value.$invalid">
|
<woot-button color-scheme="alert" :is-disabled="v$.value.$invalid">
|
||||||
{{ confirmText }}
|
{{ confirmText }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
<woot-button class="clear" @click.prevent="closeModal">
|
<woot-button class="clear" @click.prevent="closeModal">
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required } from '@vuelidate/validators';
|
||||||
import Modal from '../../Modal.vue';
|
import Modal from '../../Modal.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
@@ -61,6 +61,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
value: '',
|
value: '',
|
||||||
|
|||||||
127
app/javascript/dashboard/helper/specs/validations.spec.js
Normal file
127
app/javascript/dashboard/helper/specs/validations.spec.js
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import {
|
||||||
|
validateConversationOrContactFilters,
|
||||||
|
validateAutomation,
|
||||||
|
} from '../validations';
|
||||||
|
|
||||||
|
describe('validateConversationOrContactFilters', () => {
|
||||||
|
it('should return no errors for valid filters', () => {
|
||||||
|
const validFilters = [
|
||||||
|
{ attribute_key: 'name', filter_operator: 'contains', values: 'John' },
|
||||||
|
{ attribute_key: 'email', filter_operator: 'is_present' },
|
||||||
|
];
|
||||||
|
const errors = validateConversationOrContactFilters(validFilters);
|
||||||
|
expect(errors).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return errors for invalid filters', () => {
|
||||||
|
const invalidFilters = [
|
||||||
|
{ attribute_key: '', filter_operator: 'contains', values: 'John' },
|
||||||
|
{ attribute_key: 'email', filter_operator: '' },
|
||||||
|
{ attribute_key: 'age', filter_operator: 'equals' },
|
||||||
|
];
|
||||||
|
const errors = validateConversationOrContactFilters(invalidFilters);
|
||||||
|
expect(errors).toEqual({
|
||||||
|
filter_0: 'ATTRIBUTE_KEY_REQUIRED',
|
||||||
|
filter_1: 'FILTER_OPERATOR_REQUIRED',
|
||||||
|
filter_2: 'VALUE_REQUIRED',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should validate days_before operator correctly', () => {
|
||||||
|
const filters = [
|
||||||
|
{ attribute_key: 'date', filter_operator: 'days_before', values: '0' },
|
||||||
|
{ attribute_key: 'date', filter_operator: 'days_before', values: '999' },
|
||||||
|
{ attribute_key: 'date', filter_operator: 'days_before', values: '500' },
|
||||||
|
];
|
||||||
|
const errors = validateConversationOrContactFilters(filters);
|
||||||
|
expect(errors).toEqual({
|
||||||
|
filter_0: 'VALUE_MUST_BE_BETWEEN_1_AND_998',
|
||||||
|
filter_1: 'VALUE_MUST_BE_BETWEEN_1_AND_998',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateAutomation', () => {
|
||||||
|
it('should return no errors for a valid automation', () => {
|
||||||
|
const validAutomation = {
|
||||||
|
name: 'Test Automation',
|
||||||
|
description: 'A test automation',
|
||||||
|
event_name: 'message_created',
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
attribute_key: 'content',
|
||||||
|
filter_operator: 'contains',
|
||||||
|
values: 'hello',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
{ action_name: 'send_message', action_params: ['Hello there!'] },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const errors = validateAutomation(validAutomation);
|
||||||
|
expect(errors).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return errors for missing basic fields', () => {
|
||||||
|
const invalidAutomation = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
event_name: '',
|
||||||
|
conditions: [],
|
||||||
|
actions: [],
|
||||||
|
};
|
||||||
|
const errors = validateAutomation(invalidAutomation);
|
||||||
|
expect(errors).toHaveProperty('name');
|
||||||
|
expect(errors).toHaveProperty('description');
|
||||||
|
expect(errors).toHaveProperty('event_name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return errors for invalid conditions', () => {
|
||||||
|
const automationWithInvalidConditions = {
|
||||||
|
name: 'Test',
|
||||||
|
description: 'Test',
|
||||||
|
event_name: 'message_created',
|
||||||
|
conditions: [{ attribute_key: '', filter_operator: '', values: '' }],
|
||||||
|
actions: [{ action_name: 'send_message', action_params: ['Hello'] }],
|
||||||
|
};
|
||||||
|
const errors = validateAutomation(automationWithInvalidConditions);
|
||||||
|
expect(errors).toHaveProperty('condition_0');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return errors for invalid actions', () => {
|
||||||
|
const automationWithInvalidActions = {
|
||||||
|
name: 'Test',
|
||||||
|
description: 'Test',
|
||||||
|
event_name: 'message_created',
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
attribute_key: 'content',
|
||||||
|
filter_operator: 'contains',
|
||||||
|
values: 'hello',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
actions: [{ action_name: 'send_message', action_params: [] }],
|
||||||
|
};
|
||||||
|
const errors = validateAutomation(automationWithInvalidActions);
|
||||||
|
expect(errors).toHaveProperty('action_0');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not require action params for specific actions', () => {
|
||||||
|
const automationWithNoParamAction = {
|
||||||
|
name: 'Test',
|
||||||
|
description: 'Test',
|
||||||
|
event_name: 'message_created',
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
attribute_key: 'content',
|
||||||
|
filter_operator: 'contains',
|
||||||
|
values: 'hello',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
actions: [{ action_name: 'mute_conversation' }],
|
||||||
|
};
|
||||||
|
const errors = validateAutomation(automationWithNoParamAction);
|
||||||
|
expect(errors).toEqual({});
|
||||||
|
});
|
||||||
|
});
|
||||||
193
app/javascript/dashboard/helper/validations.js
Normal file
193
app/javascript/dashboard/helper/validations.js
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
export const ATTRIBUTE_KEY_REQUIRED = 'ATTRIBUTE_KEY_REQUIRED';
|
||||||
|
export const FILTER_OPERATOR_REQUIRED = 'FILTER_OPERATOR_REQUIRED';
|
||||||
|
export const VALUE_REQUIRED = 'VALUE_REQUIRED';
|
||||||
|
export const VALUE_MUST_BE_BETWEEN_1_AND_998 =
|
||||||
|
'VALUE_MUST_BE_BETWEEN_1_AND_998';
|
||||||
|
export const ACTION_PARAMETERS_REQUIRED = 'ACTION_PARAMETERS_REQUIRED';
|
||||||
|
export const ATLEAST_ONE_CONDITION_REQUIRED = 'ATLEAST_ONE_CONDITION_REQUIRED';
|
||||||
|
export const ATLEAST_ONE_ACTION_REQUIRED = 'ATLEAST_ONE_ACTION_REQUIRED';
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ------------------------ Filter Validation -----------------------
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a single filter for conversations or contacts.
|
||||||
|
*
|
||||||
|
* @param {Object} filter - The filter object to validate.
|
||||||
|
* @param {string} filter.attribute_key - The key of the attribute to filter on.
|
||||||
|
* @param {string} filter.filter_operator - The operator to use for filtering.
|
||||||
|
* @param {string|number|Array} [filter.values] - The value(s) to filter by (required for most operators).
|
||||||
|
*
|
||||||
|
* @returns {string|null} An error message if validation fails, or null if validation passes.
|
||||||
|
*/
|
||||||
|
const validateSingleFilter = filter => {
|
||||||
|
if (!filter.attribute_key) {
|
||||||
|
return ATTRIBUTE_KEY_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filter.filter_operator) {
|
||||||
|
return FILTER_OPERATOR_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
filter.filter_operator !== 'is_present' &&
|
||||||
|
filter.filter_operator !== 'is_not_present' &&
|
||||||
|
(!filter.values ||
|
||||||
|
(Array.isArray(filter.values) && filter.values.length === 0))
|
||||||
|
) {
|
||||||
|
return VALUE_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
filter.filter_operator === 'days_before' &&
|
||||||
|
(parseInt(filter.values, 10) <= 0 || parseInt(filter.values, 10) >= 999)
|
||||||
|
) {
|
||||||
|
return VALUE_MUST_BE_BETWEEN_1_AND_998;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates filters for conversations or contacts.
|
||||||
|
*
|
||||||
|
* @param {Array} filters - An array of filter objects to validate.
|
||||||
|
* @param {string} filters[].attribute_key - The key of the attribute to filter on.
|
||||||
|
* @param {string} filters[].filter_operator - The operator to use for filtering.
|
||||||
|
* @param {string|number} [filters[].values] - The value(s) to filter by (required for most operators).
|
||||||
|
*
|
||||||
|
* @returns {Object} An object containing any validation errors, keyed by filter index.
|
||||||
|
*/
|
||||||
|
export const validateConversationOrContactFilters = filters => {
|
||||||
|
const errors = {};
|
||||||
|
|
||||||
|
filters.forEach((filter, index) => {
|
||||||
|
const error = validateSingleFilter(filter);
|
||||||
|
if (error) {
|
||||||
|
errors[`filter_${index}`] = error;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ---------------------- Automation Validation ---------------------
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the basic fields of an automation object.
|
||||||
|
*
|
||||||
|
* @param {Object} automation - The automation object to validate.
|
||||||
|
* @returns {Object} An object containing any validation errors.
|
||||||
|
*/
|
||||||
|
const validateBasicFields = automation => {
|
||||||
|
const errors = {};
|
||||||
|
const requiredFields = ['name', 'description', 'event_name'];
|
||||||
|
|
||||||
|
requiredFields.forEach(field => {
|
||||||
|
if (!automation[field]) {
|
||||||
|
errors[field] = `${
|
||||||
|
field.charAt(0).toUpperCase() + field.slice(1)
|
||||||
|
} is required`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the conditions of an automation object.
|
||||||
|
*
|
||||||
|
* @param {Array} conditions - The conditions to validate.
|
||||||
|
* @returns {Object} An object containing any validation errors.
|
||||||
|
*/
|
||||||
|
export const validateConditions = conditions => {
|
||||||
|
const errors = {};
|
||||||
|
|
||||||
|
if (!conditions || conditions.length === 0) {
|
||||||
|
errors.conditions = ATLEAST_ONE_CONDITION_REQUIRED;
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions.forEach((condition, index) => {
|
||||||
|
const error = validateSingleFilter(condition);
|
||||||
|
if (error) {
|
||||||
|
errors[`condition_${index}`] = error;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a single action of an automation object.
|
||||||
|
*
|
||||||
|
* @param {Object} action - The action to validate.
|
||||||
|
* @returns {string|null} An error message if validation fails, or null if validation passes.
|
||||||
|
*/
|
||||||
|
const validateSingleAction = action => {
|
||||||
|
const noParamActions = [
|
||||||
|
'mute_conversation',
|
||||||
|
'snooze_conversation',
|
||||||
|
'resolve_conversation',
|
||||||
|
'remove_assigned_team',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (
|
||||||
|
!noParamActions.includes(action.action_name) &&
|
||||||
|
(!action.action_params || action.action_params.length === 0)
|
||||||
|
) {
|
||||||
|
return ACTION_PARAMETERS_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the actions of an automation object.
|
||||||
|
*
|
||||||
|
* @param {Array} actions - The actions to validate.
|
||||||
|
* @returns {Object} An object containing any validation errors.
|
||||||
|
*/
|
||||||
|
export const validateActions = actions => {
|
||||||
|
if (!actions || actions.length === 0) {
|
||||||
|
return { actions: ATLEAST_ONE_ACTION_REQUIRED };
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions.reduce((errors, action, index) => {
|
||||||
|
const error = validateSingleAction(action);
|
||||||
|
if (error) {
|
||||||
|
errors[`action_${index}`] = error;
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an automation object.
|
||||||
|
*
|
||||||
|
* @param {Object} automation - The automation object to validate.
|
||||||
|
* @param {string} automation.name - The name of the automation.
|
||||||
|
* @param {string} automation.description - The description of the automation.
|
||||||
|
* @param {string} automation.event_name - The name of the event that triggers the automation.
|
||||||
|
* @param {Array} automation.conditions - An array of condition objects for the automation.
|
||||||
|
* @param {string} automation.conditions[].filter_operator - The operator for the condition.
|
||||||
|
* @param {string|number} [automation.conditions[].values] - The value(s) for the condition.
|
||||||
|
* @param {Array} automation.actions - An array of action objects for the automation.
|
||||||
|
* @param {string} automation.actions[].action_name - The name of the action.
|
||||||
|
* @param {Array} [automation.actions[].action_params] - The parameters for the action.
|
||||||
|
*
|
||||||
|
* @returns {Object} An object containing any validation errors.
|
||||||
|
*/
|
||||||
|
export const validateAutomation = automation => {
|
||||||
|
const basicErrors = validateBasicFields(automation);
|
||||||
|
const conditionErrors = validateConditions(automation.conditions);
|
||||||
|
const actionErrors = validateActions(automation.actions);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...basicErrors,
|
||||||
|
...conditionErrors,
|
||||||
|
...actionErrors,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -39,12 +39,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"LIST": {
|
"LIST": {
|
||||||
"TABLE_HEADER": [
|
"TABLE_HEADER": ["Name", "Description", "Active", "Created on"],
|
||||||
"Name",
|
|
||||||
"Description",
|
|
||||||
"Active",
|
|
||||||
"Created on"
|
|
||||||
],
|
|
||||||
"404": "No automation rules found"
|
"404": "No automation rules found"
|
||||||
},
|
},
|
||||||
"DELETE": {
|
"DELETE": {
|
||||||
@@ -113,6 +108,15 @@
|
|||||||
"LABEL_UPLOADING": "Uploading...",
|
"LABEL_UPLOADING": "Uploading...",
|
||||||
"LABEL_UPLOADED": "Successfully Uploaded",
|
"LABEL_UPLOADED": "Successfully Uploaded",
|
||||||
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
"LABEL_UPLOAD_FAILED": "Upload Failed"
|
||||||
|
},
|
||||||
|
"ERRORS": {
|
||||||
|
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||||
|
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||||
|
"VALUE_REQUIRED": "Value is required",
|
||||||
|
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||||
|
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||||
|
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||||
|
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,15 @@
|
|||||||
"BUTTON_TOOLTIP": "Execute",
|
"BUTTON_TOOLTIP": "Execute",
|
||||||
"PREVIEW": "Preview Macro",
|
"PREVIEW": "Preview Macro",
|
||||||
"EXECUTED_SUCCESSFULLY": "Macro executed successfully"
|
"EXECUTED_SUCCESSFULLY": "Macro executed successfully"
|
||||||
|
},
|
||||||
|
"ERRORS": {
|
||||||
|
"ATTRIBUTE_KEY_REQUIRED": "Attribute key is required",
|
||||||
|
"FILTER_OPERATOR_REQUIRED": "Filter operator is required",
|
||||||
|
"VALUE_REQUIRED": "Value is required",
|
||||||
|
"VALUE_MUST_BE_BETWEEN_1_AND_998": "Value must be between 1 and 998",
|
||||||
|
"ACTION_PARAMETERS_REQUIRED": "Action parameters are required",
|
||||||
|
"ATLEAST_ONE_CONDITION_REQUIRED": "At least one condition is required",
|
||||||
|
"ATLEAST_ONE_ACTION_REQUIRED": "At least one action is required"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
import languages from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
||||||
import countries from 'shared/constants/countries';
|
import countries from 'shared/constants/countries';
|
||||||
|
import { validateAutomation } from 'dashboard/helper/validations';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
generateCustomAttributeTypes,
|
generateCustomAttributeTypes,
|
||||||
getActionOptions,
|
getActionOptions,
|
||||||
@@ -152,10 +154,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitAutomation() {
|
submitAutomation() {
|
||||||
this.$v.$touch();
|
// we assign it to this.errors so that it can be accessed in the template
|
||||||
if (this.$v.$invalid) return;
|
// it is supposed to be declared in the data function
|
||||||
const automation = generateAutomationPayload(this.automation);
|
this.errors = validateAutomation(this.automation);
|
||||||
this.$emit('saveAutomation', automation, this.mode);
|
if (Object.keys(this.errors).length === 0) {
|
||||||
|
const automation = generateAutomationPayload(this.automation);
|
||||||
|
this.$emit('saveAutomation', automation, this.mode);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
resetFilter(index, currentCondition) {
|
resetFilter(index, currentCondition) {
|
||||||
this.automation.conditions[index].filter_operator = this.automationTypes[
|
this.automation.conditions[index].filter_operator = this.automationTypes[
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
validations: {
|
|
||||||
automation: {
|
|
||||||
name: {
|
|
||||||
required,
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
required,
|
|
||||||
},
|
|
||||||
event_name: {
|
|
||||||
required,
|
|
||||||
},
|
|
||||||
conditions: {
|
|
||||||
required,
|
|
||||||
$each: {
|
|
||||||
values: {
|
|
||||||
required: requiredIf(prop => {
|
|
||||||
return !(
|
|
||||||
prop.filter_operator === 'is_present' ||
|
|
||||||
prop.filter_operator === 'is_not_present'
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
required,
|
|
||||||
$each: {
|
|
||||||
action_params: {
|
|
||||||
required: requiredIf(prop => {
|
|
||||||
return !(
|
|
||||||
prop.action_name === 'mute_conversation' ||
|
|
||||||
prop.action_name === 'snooze_conversation' ||
|
|
||||||
prop.action_name === 'resolve_conversation'
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
<form class="w-full" @submit.prevent="addCustomAttribute">
|
<form class="w-full" @submit.prevent="addCustomAttribute">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="attributeName"
|
v-model.trim="attributeName"
|
||||||
:class="{ error: $v.attributeName.$error }"
|
:class="{ error: v$.attributeName.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:error="attributeNameError"
|
:error="attributeNameError"
|
||||||
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
|
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.attributeName.$touch"
|
@input="v$.attributeName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="attributeValue"
|
v-model.trim="attributeValue"
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
/>
|
/>
|
||||||
<div class="flex items-center justify-end gap-2 px-0 py-2">
|
<div class="flex items-center justify-end gap-2 px-0 py-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-disabled="$v.attributeName.$invalid || isCreating"
|
:is-disabled="v$.attributeName.$invalid || isCreating"
|
||||||
:is-loading="isCreating"
|
:is-loading="isCreating"
|
||||||
>
|
>
|
||||||
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
|
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
|
||||||
@@ -38,7 +38,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Modal from 'dashboard/components/Modal.vue';
|
import Modal from 'dashboard/components/Modal.vue';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -54,6 +55,9 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
attributeValue: '',
|
attributeValue: '',
|
||||||
@@ -68,7 +72,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
attributeNameError() {
|
attributeNameError() {
|
||||||
if (this.$v.attributeName.$error) {
|
if (this.v$.attributeName.$error) {
|
||||||
return this.$t('CUSTOM_ATTRIBUTES.FORM.NAME.ERROR');
|
return this.$t('CUSTOM_ATTRIBUTES.FORM.NAME.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mt-1 multiselect-wrap--medium"
|
class="mt-1 multiselect-wrap--medium"
|
||||||
:class="{ error: $v.parentContact.$error }"
|
:class="{ error: v$.parentContact.$error }"
|
||||||
>
|
>
|
||||||
<label class="multiselect__label">
|
<label class="multiselect__label">
|
||||||
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
|
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
|
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
|
||||||
</span>
|
</span>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
<span v-if="$v.parentContact.$error" class="message">
|
<span v-if="v$.parentContact.$error" class="message">
|
||||||
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
|
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -114,7 +114,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required } from '@vuelidate/validators';
|
||||||
|
|
||||||
import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary.vue';
|
import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary.vue';
|
||||||
import ContactDropdownItem from './ContactDropdownItem.vue';
|
import ContactDropdownItem from './ContactDropdownItem.vue';
|
||||||
@@ -139,6 +140,9 @@ export default {
|
|||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
primaryContact: {
|
primaryContact: {
|
||||||
required,
|
required,
|
||||||
@@ -163,8 +167,8 @@ export default {
|
|||||||
this.$emit('search', query);
|
this.$emit('search', query);
|
||||||
},
|
},
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('submit', this.parentContact.id);
|
this.$emit('submit', this.parentContact.id);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<input
|
<input
|
||||||
v-model="activeSegmentNewName"
|
v-model="activeSegmentNewName"
|
||||||
type="text"
|
type="text"
|
||||||
class="folder-input border-slate-75 dark:border-slate-600 bg-white dark:bg-slate-900 text-slate-900 dark:text-slate-100"
|
class="bg-white folder-input border-slate-75 dark:border-slate-600 dark:bg-slate-900 text-slate-900 dark:text-slate-100"
|
||||||
/>
|
/>
|
||||||
<span v-if="!activeSegmentNewName" class="message">
|
<span v-if="!activeSegmentNewName" class="message">
|
||||||
{{ $t('CONTACTS_FILTER.EMPTY_VALUE_ERROR') }}
|
{{ $t('CONTACTS_FILTER.EMPTY_VALUE_ERROR') }}
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="p-4 rounded-lg bg-slate-25 dark:bg-slate-900 border border-solid border-slate-50 dark:border-slate-700/50 mb-4"
|
class="p-4 mb-4 border border-solid rounded-lg bg-slate-25 dark:bg-slate-900 border-slate-50 dark:border-slate-700/50"
|
||||||
>
|
>
|
||||||
<filter-input-box
|
<filter-input-box
|
||||||
v-for="(filter, i) in appliedFilters"
|
v-for="(filter, i) in appliedFilters"
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
:dropdown-values="getDropdownValues(appliedFilters[i].attribute_key)"
|
:dropdown-values="getDropdownValues(appliedFilters[i].attribute_key)"
|
||||||
:show-query-operator="i !== appliedFilters.length - 1"
|
:show-query-operator="i !== appliedFilters.length - 1"
|
||||||
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
:show-user-input="showUserInput(appliedFilters[i].filter_operator)"
|
||||||
:v="$v.appliedFilters.$each[i]"
|
:error-message="validationErrors[`filter_${i}`]"
|
||||||
@resetFilter="resetFilter(i, appliedFilters[i])"
|
@resetFilter="resetFilter(i, appliedFilters[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button class="button clear" @click.prevent="onClose">
|
<woot-button class="button clear" @click.prevent="onClose">
|
||||||
{{ $t('CONTACTS_FILTER.CANCEL_BUTTON_LABEL') }}
|
{{ $t('CONTACTS_FILTER.CANCEL_BUTTON_LABEL') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
@@ -90,7 +90,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
|
||||||
import FilterInputBox from '../../../../components/widgets/FilterInput/Index.vue';
|
import FilterInputBox from '../../../../components/widgets/FilterInput/Index.vue';
|
||||||
import countries from 'shared/constants/countries.js';
|
import countries from 'shared/constants/countries.js';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
@@ -98,6 +97,8 @@ import { filterAttributeGroups } from '../contactFilterItems';
|
|||||||
import filterMixin from 'shared/mixins/filterMixin';
|
import filterMixin from 'shared/mixins/filterMixin';
|
||||||
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
import * as OPERATORS from 'dashboard/components/widgets/FilterInput/FilterOperatorTypes.js';
|
||||||
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
import { CONTACTS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||||
|
import { validateConversationOrContactFilters } from 'dashboard/helper/validations.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FilterInputBox,
|
FilterInputBox,
|
||||||
@@ -125,22 +126,6 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validations: {
|
|
||||||
appliedFilters: {
|
|
||||||
required,
|
|
||||||
$each: {
|
|
||||||
values: {
|
|
||||||
required,
|
|
||||||
ensureBetween0to999(value, prop) {
|
|
||||||
if (prop.filter_operator === 'days_before') {
|
|
||||||
return parseInt(value, 10) > 0 && parseInt(value, 10) < 999;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -152,6 +137,7 @@ export default {
|
|||||||
filterAttributeGroups,
|
filterAttributeGroups,
|
||||||
attributeModel: 'contact_attribute',
|
attributeModel: 'contact_attribute',
|
||||||
filtersFori18n: 'CONTACTS_FILTER',
|
filtersFori18n: 'CONTACTS_FILTER',
|
||||||
|
validationErrors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -314,20 +300,23 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitFilterQuery() {
|
submitFilterQuery() {
|
||||||
this.$v.$touch();
|
this.validationErrors = validateConversationOrContactFilters(
|
||||||
if (this.$v.$invalid) return;
|
this.appliedFilters
|
||||||
this.$store.dispatch(
|
|
||||||
'contacts/setContactFilters',
|
|
||||||
JSON.parse(JSON.stringify(this.appliedFilters))
|
|
||||||
);
|
);
|
||||||
this.$emit('applyFilter', this.appliedFilters);
|
if (Object.keys(this.validationErrors).length === 0) {
|
||||||
this.$track(CONTACTS_EVENTS.APPLY_FILTER, {
|
this.$store.dispatch(
|
||||||
applied_filters: this.appliedFilters.map(filter => ({
|
'contacts/setContactFilters',
|
||||||
key: filter.attribute_key,
|
JSON.parse(JSON.stringify(this.appliedFilters))
|
||||||
operator: filter.filter_operator,
|
);
|
||||||
query_operator: filter.query_operator,
|
this.$emit('applyFilter', this.appliedFilters);
|
||||||
})),
|
this.$track(CONTACTS_EVENTS.APPLY_FILTER, {
|
||||||
});
|
applied_filters: this.appliedFilters.map(filter => ({
|
||||||
|
key: filter.attribute_key,
|
||||||
|
operator: filter.filter_operator,
|
||||||
|
query_operator: filter.query_operator,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateSegment() {
|
updateSegment() {
|
||||||
this.$emit(
|
this.$emit(
|
||||||
|
|||||||
@@ -18,38 +18,38 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.name.$error }">
|
<label :class="{ error: v$.name.$error }">
|
||||||
{{ $t('CONTACT_FORM.FORM.NAME.LABEL') }}
|
{{ $t('CONTACT_FORM.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="name"
|
v-model.trim="name"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.name.$touch"
|
@input="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label :class="{ error: $v.email.$error }">
|
<label :class="{ error: v$.email.$error }">
|
||||||
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.LABEL') }}
|
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="email"
|
v-model.trim="email"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.EMAIL_ADDRESS.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.EMAIL_ADDRESS.PLACEHOLDER')"
|
||||||
@input="$v.email.$touch"
|
@input="v$.email.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.email.$error" class="message">
|
<span v-if="v$.email.$error" class="message">
|
||||||
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.ERROR') }}
|
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label :class="{ error: v$.description.$error }">
|
||||||
{{ $t('CONTACT_FORM.FORM.BIO.LABEL') }}
|
{{ $t('CONTACT_FORM.FORM.BIO.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.BIO.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.BIO.PLACEHOLDER')"
|
||||||
@input="$v.description.$touch"
|
@input="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
:error="isPhoneNumberNotValid"
|
:error="isPhoneNumberNotValid"
|
||||||
:placeholder="$t('CONTACT_FORM.FORM.PHONE_NUMBER.PLACEHOLDER')"
|
:placeholder="$t('CONTACT_FORM.FORM.PHONE_NUMBER.PLACEHOLDER')"
|
||||||
@input="onPhoneNumberInputChange"
|
@input="onPhoneNumberInputChange"
|
||||||
@blur="$v.phoneNumber.$touch"
|
@blur="v$.phoneNumber.$touch"
|
||||||
@setCode="setPhoneCode"
|
@setCode="setPhoneCode"
|
||||||
/>
|
/>
|
||||||
<span v-if="isPhoneNumberNotValid" class="message">
|
<span v-if="isPhoneNumberNotValid" class="message">
|
||||||
@@ -155,7 +155,8 @@ import {
|
|||||||
DuplicateContactException,
|
DuplicateContactException,
|
||||||
ExceptionWithMessage,
|
ExceptionWithMessage,
|
||||||
} from 'shared/helpers/CustomErrors';
|
} from 'shared/helpers/CustomErrors';
|
||||||
import { required, email } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, email } from '@vuelidate/validators';
|
||||||
import countries from 'shared/constants/countries.js';
|
import countries from 'shared/constants/countries.js';
|
||||||
import { isPhoneNumberValid } from 'shared/helpers/Validators';
|
import { isPhoneNumberValid } from 'shared/helpers/Validators';
|
||||||
import parsePhoneNumber from 'libphonenumber-js';
|
import parsePhoneNumber from 'libphonenumber-js';
|
||||||
@@ -175,6 +176,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
countries: countries,
|
countries: countries,
|
||||||
@@ -367,8 +371,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async handleSubmit() {
|
async handleSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid || this.isPhoneNumberNotValid) {
|
if (this.v$.$invalid || this.isPhoneNumberNotValid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
class="multiselect-wrap--small"
|
class="multiselect-wrap--small"
|
||||||
:class="{ 'has-multi-select-error': $v.targetInbox.$error }"
|
:class="{ 'has-multi-select-error': v$.targetInbox.$error }"
|
||||||
>
|
>
|
||||||
<multiselect
|
<multiselect
|
||||||
v-model="targetInbox"
|
v-model="targetInbox"
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
<label :class="{ error: $v.targetInbox.$error }">
|
<label :class="{ error: v$.targetInbox.$error }">
|
||||||
<span v-if="$v.targetInbox.$error" class="message">
|
<span v-if="v$.targetInbox.$error" class="message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.INBOX.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.INBOX.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -79,15 +79,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="isAnEmailInbox" class="w-full">
|
<div v-if="isAnEmailInbox" class="w-full">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.subject.$error }">
|
<label :class="{ error: v$.subject.$error }">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.LABEL') }}
|
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model="subject"
|
v-model="subject"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('NEW_CONVERSATION.FORM.SUBJECT.PLACEHOLDER')"
|
:placeholder="$t('NEW_CONVERSATION.FORM.SUBJECT.PLACEHOLDER')"
|
||||||
@input="$v.subject.$touch"
|
@input="v$.subject.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.subject.$error" class="message">
|
<span v-if="v$.subject.$error" class="message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -115,13 +115,13 @@
|
|||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="message"
|
v-model="message"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:class="{ editor_warning: $v.message.$error }"
|
:class="{ editor_warning: v$.message.$error }"
|
||||||
:enable-variables="true"
|
:enable-variables="true"
|
||||||
:signature="signatureToApply"
|
:signature="signatureToApply"
|
||||||
:allow-signature="true"
|
:allow-signature="true"
|
||||||
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@toggle-canned-menu="toggleCannedMenu"
|
@toggle-canned-menu="toggleCannedMenu"
|
||||||
@blur="$v.message.$touch"
|
@blur="v$.message.$touch"
|
||||||
>
|
>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<message-signature-missing-alert
|
<message-signature-missing-alert
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</woot-message-editor>
|
</woot-message-editor>
|
||||||
<span v-if="$v.message.$error" class="editor-warning__message">
|
<span v-if="v$.message.$error" class="editor-warning__message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -152,16 +152,16 @@
|
|||||||
@on-select-template="toggleWaTemplate"
|
@on-select-template="toggleWaTemplate"
|
||||||
@on-send="onSendWhatsAppReply"
|
@on-send="onSendWhatsAppReply"
|
||||||
/>
|
/>
|
||||||
<label v-else :class="{ error: $v.message.$error }">
|
<label v-else :class="{ error: v$.message.$error }">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.LABEL') }}
|
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="message"
|
v-model="message"
|
||||||
class="min-h-[5rem]"
|
class="min-h-[5rem]"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('NEW_CONVERSATION.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@input="$v.message.$touch"
|
@input="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="message">
|
<span v-if="v$.message.$error" class="message">
|
||||||
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
{{ $t('NEW_CONVERSATION.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -251,7 +251,8 @@ import WhatsappTemplates from './WhatsappTemplates.vue';
|
|||||||
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
|
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
|
||||||
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
|
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
|
||||||
import { getInboxSource } from 'dashboard/helper/inbox';
|
import { getInboxSource } from 'dashboard/helper/inbox';
|
||||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, requiredIf } from '@vuelidate/validators';
|
||||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||||
import FileUpload from 'vue-upload-component';
|
import FileUpload from 'vue-upload-component';
|
||||||
import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview';
|
import AttachmentPreview from 'dashboard/components/widgets/AttachmentsPreview';
|
||||||
@@ -292,11 +293,9 @@ export default {
|
|||||||
setup() {
|
setup() {
|
||||||
const { fetchSignatureFlagFromUISettings, setSignatureFlagForInbox } =
|
const { fetchSignatureFlagFromUISettings, setSignatureFlagForInbox } =
|
||||||
useUISettings();
|
useUISettings();
|
||||||
|
const v$ = useVuelidate();
|
||||||
|
|
||||||
return {
|
return { fetchSignatureFlagFromUISettings, setSignatureFlagForInbox, v$ };
|
||||||
fetchSignatureFlagFromUISettings,
|
|
||||||
setSignatureFlagForInbox,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -506,8 +505,8 @@ export default {
|
|||||||
},
|
},
|
||||||
onFormSubmit() {
|
onFormSubmit() {
|
||||||
const isFromWhatsApp = false;
|
const isFromWhatsApp = false;
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.createConversation({
|
this.createConversation({
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
:label="$t('FILTER.CUSTOM_VIEWS.ADD.LABEL')"
|
:label="$t('FILTER.CUSTOM_VIEWS.ADD.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:error="
|
:error="
|
||||||
$v.name.$error ? $t('FILTER.CUSTOM_VIEWS.ADD.ERROR_MESSAGE') : ''
|
v$.name.$error ? $t('FILTER.CUSTOM_VIEWS.ADD.ERROR_MESSAGE') : ''
|
||||||
"
|
"
|
||||||
:class="{ error: $v.name.$error }"
|
:class="{ error: v$.name.$error }"
|
||||||
:placeholder="$t('FILTER.CUSTOM_VIEWS.ADD.PLACEHOLDER')"
|
:placeholder="$t('FILTER.CUSTOM_VIEWS.ADD.PLACEHOLDER')"
|
||||||
@blur="$v.name.$touch"
|
@blur="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
@@ -29,7 +29,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
import { CONTACTS_EVENTS } from '../../../helper/AnalyticsHelper/events';
|
||||||
|
|
||||||
@@ -48,7 +49,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -58,7 +61,7 @@ export default {
|
|||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return this.$v.name.$invalid;
|
return this.v$.name.$invalid;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -74,8 +77,8 @@ export default {
|
|||||||
this.$emit('close');
|
this.$emit('close');
|
||||||
},
|
},
|
||||||
async saveCustomViews() {
|
async saveCustomViews() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/>
|
/>
|
||||||
<form class="w-full" @submit.prevent="onCreate">
|
<form class="w-full" @submit.prevent="onCreate">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.selectedLocale.$error }">
|
<label :class="{ error: v$.selectedLocale.$error }">
|
||||||
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.LABEL') }}
|
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.LABEL') }}
|
||||||
<select v-model="selectedLocale">
|
<select v-model="selectedLocale">
|
||||||
<option
|
<option
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
{{ locale.name }}-{{ locale.code }}
|
{{ locale.name }}-{{ locale.code }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedLocale.$error" class="message">
|
<span v-if="v$.selectedLocale.$error" class="message">
|
||||||
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.ERROR') }}
|
{{ $t('HELP_CENTER.PORTAL.ADD_LOCALE.LOCALE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -39,11 +39,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Modal from 'dashboard/components/Modal.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import allLocales from 'shared/constants/locales.js';
|
import allLocales from 'shared/constants/locales.js';
|
||||||
import { PORTALS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
import { PORTALS_EVENTS } from '../../../../helper/AnalyticsHelper/events';
|
||||||
import Modal from 'dashboard/components/Modal.vue';
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
@@ -58,6 +60,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedLocale: '',
|
selectedLocale: '',
|
||||||
@@ -93,8 +98,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onCreate() {
|
async onCreate() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const updatedLocales = this.addedLocales;
|
const updatedLocales = this.addedLocales;
|
||||||
|
|||||||
@@ -25,20 +25,20 @@
|
|||||||
:label="$t('HELP_CENTER.CATEGORY.ADD.NAME.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.ADD.NAME.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.NAME.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.NAME.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.ADD.NAME.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.ADD.NAME.HELP_TEXT')"
|
||||||
:has-error="$v.name.$error"
|
:has-error="v$.name.$error"
|
||||||
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
||||||
@name-change="onNameChange"
|
@name-change="onNameChange"
|
||||||
@icon-change="onClickInsertEmoji"
|
@icon-change="onClickInsertEmoji"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="slug"
|
v-model.trim="slug"
|
||||||
:class="{ error: $v.slug.$error }"
|
:class="{ error: v$.slug.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:error="slugError"
|
:error="slugError"
|
||||||
:label="$t('HELP_CENTER.CATEGORY.ADD.SLUG.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.ADD.SLUG.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.SLUG.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.ADD.SLUG.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.ADD.SLUG.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.ADD.SLUG.HELP_TEXT')"
|
||||||
@input="$v.slug.$touch"
|
@input="v$.slug.$touch"
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.LABEL') }}
|
{{ $t('HELP_CENTER.CATEGORY.ADD.DESCRIPTION.LABEL') }}
|
||||||
@@ -67,8 +67,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||||
import CategoryNameIconInput from './NameEmojiInput.vue';
|
import CategoryNameIconInput from './NameEmojiInput.vue';
|
||||||
@@ -93,6 +94,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -117,7 +121,7 @@ export default {
|
|||||||
: this.portalSlug;
|
: this.portalSlug;
|
||||||
},
|
},
|
||||||
slugError() {
|
slugError() {
|
||||||
if (this.$v.slug.$error) {
|
if (this.v$.slug.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -147,8 +151,8 @@ export default {
|
|||||||
description,
|
description,
|
||||||
locale,
|
locale,
|
||||||
};
|
};
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
:label="$t('HELP_CENTER.CATEGORY.EDIT.NAME.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.EDIT.NAME.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.NAME.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.NAME.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.NAME.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.NAME.HELP_TEXT')"
|
||||||
:has-error="$v.name.$error"
|
:has-error="v$.name.$error"
|
||||||
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
:error-message="$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR')"
|
||||||
:existing-name="category.name"
|
:existing-name="category.name"
|
||||||
:saved-icon="category.icon"
|
:saved-icon="category.icon"
|
||||||
@@ -34,13 +34,13 @@
|
|||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="slug"
|
v-model.trim="slug"
|
||||||
:class="{ error: $v.slug.$error }"
|
:class="{ error: v$.slug.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:error="slugError"
|
:error="slugError"
|
||||||
:label="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.LABEL')"
|
:label="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.LABEL')"
|
||||||
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.PLACEHOLDER')"
|
:placeholder="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.PLACEHOLDER')"
|
||||||
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.HELP_TEXT')"
|
:help-text="$t('HELP_CENTER.CATEGORY.EDIT.SLUG.HELP_TEXT')"
|
||||||
@input="$v.slug.$touch"
|
@input="v$.slug.$touch"
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
{{ $t('HELP_CENTER.CATEGORY.EDIT.DESCRIPTION.LABEL') }}
|
{{ $t('HELP_CENTER.CATEGORY.EDIT.DESCRIPTION.LABEL') }}
|
||||||
@@ -69,8 +69,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
|
||||||
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
|
||||||
import CategoryNameIconInput from './NameEmojiInput.vue';
|
import CategoryNameIconInput from './NameEmojiInput.vue';
|
||||||
@@ -99,6 +100,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
id: this.category.id,
|
id: this.category.id,
|
||||||
@@ -119,7 +123,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
slugError() {
|
slugError() {
|
||||||
if (this.$v.slug.$error) {
|
if (this.v$.slug.$error) {
|
||||||
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -158,8 +162,8 @@ export default {
|
|||||||
slug,
|
slug,
|
||||||
description,
|
description,
|
||||||
};
|
};
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -13,19 +13,19 @@
|
|||||||
<p>{{ $t('GENERAL_SETTINGS.FORM.GENERAL_SECTION.NOTE') }}</p>
|
<p>{{ $t('GENERAL_SETTINGS.FORM.GENERAL_SECTION.NOTE') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 flex-grow-0 flex-shrink-0 flex-[50%]">
|
<div class="p-4 flex-grow-0 flex-shrink-0 flex-[50%]">
|
||||||
<label :class="{ error: $v.name.$error }">
|
<label :class="{ error: v$.name.$error }">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.NAME.LABEL') }}
|
{{ $t('GENERAL_SETTINGS.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model="name"
|
v-model="name"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('GENERAL_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('GENERAL_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.name.$touch"
|
@blur="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.name.$error" class="message">
|
<span v-if="v$.name.$error" class="message">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.NAME.ERROR') }}
|
{{ $t('GENERAL_SETTINGS.FORM.NAME.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.locale.$error }">
|
<label :class="{ error: v$.locale.$error }">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.LABEL') }}
|
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.LABEL') }}
|
||||||
<select v-model="locale">
|
<select v-model="locale">
|
||||||
<option
|
<option
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
{{ lang.name }}
|
{{ lang.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.locale.$error" class="message">
|
<span v-if="v$.locale.$error" class="message">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.ERROR') }}
|
{{ $t('GENERAL_SETTINGS.FORM.LANGUAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
v-if="showAutoResolutionConfig"
|
v-if="showAutoResolutionConfig"
|
||||||
:class="{ error: $v.autoResolveDuration.$error }"
|
:class="{ error: v$.autoResolveDuration.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.LABEL') }}
|
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.LABEL') }}
|
||||||
<input
|
<input
|
||||||
@@ -77,9 +77,9 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.PLACEHOLDER')
|
$t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.autoResolveDuration.$touch"
|
@blur="v$.autoResolveDuration.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.autoResolveDuration.$error" class="message">
|
<span v-if="v$.autoResolveDuration.$error" class="message">
|
||||||
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.ERROR') }}
|
{{ $t('GENERAL_SETTINGS.FORM.AUTO_RESOLVE_DURATION.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -129,7 +129,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minValue, maxValue } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minValue, maxValue } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { useUISettings } from 'dashboard/composables/useUISettings';
|
import { useUISettings } from 'dashboard/composables/useUISettings';
|
||||||
@@ -143,10 +144,9 @@ export default {
|
|||||||
mixins: [accountMixin, configMixin],
|
mixins: [accountMixin, configMixin],
|
||||||
setup() {
|
setup() {
|
||||||
const { updateUISettings } = useUISettings();
|
const { updateUISettings } = useUISettings();
|
||||||
|
const v$ = useVuelidate();
|
||||||
|
|
||||||
return {
|
return { updateUISettings, v$ };
|
||||||
updateUISettings,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -258,8 +258,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async updateAccount() {
|
async updateAccount() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
useAlert(this.$t('GENERAL_SETTINGS.FORM.ERROR'));
|
useAlert(this.$t('GENERAL_SETTINGS.FORM.ERROR'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="h-[calc(100vh-56px)] relative">
|
<div class="h-[calc(100vh-56px)] relative">
|
||||||
<csml-monaco-editor v-model="bot.csmlContent" class="w-full h-full" />
|
<csml-monaco-editor v-model="bot.csmlContent" class="w-full h-full" />
|
||||||
<div
|
<div
|
||||||
v-if="$v.bot.csmlContent.$error"
|
v-if="v$.bot.csmlContent.$error"
|
||||||
class="bg-red-100 dark:bg-red-200 text-white dark:text-white absolute bottom-0 w-full p-2.5 flex items-center text-xs justify-center flex-shrink-0"
|
class="bg-red-100 dark:bg-red-200 text-white dark:text-white absolute bottom-0 w-full p-2.5 flex items-center text-xs justify-center flex-shrink-0"
|
||||||
>
|
>
|
||||||
<span>{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.BOT_CONFIG.ERROR') }}</span>
|
<span>{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.BOT_CONFIG.ERROR') }}</span>
|
||||||
@@ -18,14 +18,14 @@
|
|||||||
@submit.prevent="onSubmit"
|
@submit.prevent="onSubmit"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<label :class="{ error: $v.bot.name.$error }">
|
<label :class="{ error: v$.bot.name.$error }">
|
||||||
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.LABEL') }}
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model="bot.name"
|
v-model="bot.name"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.PLACEHOLDER')"
|
:placeholder="$t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.PLACEHOLDER')"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.bot.name.$error" class="message">
|
<span v-if="v$.bot.name.$error" class="message">
|
||||||
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.ERROR') }}
|
{{ $t('AGENT_BOTS.CSML_BOT_EDITOR.NAME.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -50,7 +50,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required } from '@vuelidate/validators';
|
||||||
import CsmlMonacoEditor from './CSMLMonacoEditor.vue';
|
import CsmlMonacoEditor from './CSMLMonacoEditor.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -61,6 +62,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
bot: {
|
bot: {
|
||||||
name: { required },
|
name: { required },
|
||||||
@@ -78,8 +82,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('submit', {
|
this.$emit('submit', {
|
||||||
|
|||||||
@@ -11,37 +11,37 @@
|
|||||||
@submit.prevent="addAgent()"
|
@submit.prevent="addAgent()"
|
||||||
>
|
>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentName.$error }">
|
<label :class="{ error: v$.agentName.$error }">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.NAME.LABEL') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="agentName"
|
v-model.trim="agentName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AGENT_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.agentName.$touch"
|
@input="v$.agentName.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentType.$error }">
|
<label :class="{ error: v$.agentType.$error }">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.LABEL') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.LABEL') }}
|
||||||
<select v-model="agentType">
|
<select v-model="agentType">
|
||||||
<option v-for="role in roles" :key="role.name" :value="role.name">
|
<option v-for="role in roles" :key="role.name" :value="role.name">
|
||||||
{{ role.label }}
|
{{ role.label }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.agentType.$error" class="message">
|
<span v-if="v$.agentType.$error" class="message">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.ERROR') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.AGENT_TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentEmail.$error }">
|
<label :class="{ error: v$.agentEmail.$error }">
|
||||||
{{ $t('AGENT_MGMT.ADD.FORM.EMAIL.LABEL') }}
|
{{ $t('AGENT_MGMT.ADD.FORM.EMAIL.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="agentEmail"
|
v-model.trim="agentEmail"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_MGMT.ADD.FORM.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('AGENT_MGMT.ADD.FORM.EMAIL.PLACEHOLDER')"
|
||||||
@input="$v.agentEmail.$touch"
|
@input="v$.agentEmail.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.agentEmail.$invalid ||
|
v$.agentEmail.$invalid ||
|
||||||
$v.agentName.$invalid ||
|
v$.agentName.$invalid ||
|
||||||
uiFlags.isCreating
|
uiFlags.isCreating
|
||||||
"
|
"
|
||||||
:button-text="$t('AGENT_MGMT.ADD.FORM.SUBMIT')"
|
:button-text="$t('AGENT_MGMT.ADD.FORM.SUBMIT')"
|
||||||
@@ -67,7 +67,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
|
||||||
@@ -78,6 +79,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
agentName: '',
|
agentName: '',
|
||||||
|
|||||||
@@ -4,33 +4,33 @@
|
|||||||
<woot-modal-header :header-title="pageTitle" />
|
<woot-modal-header :header-title="pageTitle" />
|
||||||
<form class="w-full" @submit.prevent="editAgent()">
|
<form class="w-full" @submit.prevent="editAgent()">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentName.$error }">
|
<label :class="{ error: v$.agentName.$error }">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.NAME.LABEL') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="agentName"
|
v-model.trim="agentName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('AGENT_MGMT.EDIT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AGENT_MGMT.EDIT.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.agentName.$touch"
|
@input="v$.agentName.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentType.$error }">
|
<label :class="{ error: v$.agentType.$error }">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.LABEL') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.LABEL') }}
|
||||||
<select v-model="agentType">
|
<select v-model="agentType">
|
||||||
<option v-for="role in roles" :key="role.name" :value="role.name">
|
<option v-for="role in roles" :key="role.name" :value="role.name">
|
||||||
{{ role.label }}
|
{{ role.label }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.agentType.$error" class="message">
|
<span v-if="v$.agentType.$error" class="message">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.ERROR') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.agentAvailability.$error }">
|
<label :class="{ error: v$.agentAvailability.$error }">
|
||||||
{{ $t('PROFILE_SETTINGS.FORM.AVAILABILITY.LABEL') }}
|
{{ $t('PROFILE_SETTINGS.FORM.AVAILABILITY.LABEL') }}
|
||||||
<select v-model="agentAvailability">
|
<select v-model="agentAvailability">
|
||||||
<option
|
<option
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
{{ role.label }}
|
{{ role.label }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.agentAvailability.$error" class="message">
|
<span v-if="v$.agentAvailability.$error" class="message">
|
||||||
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_AVAILABILITY.ERROR') }}
|
{{ $t('AGENT_MGMT.EDIT.FORM.AGENT_AVAILABILITY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
<div class="w-[50%]">
|
<div class="w-[50%]">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.agentType.$invalid ||
|
v$.agentType.$invalid ||
|
||||||
$v.agentName.$invalid ||
|
v$.agentName.$invalid ||
|
||||||
uiFlags.isUpdating
|
uiFlags.isUpdating
|
||||||
"
|
"
|
||||||
:button-text="$t('AGENT_MGMT.EDIT.FORM.SUBMIT')"
|
:button-text="$t('AGENT_MGMT.EDIT.FORM.SUBMIT')"
|
||||||
@@ -77,7 +77,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
@@ -118,6 +119,9 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
roles: [
|
roles: [
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
<form class="flex w-full" @submit.prevent="addAttributes">
|
<form class="flex w-full" @submit.prevent="addAttributes">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.attributeModel.$error }">
|
<label :class="{ error: v$.attributeModel.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.LABEL') }}
|
||||||
<select v-model="attributeModel">
|
<select v-model="attributeModel">
|
||||||
<option v-for="model in models" :key="model.id" :value="model.id">
|
<option v-for="model in models" :key="model.id" :value="model.id">
|
||||||
{{ model.option }}
|
{{ model.option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.attributeModel.$error" class="message">
|
<span v-if="v$.attributeModel.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.MODEL.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -20,46 +20,46 @@
|
|||||||
v-model="displayName"
|
v-model="displayName"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.displayName.$error }"
|
:class="{ error: v$.displayName.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.displayName.$error
|
v$.displayName.$error
|
||||||
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="onDisplayNameChange"
|
@input="onDisplayNameChange"
|
||||||
@blur="$v.displayName.$touch"
|
@blur="v$.displayName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="attributeKey"
|
v-model="attributeKey"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.attributeKey.$error }"
|
:class="{ error: v$.attributeKey.$error }"
|
||||||
:error="$v.attributeKey.$error ? keyErrorMessage : ''"
|
:error="v$.attributeKey.$error ? keyErrorMessage : ''"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
||||||
@blur="$v.attributeKey.$touch"
|
@blur="v$.attributeKey.$touch"
|
||||||
/>
|
/>
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label :class="{ error: v$.description.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="description"
|
v-model="description"
|
||||||
rows="3"
|
rows="3"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.description.$touch"
|
@blur="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.description.$error" class="message">
|
<span v-if="v$.description.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.attributeType.$error }">
|
<label :class="{ error: v$.attributeType.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
||||||
<select v-model="attributeType">
|
<select v-model="attributeType">
|
||||||
<option v-for="type in types" :key="type.id" :value="type.id">
|
<option v-for="type in types" :key="type.id" :value="type.id">
|
||||||
{{ type.option }}
|
{{ type.option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.attributeType.$error" class="message">
|
<span v-if="v$.attributeType.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -126,7 +126,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { convertToAttributeSlug } from 'dashboard/helper/commons.js';
|
import { convertToAttributeSlug } from 'dashboard/helper/commons.js';
|
||||||
@@ -139,7 +140,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
displayName: '',
|
displayName: '',
|
||||||
@@ -174,14 +177,14 @@ export default {
|
|||||||
},
|
},
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return (
|
return (
|
||||||
this.$v.displayName.$invalid ||
|
this.v$.displayName.$invalid ||
|
||||||
this.$v.description.$invalid ||
|
this.v$.description.$invalid ||
|
||||||
this.uiFlags.isCreating ||
|
this.uiFlags.isCreating ||
|
||||||
this.isTagInputInvalid
|
this.isTagInputInvalid
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
keyErrorMessage() {
|
keyErrorMessage() {
|
||||||
if (!this.$v.attributeKey.isKey) {
|
if (!this.v$.attributeKey.isKey) {
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
||||||
}
|
}
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
||||||
@@ -237,8 +240,8 @@ export default {
|
|||||||
this.regexEnabled = !this.regexEnabled;
|
this.regexEnabled = !this.regexEnabled;
|
||||||
},
|
},
|
||||||
async addAttributes() {
|
async addAttributes() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.regexEnabled) {
|
if (!this.regexEnabled) {
|
||||||
|
|||||||
@@ -7,46 +7,46 @@
|
|||||||
v-model.trim="displayName"
|
v-model.trim="displayName"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.displayName.$error }"
|
:class="{ error: v$.displayName.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.displayName.$error
|
v$.displayName.$error
|
||||||
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
? $t('ATTRIBUTES_MGMT.ADD.FORM.NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.displayName.$touch"
|
@blur="v$.displayName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="attributeKey"
|
v-model.trim="attributeKey"
|
||||||
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
:label="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.attributeKey.$error }"
|
:class="{ error: v$.attributeKey.$error }"
|
||||||
:error="$v.attributeKey.$error ? keyErrorMessage : ''"
|
:error="v$.attributeKey.$error ? keyErrorMessage : ''"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.PLACEHOLDER')"
|
||||||
readonly
|
readonly
|
||||||
@blur="$v.attributeKey.$touch"
|
@blur="v$.attributeKey.$touch"
|
||||||
/>
|
/>
|
||||||
<label :class="{ error: $v.description.$error }">
|
<label :class="{ error: v$.description.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
rows="5"
|
rows="5"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('ATTRIBUTES_MGMT.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.description.$touch"
|
@blur="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.description.$error" class="message">
|
<span v-if="v$.description.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.DESC.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.attributeType.$error }">
|
<label :class="{ error: v$.attributeType.$error }">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.LABEL') }}
|
||||||
<select v-model="attributeType" disabled>
|
<select v-model="attributeType" disabled>
|
||||||
<option v-for="type in types" :key="type.id" :value="type.id">
|
<option v-for="type in types" :key="type.id" :value="type.id">
|
||||||
{{ type.option }}
|
{{ type.option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.attributeType.$error" class="message">
|
<span v-if="v$.attributeType.$error" class="message">
|
||||||
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
{{ $t('ATTRIBUTES_MGMT.ADD.FORM.TYPE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -109,8 +109,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { ATTRIBUTE_TYPES } from './constants';
|
import { ATTRIBUTE_TYPES } from './constants';
|
||||||
import customAttributeMixin from '../../../../mixins/customAttributeMixin';
|
import customAttributeMixin from '../../../../mixins/customAttributeMixin';
|
||||||
export default {
|
export default {
|
||||||
@@ -126,6 +127,9 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
displayName: '',
|
displayName: '',
|
||||||
@@ -173,7 +177,7 @@ export default {
|
|||||||
return this.values.map(item => item.name);
|
return this.values.map(item => item.name);
|
||||||
},
|
},
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return this.$v.description.$invalid || this.isMultiselectInvalid;
|
return this.v$.description.$invalid || this.isMultiselectInvalid;
|
||||||
},
|
},
|
||||||
isMultiselectInvalid() {
|
isMultiselectInvalid() {
|
||||||
return (
|
return (
|
||||||
@@ -194,7 +198,7 @@ export default {
|
|||||||
).id;
|
).id;
|
||||||
},
|
},
|
||||||
keyErrorMessage() {
|
keyErrorMessage() {
|
||||||
if (!this.$v.attributeKey.isKey) {
|
if (!this.v$.attributeKey.isKey) {
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.IN_VALID');
|
||||||
}
|
}
|
||||||
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
return this.$t('ATTRIBUTES_MGMT.ADD.FORM.KEY.ERROR');
|
||||||
@@ -237,8 +241,8 @@ export default {
|
|||||||
this.values = this.setAttributeListValue;
|
this.values = this.setAttributeListValue;
|
||||||
},
|
},
|
||||||
async editAttributes() {
|
async editAttributes() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.regexEnabled) {
|
if (!this.regexEnabled) {
|
||||||
|
|||||||
@@ -7,32 +7,28 @@
|
|||||||
v-model="automation.name"
|
v-model="automation.name"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.name.$error }"
|
:class="{ error: errors.name }"
|
||||||
:error="
|
:error="errors.name ? $t('AUTOMATION.ADD.FORM.NAME.ERROR') : ''"
|
||||||
$v.automation.name.$error
|
|
||||||
? $t('AUTOMATION.ADD.FORM.NAME.ERROR')
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.automation.name.$touch"
|
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="automation.description"
|
v-model="automation.description"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.description.$error }"
|
:class="{ error: errors.description }"
|
||||||
:error="
|
:error="
|
||||||
$v.automation.description.$error
|
errors.description ? $t('AUTOMATION.ADD.FORM.DESC.ERROR') : ''
|
||||||
? $t('AUTOMATION.ADD.FORM.DESC.ERROR')
|
|
||||||
: ''
|
|
||||||
"
|
"
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.automation.description.$touch"
|
|
||||||
/>
|
/>
|
||||||
<div class="event_wrapper">
|
<div class="mb-6">
|
||||||
<label :class="{ error: $v.automation.event_name.$error }">
|
<label :class="{ error: errors.event_name }">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
||||||
<select v-model="automation.event_name" @change="onEventChange()">
|
<select
|
||||||
|
v-model="automation.event_name"
|
||||||
|
class="m-0"
|
||||||
|
@change="onEventChange()"
|
||||||
|
>
|
||||||
<option
|
<option
|
||||||
v-for="event in automationRuleEvents"
|
v-for="event in automationRuleEvents"
|
||||||
:key="event.key"
|
:key="event.key"
|
||||||
@@ -41,11 +37,14 @@
|
|||||||
{{ event.value }}
|
{{ event.value }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.automation.event_name.$error" class="message">
|
<span v-if="errors.event_name" class="message">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<p v-if="hasAutomationMutated" class="info-message">
|
<p
|
||||||
|
v-if="hasAutomationMutated"
|
||||||
|
class="text-xs text-green-500 dark:text-green-500 text-right"
|
||||||
|
>
|
||||||
{{ $t('AUTOMATION.FORM.RESET_MESSAGE') }}
|
{{ $t('AUTOMATION.FORM.RESET_MESSAGE') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +72,11 @@
|
|||||||
:custom-attribute-type="
|
:custom-attribute-type="
|
||||||
getCustomAttributeType(automation.conditions[i].attribute_key)
|
getCustomAttributeType(automation.conditions[i].attribute_key)
|
||||||
"
|
"
|
||||||
:v="$v.automation.conditions.$each[i]"
|
:error-message="
|
||||||
|
errors[`condition_${i}`]
|
||||||
|
? $t(`AUTOMATION.ERRORS.${errors[`condition_${i}`]}`)
|
||||||
|
: ''
|
||||||
|
"
|
||||||
@resetFilter="resetFilter(i, automation.conditions[i])"
|
@resetFilter="resetFilter(i, automation.conditions[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -110,7 +113,11 @@
|
|||||||
:show-action-input="
|
:show-action-input="
|
||||||
showActionInput(automation.actions[i].action_name)
|
showActionInput(automation.actions[i].action_name)
|
||||||
"
|
"
|
||||||
:v="$v.automation.actions.$each[i]"
|
:error-message="
|
||||||
|
errors[`action_${i}`]
|
||||||
|
? $t(`AUTOMATION.ERRORS.${errors[`action_${i}`]}`)
|
||||||
|
: ''
|
||||||
|
"
|
||||||
@resetAction="resetAction(i)"
|
@resetAction="resetAction(i)"
|
||||||
@removeAction="removeAction(i)"
|
@removeAction="removeAction(i)"
|
||||||
/>
|
/>
|
||||||
@@ -146,9 +153,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import automationMethodsMixin from 'dashboard/mixins/automations/methodsMixin';
|
import automationMethodsMixin from 'dashboard/mixins/automations/methodsMixin';
|
||||||
import automationValidationsMixin from 'dashboard/mixins/automations/validationsMixin';
|
|
||||||
import filterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue';
|
import filterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue';
|
||||||
import automationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue';
|
import automationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue';
|
||||||
|
// import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AUTOMATION_RULE_EVENTS,
|
AUTOMATION_RULE_EVENTS,
|
||||||
@@ -160,14 +167,13 @@ export default {
|
|||||||
filterInputBox,
|
filterInputBox,
|
||||||
automationActionInput,
|
automationActionInput,
|
||||||
},
|
},
|
||||||
mixins: [automationMethodsMixin, automationValidationsMixin],
|
mixins: [automationMethodsMixin],
|
||||||
props: {
|
props: {
|
||||||
onClose: {
|
onClose: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
automationTypes: JSON.parse(JSON.stringify(AUTOMATIONS)),
|
automationTypes: JSON.parse(JSON.stringify(AUTOMATIONS)),
|
||||||
@@ -198,6 +204,7 @@ export default {
|
|||||||
showDeleteConfirmationModal: false,
|
showDeleteConfirmationModal: false,
|
||||||
allCustomAttributes: [],
|
allCustomAttributes: [],
|
||||||
mode: 'create',
|
mode: 'create',
|
||||||
|
errors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -237,15 +244,3 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.event_wrapper {
|
|
||||||
select {
|
|
||||||
@apply m-0;
|
|
||||||
}
|
|
||||||
.info-message {
|
|
||||||
@apply text-xs text-green-500 dark:text-green-500 text-right;
|
|
||||||
}
|
|
||||||
|
|
||||||
@apply mb-6;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -7,30 +7,22 @@
|
|||||||
v-model="automation.name"
|
v-model="automation.name"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.NAME.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.name.$error }"
|
:class="{ error: errors.name }"
|
||||||
:error="
|
:error="errors.name ? $t('AUTOMATION.ADD.FORM.NAME.ERROR') : ''"
|
||||||
$v.automation.name.$error
|
|
||||||
? $t('AUTOMATION.ADD.FORM.NAME.ERROR')
|
|
||||||
: ''
|
|
||||||
"
|
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
@blur="$v.automation.name.$touch"
|
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="automation.description"
|
v-model="automation.description"
|
||||||
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
:label="$t('AUTOMATION.ADD.FORM.DESC.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.automation.description.$error }"
|
:class="{ error: errors.description }"
|
||||||
:error="
|
:error="
|
||||||
$v.automation.description.$error
|
errors.description ? $t('AUTOMATION.ADD.FORM.DESC.ERROR') : ''
|
||||||
? $t('AUTOMATION.ADD.FORM.DESC.ERROR')
|
|
||||||
: ''
|
|
||||||
"
|
"
|
||||||
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
:placeholder="$t('AUTOMATION.ADD.FORM.DESC.PLACEHOLDER')"
|
||||||
@blur="$v.automation.description.$touch"
|
|
||||||
/>
|
/>
|
||||||
<div class="event_wrapper">
|
<div class="event_wrapper">
|
||||||
<label :class="{ error: $v.automation.event_name.$error }">
|
<label :class="{ error: errors.event_name }">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.LABEL') }}
|
||||||
<select v-model="automation.event_name" @change="onEventChange()">
|
<select v-model="automation.event_name" @change="onEventChange()">
|
||||||
<option
|
<option
|
||||||
@@ -41,7 +33,7 @@
|
|||||||
{{ event.value }}
|
{{ event.value }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.automation.event_name.$error" class="message">
|
<span v-if="errors.event_name" class="message">
|
||||||
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
{{ $t('AUTOMATION.ADD.FORM.EVENT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -70,7 +62,11 @@
|
|||||||
getCustomAttributeType(automation.conditions[i].attribute_key)
|
getCustomAttributeType(automation.conditions[i].attribute_key)
|
||||||
"
|
"
|
||||||
:show-query-operator="i !== automation.conditions.length - 1"
|
:show-query-operator="i !== automation.conditions.length - 1"
|
||||||
:v="$v.automation.conditions.$each[i]"
|
:error-message="
|
||||||
|
errors[`condition_${i}`]
|
||||||
|
? $t(`AUTOMATION.ERRORS.${errors[`condition_${i}`]}`)
|
||||||
|
: ''
|
||||||
|
"
|
||||||
@resetFilter="resetFilter(i, automation.conditions[i])"
|
@resetFilter="resetFilter(i, automation.conditions[i])"
|
||||||
@removeFilter="removeFilter(i)"
|
@removeFilter="removeFilter(i)"
|
||||||
/>
|
/>
|
||||||
@@ -103,7 +99,11 @@
|
|||||||
:action-types="automationActionTypes"
|
:action-types="automationActionTypes"
|
||||||
:dropdown-values="getActionDropdownValues(action.action_name)"
|
:dropdown-values="getActionDropdownValues(action.action_name)"
|
||||||
:show-action-input="showActionInput(action.action_name)"
|
:show-action-input="showActionInput(action.action_name)"
|
||||||
:v="$v.automation.actions.$each[i]"
|
:error-message="
|
||||||
|
errors[`action_${i}`]
|
||||||
|
? $t(`AUTOMATION.ERRORS.${errors[`action_${i}`]}`)
|
||||||
|
: ''
|
||||||
|
"
|
||||||
:initial-file-name="getFileName(action, automation.files)"
|
:initial-file-name="getFileName(action, automation.files)"
|
||||||
@resetAction="resetAction(i)"
|
@resetAction="resetAction(i)"
|
||||||
@removeAction="removeAction(i)"
|
@removeAction="removeAction(i)"
|
||||||
@@ -144,7 +144,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import automationMethodsMixin from 'dashboard/mixins/automations/methodsMixin';
|
import automationMethodsMixin from 'dashboard/mixins/automations/methodsMixin';
|
||||||
import automationValidationsMixin from 'dashboard/mixins/automations/validationsMixin';
|
|
||||||
import filterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue';
|
import filterInputBox from 'dashboard/components/widgets/FilterInput/Index.vue';
|
||||||
import automationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue';
|
import automationActionInput from 'dashboard/components/widgets/AutomationActionInput.vue';
|
||||||
|
|
||||||
@@ -159,7 +158,7 @@ export default {
|
|||||||
filterInputBox,
|
filterInputBox,
|
||||||
automationActionInput,
|
automationActionInput,
|
||||||
},
|
},
|
||||||
mixins: [automationMethodsMixin, automationValidationsMixin],
|
mixins: [automationMethodsMixin],
|
||||||
props: {
|
props: {
|
||||||
onClose: {
|
onClose: {
|
||||||
type: Function,
|
type: Function,
|
||||||
@@ -181,6 +180,7 @@ export default {
|
|||||||
showDeleteConfirmationModal: false,
|
showDeleteConfirmationModal: false,
|
||||||
allCustomAttributes: [],
|
allCustomAttributes: [],
|
||||||
mode: 'edit',
|
mode: 'edit',
|
||||||
|
errors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-auto overflow-auto flex flex-col">
|
<div class="flex flex-col h-auto overflow-auto">
|
||||||
<woot-modal-header
|
<woot-modal-header
|
||||||
:header-title="$t('CAMPAIGN.ADD.TITLE')"
|
:header-title="$t('CAMPAIGN.ADD.TITLE')"
|
||||||
:header-content="$t('CAMPAIGN.ADD.DESC')"
|
:header-content="$t('CAMPAIGN.ADD.DESC')"
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
v-model="title"
|
v-model="title"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
:error="$v.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
:error="v$.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
||||||
@blur="$v.title.$touch"
|
@blur="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="isOngoingType" class="editor-wrap">
|
<div v-if="isOngoingType" class="editor-wrap">
|
||||||
@@ -24,38 +24,38 @@
|
|||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="message"
|
v-model="message"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:class="{ editor_warning: $v.message.$error }"
|
:class="{ editor_warning: v$.message.$error }"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@blur="$v.message.$touch"
|
@blur="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="editor-warning__message">
|
<span v-if="v$.message.$error" class="editor-warning__message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label v-else :class="{ error: $v.message.$error }">
|
<label v-else :class="{ error: v$.message.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.LABEL') }}
|
||||||
<textarea
|
<textarea
|
||||||
v-model="message"
|
v-model="message"
|
||||||
rows="5"
|
rows="5"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@blur="$v.message.$touch"
|
@blur="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="message">
|
<span v-if="v$.message.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label :class="{ error: $v.selectedInbox.$error }">
|
<label :class="{ error: v$.selectedInbox.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
||||||
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
<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.name" :value="item.id">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedInbox.$error" class="message">
|
<span v-if="v$.selectedInbox.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
<label
|
<label
|
||||||
v-if="isOneOffType"
|
v-if="isOneOffType"
|
||||||
class="multiselect-wrap--small"
|
class="multiselect-wrap--small"
|
||||||
:class="{ error: $v.selectedAudience.$error }"
|
:class="{ error: v$.selectedAudience.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.LABEL') }}
|
||||||
<multiselect
|
<multiselect
|
||||||
@@ -79,17 +79,17 @@
|
|||||||
selected-label
|
selected-label
|
||||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||||
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
||||||
@blur="$v.selectedAudience.$touch"
|
@blur="v$.selectedAudience.$touch"
|
||||||
@select="$v.selectedAudience.$touch"
|
@select="v$.selectedAudience.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.selectedAudience.$error" class="message">
|
<span v-if="v$.selectedAudience.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.AUDIENCE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
v-if="isOngoingType"
|
v-if="isOngoingType"
|
||||||
:class="{ error: $v.selectedSender.$error }"
|
:class="{ error: v$.selectedSender.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
||||||
<select v-model="selectedSender">
|
<select v-model="selectedSender">
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
{{ sender.name }}
|
{{ sender.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedSender.$error" class="message">
|
<span v-if="v$.selectedSender.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -121,26 +121,26 @@
|
|||||||
v-model="endPoint"
|
v-model="endPoint"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.endPoint.$error }"
|
:class="{ error: v$.endPoint.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
v$.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
||||||
@blur="$v.endPoint.$touch"
|
@blur="v$.endPoint.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="isOngoingType"
|
v-if="isOngoingType"
|
||||||
v-model="timeOnPage"
|
v-model="timeOnPage"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.timeOnPage.$error }"
|
:class="{ error: v$.timeOnPage.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.timeOnPage.$error
|
v$.timeOnPage.$error
|
||||||
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
||||||
@blur="$v.timeOnPage.$touch"
|
@blur="v$.timeOnPage.$touch"
|
||||||
/>
|
/>
|
||||||
<label v-if="isOngoingType">
|
<label v-if="isOngoingType">
|
||||||
<input
|
<input
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button :is-loading="uiFlags.isCreating">
|
<woot-button :is-loading="uiFlags.isCreating">
|
||||||
{{ $t('CAMPAIGN.ADD.CREATE_BUTTON_TEXT') }}
|
{{ $t('CAMPAIGN.ADD.CREATE_BUTTON_TEXT') }}
|
||||||
</woot-button>
|
</woot-button>
|
||||||
@@ -176,7 +176,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
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 campaignMixin from 'shared/mixins/campaignMixin';
|
||||||
@@ -189,8 +190,10 @@ export default {
|
|||||||
WootDateTimePicker,
|
WootDateTimePicker,
|
||||||
WootMessageEditor,
|
WootMessageEditor,
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [campaignMixin],
|
mixins: [campaignMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '',
|
title: '',
|
||||||
@@ -343,8 +346,8 @@ export default {
|
|||||||
return campaignDetails;
|
return campaignDetails;
|
||||||
},
|
},
|
||||||
async addCampaign() {
|
async addCampaign() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
v-model="title"
|
v-model="title"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TITLE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
:error="$v.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
:error="v$.title.$error ? $t('CAMPAIGN.ADD.FORM.TITLE.ERROR') : ''"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TITLE.PLACEHOLDER')"
|
||||||
@blur="$v.title.$touch"
|
@blur="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="editor-wrap">
|
<div class="editor-wrap">
|
||||||
<label>
|
<label>
|
||||||
@@ -20,28 +20,28 @@
|
|||||||
v-model="message"
|
v-model="message"
|
||||||
class="message-editor"
|
class="message-editor"
|
||||||
:is-format-mode="true"
|
:is-format-mode="true"
|
||||||
:class="{ editor_warning: $v.message.$error }"
|
:class="{ editor_warning: v$.message.$error }"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.MESSAGE.PLACEHOLDER')"
|
||||||
@input="$v.message.$touch"
|
@input="v$.message.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.message.$error" class="editor-warning__message">
|
<span v-if="v$.message.$error" class="editor-warning__message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.MESSAGE.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label :class="{ error: $v.selectedInbox.$error }">
|
<label :class="{ error: v$.selectedInbox.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.LABEL') }}
|
||||||
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
<select v-model="selectedInbox" @change="onChangeInbox($event)">
|
||||||
<option v-for="item in inboxes" :key="item.id" :value="item.id">
|
<option v-for="item in inboxes" :key="item.id" :value="item.id">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedInbox.$error" class="message">
|
<span v-if="v$.selectedInbox.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.INBOX.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label :class="{ error: $v.selectedSender.$error }">
|
<label :class="{ error: v$.selectedSender.$error }">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.LABEL') }}
|
||||||
<select v-model="selectedSender">
|
<select v-model="selectedSender">
|
||||||
<option
|
<option
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
{{ sender.name }}
|
{{ sender.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<span v-if="$v.selectedSender.$error" class="message">
|
<span v-if="v$.selectedSender.$error" class="message">
|
||||||
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
{{ $t('CAMPAIGN.ADD.FORM.SENT_BY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -60,25 +60,25 @@
|
|||||||
v-model="endPoint"
|
v-model="endPoint"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.END_POINT.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.endPoint.$error }"
|
:class="{ error: v$.endPoint.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
v$.endPoint.$error ? $t('CAMPAIGN.ADD.FORM.END_POINT.ERROR') : ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.END_POINT.PLACEHOLDER')"
|
||||||
@blur="$v.endPoint.$touch"
|
@blur="v$.endPoint.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="timeOnPage"
|
v-model="timeOnPage"
|
||||||
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
:label="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.LABEL')"
|
||||||
type="text"
|
type="text"
|
||||||
:class="{ error: $v.timeOnPage.$error }"
|
:class="{ error: v$.timeOnPage.$error }"
|
||||||
:error="
|
:error="
|
||||||
$v.timeOnPage.$error
|
v$.timeOnPage.$error
|
||||||
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
? $t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
:placeholder="$t('CAMPAIGN.ADD.FORM.TIME_ON_PAGE.PLACEHOLDER')"
|
||||||
@blur="$v.timeOnPage.$touch"
|
@blur="v$.timeOnPage.$touch"
|
||||||
/>
|
/>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -113,7 +113,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
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 campaignMixin from 'shared/mixins/campaignMixin';
|
||||||
@@ -130,6 +131,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '',
|
title: '',
|
||||||
@@ -252,8 +256,8 @@ export default {
|
|||||||
this.loadInboxMembers();
|
this.loadInboxMembers();
|
||||||
},
|
},
|
||||||
async editCampaign() {
|
async editCampaign() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,38 +7,38 @@
|
|||||||
/>
|
/>
|
||||||
<form class="flex flex-col w-full" @submit.prevent="addCannedResponse()">
|
<form class="flex flex-col w-full" @submit.prevent="addCannedResponse()">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.shortCode.$error }">
|
<label :class="{ error: v$.shortCode.$error }">
|
||||||
{{ $t('CANNED_MGMT.ADD.FORM.SHORT_CODE.LABEL') }}
|
{{ $t('CANNED_MGMT.ADD.FORM.SHORT_CODE.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="shortCode"
|
v-model.trim="shortCode"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CANNED_MGMT.ADD.FORM.SHORT_CODE.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.ADD.FORM.SHORT_CODE.PLACEHOLDER')"
|
||||||
@input="$v.shortCode.$touch"
|
@input="v$.shortCode.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.content.$error }">
|
<label :class="{ error: v$.content.$error }">
|
||||||
{{ $t('CANNED_MGMT.ADD.FORM.CONTENT.LABEL') }}
|
{{ $t('CANNED_MGMT.ADD.FORM.CONTENT.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="editor-wrap">
|
<div class="editor-wrap">
|
||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="content"
|
v-model="content"
|
||||||
class="message-editor [&>div]:px-1"
|
class="message-editor [&>div]:px-1"
|
||||||
:class="{ editor_warning: $v.content.$error }"
|
:class="{ editor_warning: v$.content.$error }"
|
||||||
:enable-variables="true"
|
:enable-variables="true"
|
||||||
:enable-canned-responses="false"
|
:enable-canned-responses="false"
|
||||||
:placeholder="$t('CANNED_MGMT.ADD.FORM.CONTENT.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.ADD.FORM.CONTENT.PLACEHOLDER')"
|
||||||
@blur="$v.content.$touch"
|
@blur="v$.content.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.content.$invalid ||
|
v$.content.$invalid ||
|
||||||
$v.shortCode.$invalid ||
|
v$.shortCode.$invalid ||
|
||||||
addCanned.showLoading
|
addCanned.showLoading
|
||||||
"
|
"
|
||||||
:button-text="$t('CANNED_MGMT.ADD.FORM.SUBMIT')"
|
:button-text="$t('CANNED_MGMT.ADD.FORM.SUBMIT')"
|
||||||
@@ -54,7 +54,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
@@ -77,6 +78,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shortCode: '',
|
shortCode: '',
|
||||||
@@ -101,8 +105,8 @@ export default {
|
|||||||
resetForm() {
|
resetForm() {
|
||||||
this.shortCode = '';
|
this.shortCode = '';
|
||||||
this.content = '';
|
this.content = '';
|
||||||
this.$v.shortCode.$reset();
|
this.v$.shortCode.$reset();
|
||||||
this.$v.content.$reset();
|
this.v$.content.$reset();
|
||||||
},
|
},
|
||||||
addCannedResponse() {
|
addCannedResponse() {
|
||||||
// Show loading on button
|
// Show loading on button
|
||||||
|
|||||||
@@ -4,38 +4,38 @@
|
|||||||
<woot-modal-header :header-title="pageTitle" />
|
<woot-modal-header :header-title="pageTitle" />
|
||||||
<form class="flex flex-col w-full" @submit.prevent="editCannedResponse()">
|
<form class="flex flex-col w-full" @submit.prevent="editCannedResponse()">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.shortCode.$error }">
|
<label :class="{ error: v$.shortCode.$error }">
|
||||||
{{ $t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.LABEL') }}
|
{{ $t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="shortCode"
|
v-model.trim="shortCode"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.EDIT.FORM.SHORT_CODE.PLACEHOLDER')"
|
||||||
@input="$v.shortCode.$touch"
|
@input="v$.shortCode.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.content.$error }">
|
<label :class="{ error: v$.content.$error }">
|
||||||
{{ $t('CANNED_MGMT.EDIT.FORM.CONTENT.LABEL') }}
|
{{ $t('CANNED_MGMT.EDIT.FORM.CONTENT.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="editor-wrap">
|
<div class="editor-wrap">
|
||||||
<woot-message-editor
|
<woot-message-editor
|
||||||
v-model="content"
|
v-model="content"
|
||||||
class="message-editor [&>div]:px-1"
|
class="message-editor [&>div]:px-1"
|
||||||
:class="{ editor_warning: $v.content.$error }"
|
:class="{ editor_warning: v$.content.$error }"
|
||||||
:enable-variables="true"
|
:enable-variables="true"
|
||||||
:enable-canned-responses="false"
|
:enable-canned-responses="false"
|
||||||
:placeholder="$t('CANNED_MGMT.EDIT.FORM.CONTENT.PLACEHOLDER')"
|
:placeholder="$t('CANNED_MGMT.EDIT.FORM.CONTENT.PLACEHOLDER')"
|
||||||
@blur="$v.content.$touch"
|
@blur="v$.content.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.content.$invalid ||
|
v$.content.$invalid ||
|
||||||
$v.shortCode.$invalid ||
|
v$.shortCode.$invalid ||
|
||||||
editCanned.showLoading
|
editCanned.showLoading
|
||||||
"
|
"
|
||||||
:button-text="$t('CANNED_MGMT.EDIT.FORM.SUBMIT')"
|
:button-text="$t('CANNED_MGMT.EDIT.FORM.SUBMIT')"
|
||||||
@@ -52,7 +52,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* eslint no-console: 0 */
|
/* eslint no-console: 0 */
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } 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 WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
@@ -70,6 +71,9 @@ export default {
|
|||||||
edshortCode: { type: String, default: '' },
|
edshortCode: { type: String, default: '' },
|
||||||
onClose: { type: Function, default: () => {} },
|
onClose: { type: Function, default: () => {} },
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editCanned: {
|
editCanned: {
|
||||||
@@ -97,14 +101,14 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setPageName({ name }) {
|
setPageName({ name }) {
|
||||||
this.$v.content.$touch();
|
this.v$.content.$touch();
|
||||||
this.content = name;
|
this.content = name;
|
||||||
},
|
},
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.shortCode = '';
|
this.shortCode = '';
|
||||||
this.content = '';
|
this.content = '';
|
||||||
this.$v.shortCode.$reset();
|
this.v$.shortCode.$reset();
|
||||||
this.$v.content.$reset();
|
this.v$.content.$reset();
|
||||||
},
|
},
|
||||||
editCannedResponse() {
|
editCannedResponse() {
|
||||||
// Show loading on button
|
// Show loading on button
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-3/5">
|
<div class="w-3/5">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.selectedAgents.$error }">
|
<label :class="{ error: v$.selectedAgents.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.AGENTS.TITLE') }}
|
{{ $t('INBOX_MGMT.ADD.AGENTS.TITLE') }}
|
||||||
<multiselect
|
<multiselect
|
||||||
v-model="selectedAgents"
|
v-model="selectedAgents"
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||||
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.AGENTS.PICK_AGENTS')"
|
:placeholder="$t('INBOX_MGMT.ADD.AGENTS.PICK_AGENTS')"
|
||||||
@select="$v.selectedAgents.$touch"
|
@select="v$.selectedAgents.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.selectedAgents.$error" class="message">
|
<span v-if="v$.selectedAgents.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.AGENTS.VALIDATION_ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.AGENTS.VALIDATION_ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -52,12 +52,12 @@ import { useAlert } from 'dashboard/composables';
|
|||||||
import InboxMembersAPI from '../../../../api/inboxMembers';
|
import InboxMembersAPI from '../../../../api/inboxMembers';
|
||||||
import router from '../../../index';
|
import router from '../../../index';
|
||||||
import PageHeader from '../SettingsSubPageHeader.vue';
|
import PageHeader from '../SettingsSubPageHeader.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
PageHeader,
|
PageHeader,
|
||||||
},
|
},
|
||||||
|
|
||||||
validations: {
|
validations: {
|
||||||
selectedAgents: {
|
selectedAgents: {
|
||||||
isEmpty() {
|
isEmpty() {
|
||||||
@@ -65,24 +65,23 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedAgents: [],
|
selectedAgents: [],
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
agentList: 'agents/getAgents',
|
agentList: 'agents/getAgents',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch('agents/get');
|
this.$store.dispatch('agents/get');
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async addAgents() {
|
async addAgents() {
|
||||||
this.isCreating = true;
|
this.isCreating = true;
|
||||||
|
|||||||
@@ -19,37 +19,37 @@
|
|||||||
<div v-if="isIMAPEnabled" class="mb-6">
|
<div v-if="isIMAPEnabled" class="mb-6">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="address"
|
v-model.trim="address"
|
||||||
:class="{ error: $v.address.$error }"
|
:class="{ error: v$.address.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.IMAP.ADDRESS.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.ADDRESS.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.ADDRESS.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.ADDRESS.PLACE_HOLDER')"
|
||||||
@blur="$v.address.$touch"
|
@blur="v$.address.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="port"
|
v-model="port"
|
||||||
type="number"
|
type="number"
|
||||||
:class="{ error: $v.port.$error }"
|
:class="{ error: v$.port.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.IMAP.PORT.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.PORT.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.PORT.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.PORT.PLACE_HOLDER')"
|
||||||
@blur="$v.port.$touch"
|
@blur="v$.port.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="login"
|
v-model="login"
|
||||||
:class="{ error: $v.login.$error }"
|
:class="{ error: v$.login.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.IMAP.LOGIN.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.LOGIN.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.LOGIN.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.LOGIN.PLACE_HOLDER')"
|
||||||
@blur="$v.login.$touch"
|
@blur="v$.login.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="password"
|
v-model="password"
|
||||||
:class="{ error: $v.password.$error }"
|
:class="{ error: v$.password.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.IMAP.PASSWORD.LABEL')"
|
:label="$t('INBOX_MGMT.IMAP.PASSWORD.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.IMAP.PASSWORD.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.IMAP.PASSWORD.PLACE_HOLDER')"
|
||||||
type="password"
|
type="password"
|
||||||
@blur="$v.password.$touch"
|
@blur="v$.password.$touch"
|
||||||
/>
|
/>
|
||||||
<label for="toggle-enable-ssl">
|
<label for="toggle-enable-ssl">
|
||||||
<input
|
<input
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:button-text="$t('INBOX_MGMT.IMAP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.IMAP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdatingIMAP"
|
:loading="uiFlags.isUpdatingIMAP"
|
||||||
:disabled="($v.$invalid && isIMAPEnabled) || uiFlags.isUpdatingIMAP"
|
:disabled="(v$.$invalid && isIMAPEnabled) || uiFlags.isUpdatingIMAP"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</settings-section>
|
</settings-section>
|
||||||
@@ -75,7 +75,8 @@
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import SettingsSection from 'dashboard/components/SettingsSection.vue';
|
import SettingsSection from 'dashboard/components/SettingsSection.vue';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -87,6 +88,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isIMAPEnabled: false,
|
isIMAPEnabled: false,
|
||||||
|
|||||||
@@ -41,21 +41,21 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="selectedInboxName"
|
v-model.trim="selectedInboxName"
|
||||||
class="w-3/4 pb-4"
|
class="w-3/4 pb-4"
|
||||||
:class="{ error: $v.selectedInboxName.$error }"
|
:class="{ error: v$.selectedInboxName.$error }"
|
||||||
:label="inboxNameLabel"
|
:label="inboxNameLabel"
|
||||||
:placeholder="inboxNamePlaceHolder"
|
:placeholder="inboxNamePlaceHolder"
|
||||||
:error="
|
:error="
|
||||||
$v.selectedInboxName.$error
|
v$.selectedInboxName.$error
|
||||||
? $t('INBOX_MGMT.ADD.CHANNEL_NAME.ERROR')
|
? $t('INBOX_MGMT.ADD.CHANNEL_NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
@blur="$v.selectedInboxName.$touch"
|
@blur="v$.selectedInboxName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="isAPIInbox"
|
v-if="isAPIInbox"
|
||||||
v-model.trim="webhookUrl"
|
v-model.trim="webhookUrl"
|
||||||
class="w-3/4 pb-4"
|
class="w-3/4 pb-4"
|
||||||
:class="{ error: $v.webhookUrl.$error }"
|
:class="{ error: v$.webhookUrl.$error }"
|
||||||
:label="
|
:label="
|
||||||
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.LABEL')
|
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.LABEL')
|
||||||
"
|
"
|
||||||
@@ -63,11 +63,11 @@
|
|||||||
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
:error="
|
:error="
|
||||||
$v.webhookUrl.$error
|
v$.webhookUrl.$error
|
||||||
? $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.ERROR')
|
? $t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_WEBHOOK_URL.ERROR')
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
@blur="$v.webhookUrl.$touch"
|
@blur="v$.webhookUrl.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="isAWebWidgetInbox"
|
v-if="isAWebWidgetInbox"
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
v-if="isAPIInbox"
|
v-if="isAPIInbox"
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="$v.webhookUrl.$invalid"
|
:disabled="v$.webhookUrl.$invalid"
|
||||||
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdating"
|
:loading="uiFlags.isUpdating"
|
||||||
@click="updateInbox"
|
@click="updateInbox"
|
||||||
@@ -394,7 +394,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
v-else
|
v-else
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="$v.$invalid"
|
:disabled="v$.$invalid"
|
||||||
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdating"
|
:loading="uiFlags.isUpdating"
|
||||||
@click="updateInbox"
|
@click="updateInbox"
|
||||||
@@ -428,6 +428,7 @@ import { mapGetters } from 'vuex';
|
|||||||
import { shouldBeUrl } from 'shared/helpers/Validators';
|
import { shouldBeUrl } from 'shared/helpers/Validators';
|
||||||
import configMixin from 'shared/mixins/configMixin';
|
import configMixin from 'shared/mixins/configMixin';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import SettingIntroBanner from 'dashboard/components/widgets/SettingIntroBanner.vue';
|
import SettingIntroBanner from 'dashboard/components/widgets/SettingIntroBanner.vue';
|
||||||
import SettingsSection from '../../../../components/SettingsSection.vue';
|
import SettingsSection from '../../../../components/SettingsSection.vue';
|
||||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||||
@@ -459,6 +460,9 @@ export default {
|
|||||||
MicrosoftReauthorize,
|
MicrosoftReauthorize,
|
||||||
},
|
},
|
||||||
mixins: [configMixin, inboxMixin],
|
mixins: [configMixin, inboxMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
avatarFile: null,
|
avatarFile: null,
|
||||||
|
|||||||
@@ -17,45 +17,45 @@
|
|||||||
<div v-if="isSMTPEnabled" class="mb-6">
|
<div v-if="isSMTPEnabled" class="mb-6">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="address"
|
v-model.trim="address"
|
||||||
:class="{ error: $v.address.$error }"
|
:class="{ error: v$.address.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.SMTP.ADDRESS.LABEL')"
|
:label="$t('INBOX_MGMT.SMTP.ADDRESS.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.SMTP.ADDRESS.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.SMTP.ADDRESS.PLACE_HOLDER')"
|
||||||
@blur="$v.address.$touch"
|
@blur="v$.address.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="port"
|
v-model="port"
|
||||||
type="number"
|
type="number"
|
||||||
:class="{ error: $v.port.$error }"
|
:class="{ error: v$.port.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.SMTP.PORT.LABEL')"
|
:label="$t('INBOX_MGMT.SMTP.PORT.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.SMTP.PORT.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.SMTP.PORT.PLACE_HOLDER')"
|
||||||
@blur="$v.port.$touch"
|
@blur="v$.port.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="login"
|
v-model="login"
|
||||||
:class="{ error: $v.login.$error }"
|
:class="{ error: v$.login.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.SMTP.LOGIN.LABEL')"
|
:label="$t('INBOX_MGMT.SMTP.LOGIN.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.SMTP.LOGIN.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.SMTP.LOGIN.PLACE_HOLDER')"
|
||||||
@blur="$v.login.$touch"
|
@blur="v$.login.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="password"
|
v-model="password"
|
||||||
:class="{ error: $v.password.$error }"
|
:class="{ error: v$.password.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.SMTP.PASSWORD.LABEL')"
|
:label="$t('INBOX_MGMT.SMTP.PASSWORD.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.SMTP.PASSWORD.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.SMTP.PASSWORD.PLACE_HOLDER')"
|
||||||
type="password"
|
type="password"
|
||||||
@blur="$v.password.$touch"
|
@blur="v$.password.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="domain"
|
v-model.trim="domain"
|
||||||
:class="{ error: $v.domain.$error }"
|
:class="{ error: v$.domain.$error }"
|
||||||
class="max-w-[75%] w-full"
|
class="max-w-[75%] w-full"
|
||||||
:label="$t('INBOX_MGMT.SMTP.DOMAIN.LABEL')"
|
:label="$t('INBOX_MGMT.SMTP.DOMAIN.LABEL')"
|
||||||
:placeholder="$t('INBOX_MGMT.SMTP.DOMAIN.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.SMTP.DOMAIN.PLACE_HOLDER')"
|
||||||
@blur="$v.domain.$touch"
|
@blur="v$.domain.$touch"
|
||||||
/>
|
/>
|
||||||
<input-radio-group
|
<input-radio-group
|
||||||
:label="$t('INBOX_MGMT.SMTP.ENCRYPTION')"
|
:label="$t('INBOX_MGMT.SMTP.ENCRYPTION')"
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:button-text="$t('INBOX_MGMT.SMTP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SMTP.UPDATE')"
|
||||||
:loading="uiFlags.isUpdatingSMTP"
|
:loading="uiFlags.isUpdatingSMTP"
|
||||||
:disabled="($v.$invalid && isSMTPEnabled) || uiFlags.isUpdatingSMTP"
|
:disabled="(v$.$invalid && isSMTPEnabled) || uiFlags.isUpdatingSMTP"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</settings-section>
|
</settings-section>
|
||||||
@@ -91,7 +91,8 @@
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import SettingsSection from 'dashboard/components/SettingsSection.vue';
|
import SettingsSection from 'dashboard/components/SettingsSection.vue';
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import InputRadioGroup from './components/InputRadioGroup.vue';
|
import InputRadioGroup from './components/InputRadioGroup.vue';
|
||||||
import SingleSelectDropdown from './components/SingleSelectDropdown.vue';
|
import SingleSelectDropdown from './components/SingleSelectDropdown.vue';
|
||||||
|
|
||||||
@@ -107,6 +108,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isSMTPEnabled: false,
|
isSMTPEnabled: false,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="websiteName"
|
v-model.trim="websiteName"
|
||||||
:class="{ error: $v.websiteName.$error }"
|
:class="{ error: v$.websiteName.$error }"
|
||||||
:label="
|
:label="
|
||||||
$t(
|
$t(
|
||||||
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.LABEL'
|
'INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.LABEL'
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
)
|
)
|
||||||
"
|
"
|
||||||
:error="websiteNameValidationErrorMsg"
|
:error="websiteNameValidationErrorMsg"
|
||||||
@blur="$v.websiteName.$touch"
|
@blur="v$.websiteName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="welcomeHeading"
|
v-model.trim="welcomeHeading"
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
)
|
)
|
||||||
"
|
"
|
||||||
:loading="uiFlags.isUpdating"
|
:loading="uiFlags.isUpdating"
|
||||||
:disabled="$v.$invalid || uiFlags.isUpdating"
|
:disabled="v$.$invalid || uiFlags.isUpdating"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -157,7 +157,8 @@ import { mapGetters } from 'vuex';
|
|||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import Widget from 'dashboard/modules/widget-preview/components/Widget.vue';
|
import Widget from 'dashboard/modules/widget-preview/components/Widget.vue';
|
||||||
import InputRadioGroup from './components/InputRadioGroup.vue';
|
import InputRadioGroup from './components/InputRadioGroup.vue';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required } from '@vuelidate/validators';
|
||||||
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
|
||||||
import { LocalStorage } from 'shared/helpers/localStorage';
|
import { LocalStorage } from 'shared/helpers/localStorage';
|
||||||
|
|
||||||
@@ -172,6 +173,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isWidgetPreview: true,
|
isWidgetPreview: true,
|
||||||
@@ -287,7 +291,7 @@ export default {
|
|||||||
];
|
];
|
||||||
},
|
},
|
||||||
websiteNameValidationErrorMsg() {
|
websiteNameValidationErrorMsg() {
|
||||||
return this.$v.websiteName.$error
|
return this.v$.websiteName.$error
|
||||||
? this.$t('INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.ERROR')
|
? this.$t('INBOX_MGMT.WIDGET_BUILDER.WIDGET_OPTIONS.WEBSITE_NAME.ERROR')
|
||||||
: '';
|
: '';
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.inboxName.$error }">
|
<label :class="{ error: v$.inboxName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="inboxName"
|
v-model.trim="inboxName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')"
|
||||||
@blur="$v.inboxName.$touch"
|
@blur="v$.inboxName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.inboxName.$error" class="message">
|
<span v-if="v$.inboxName.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.phoneNumber.$error }">
|
<label :class="{ error: v$.phoneNumber.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="phoneNumber"
|
v-model.trim="phoneNumber"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')"
|
||||||
@blur="$v.phoneNumber.$touch"
|
@blur="v$.phoneNumber.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.phoneNumber.$error" class="message">
|
<span v-if="v$.phoneNumber.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.apiKey.$error }">
|
<label :class="{ error: v$.apiKey.$error }">
|
||||||
<span>
|
<span>
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }}
|
||||||
</span>
|
</span>
|
||||||
@@ -39,9 +39,9 @@
|
|||||||
v-model.trim="apiKey"
|
v-model.trim="apiKey"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')"
|
||||||
@blur="$v.apiKey.$touch"
|
@blur="v$.apiKey.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.apiKey.$error" class="message">
|
<span v-if="v$.apiKey.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -58,13 +58,17 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
|
|
||||||
import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
|
import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
inboxName: '',
|
inboxName: '',
|
||||||
@@ -82,8 +86,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/>
|
/>
|
||||||
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.channelName.$error }">
|
<label :class="{ error: v$.channelName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="channelName"
|
v-model.trim="channelName"
|
||||||
@@ -16,16 +16,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.channelName.$touch"
|
@blur="v$.channelName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.channelName.$error" class="message">{{
|
<span v-if="v$.channelName.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.ERROR')
|
$t('INBOX_MGMT.ADD.API_CHANNEL.CHANNEL_NAME.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.webhookUrl.$error }">
|
<label :class="{ error: v$.webhookUrl.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="webhookUrl"
|
v-model.trim="webhookUrl"
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.API_CHANNEL.WEBHOOK_URL.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.webhookUrl.$touch"
|
@blur="v$.webhookUrl.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<p class="help-text">
|
<p class="help-text">
|
||||||
@@ -53,8 +53,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
import PageHeader from '../../SettingsSubPageHeader.vue';
|
import PageHeader from '../../SettingsSubPageHeader.vue';
|
||||||
|
|
||||||
@@ -65,6 +66,9 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
PageHeader,
|
PageHeader,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
channelName: '',
|
channelName: '',
|
||||||
@@ -82,8 +86,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.inboxName.$error }">
|
<label :class="{ error: v$.inboxName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="inboxName"
|
v-model.trim="inboxName"
|
||||||
@@ -9,16 +9,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.inboxName.$touch"
|
@blur="v$.inboxName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.inboxName.$error" class="message">{{
|
<span v-if="v$.inboxName.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.ERROR')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.INBOX_NAME.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.phoneNumber.$error }">
|
<label :class="{ error: v$.phoneNumber.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="phoneNumber"
|
v-model.trim="phoneNumber"
|
||||||
@@ -26,16 +26,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.phoneNumber.$touch"
|
@blur="v$.phoneNumber.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.phoneNumber.$error" class="message">{{
|
<span v-if="v$.phoneNumber.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.ERROR')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.PHONE_NUMBER.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.accountId.$error }">
|
<label :class="{ error: v$.accountId.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="accountId"
|
v-model.trim="accountId"
|
||||||
@@ -43,16 +43,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.accountId.$touch"
|
@blur="v$.accountId.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.accountId.$error" class="message">{{
|
<span v-if="v$.accountId.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.ERROR')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.ACCOUNT_ID.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.applicationId.$error }">
|
<label :class="{ error: v$.applicationId.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="applicationId"
|
v-model.trim="applicationId"
|
||||||
@@ -60,31 +60,31 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.applicationId.$touch"
|
@blur="v$.applicationId.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.applicationId.$error" class="message">{{
|
<span v-if="v$.applicationId.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.ERROR')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.APPLICATION_ID.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.apiKey.$error }">
|
<label :class="{ error: v$.apiKey.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="apiKey"
|
v-model.trim="apiKey"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.PLACEHOLDER')"
|
||||||
@blur="$v.apiKey.$touch"
|
@blur="v$.apiKey.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.apiKey.$error" class="message">{{
|
<span v-if="v$.apiKey.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.ERROR')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_KEY.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.apiSecret.$error }">
|
<label :class="{ error: v$.apiSecret.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="apiSecret"
|
v-model.trim="apiSecret"
|
||||||
@@ -92,9 +92,9 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.apiSecret.$touch"
|
@blur="v$.apiSecret.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.apiSecret.$error" class="message">{{
|
<span v-if="v$.apiSecret.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.ERROR')
|
$t('INBOX_MGMT.ADD.SMS.BANDWIDTH.API_SECRET.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -111,13 +111,17 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
|
|
||||||
const shouldStartWithPlusSign = (value = '') => value.startsWith('+');
|
const shouldStartWithPlusSign = (value = '') => value.startsWith('+');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
accountId: '',
|
accountId: '',
|
||||||
@@ -144,8 +148,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.inboxName.$error }">
|
<label :class="{ error: v$.inboxName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="inboxName"
|
v-model.trim="inboxName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.PLACEHOLDER')"
|
||||||
@blur="$v.inboxName.$touch"
|
@blur="v$.inboxName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.inboxName.$error" class="message">
|
<span v-if="v$.inboxName.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.phoneNumber.$error }">
|
<label :class="{ error: v$.phoneNumber.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="phoneNumber"
|
v-model.trim="phoneNumber"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.PLACEHOLDER')"
|
||||||
@blur="$v.phoneNumber.$touch"
|
@blur="v$.phoneNumber.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.phoneNumber.$error" class="message">
|
<span v-if="v$.phoneNumber.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.phoneNumberId.$error }">
|
<label :class="{ error: v$.phoneNumberId.$error }">
|
||||||
<span>
|
<span>
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.LABEL') }}
|
||||||
</span>
|
</span>
|
||||||
@@ -41,16 +41,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.phoneNumberId.$touch"
|
@blur="v$.phoneNumberId.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.phoneNumberId.$error" class="message">
|
<span v-if="v$.phoneNumberId.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PHONE_NUMBER_ID.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.businessAccountId.$error }">
|
<label :class="{ error: v$.businessAccountId.$error }">
|
||||||
<span>
|
<span>
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.LABEL') }}
|
||||||
</span>
|
</span>
|
||||||
@@ -60,16 +60,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.businessAccountId.$touch"
|
@blur="v$.businessAccountId.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.businessAccountId.$error" class="message">
|
<span v-if="v$.businessAccountId.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.BUSINESS_ACCOUNT_ID.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.apiKey.$error }">
|
<label :class="{ error: v$.apiKey.$error }">
|
||||||
<span>
|
<span>
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.LABEL') }}
|
||||||
</span>
|
</span>
|
||||||
@@ -77,9 +77,9 @@
|
|||||||
v-model.trim="apiKey"
|
v-model.trim="apiKey"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.PLACEHOLDER')"
|
||||||
@blur="$v.apiKey.$touch"
|
@blur="v$.apiKey.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.apiKey.$error" class="message">
|
<span v-if="v$.apiKey.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }}
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_KEY.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -96,12 +96,16 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
import { isPhoneE164OrEmpty, isNumber } from 'shared/helpers/Validators';
|
import { isPhoneE164OrEmpty, isNumber } from 'shared/helpers/Validators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
inboxName: '',
|
inboxName: '',
|
||||||
@@ -123,8 +127,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-3/5">
|
<div class="w-3/5">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="input-wrap" :class="{ error: $v.selectedPage.$error }">
|
<div class="input-wrap" :class="{ error: v$.selectedPage.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PAGE') }}
|
{{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PAGE') }}
|
||||||
<multiselect
|
<multiselect
|
||||||
v-model.trim="selectedPage"
|
v-model.trim="selectedPage"
|
||||||
@@ -64,21 +64,21 @@
|
|||||||
selected-label
|
selected-label
|
||||||
@select="setPageName"
|
@select="setPageName"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.selectedPage.$error" class="message">
|
<span v-if="v$.selectedPage.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PLACEHOLDER') }}
|
{{ $t('INBOX_MGMT.ADD.FB.CHOOSE_PLACEHOLDER') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.pageName.$error }">
|
<label :class="{ error: v$.pageName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.FB.INBOX_NAME') }}
|
{{ $t('INBOX_MGMT.ADD.FB.INBOX_NAME') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="pageName"
|
v-model.trim="pageName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.FB.PICK_NAME')"
|
:placeholder="$t('INBOX_MGMT.ADD.FB.PICK_NAME')"
|
||||||
@input="$v.pageName.$touch"
|
@input="v$.pageName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.pageName.$error" class="message">
|
<span v-if="v$.pageName.$error" class="message">
|
||||||
{{ $t('INBOX_MGMT.ADD.FB.ADD_NAME') }}
|
{{ $t('INBOX_MGMT.ADD.FB.ADD_NAME') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -94,8 +94,9 @@
|
|||||||
<script>
|
<script>
|
||||||
/* eslint-env browser */
|
/* eslint-env browser */
|
||||||
/* global FB */
|
/* global FB */
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import LoadingState from 'dashboard/components/widgets/LoadingState.vue';
|
import LoadingState from 'dashboard/components/widgets/LoadingState.vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import ChannelApi from '../../../../../api/channels';
|
import ChannelApi from '../../../../../api/channels';
|
||||||
@@ -113,6 +114,9 @@ export default {
|
|||||||
PageHeader,
|
PageHeader,
|
||||||
},
|
},
|
||||||
mixins: [globalConfigMixin, accountMixin],
|
mixins: [globalConfigMixin, accountMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
@@ -181,7 +185,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
setPageName({ name }) {
|
setPageName({ name }) {
|
||||||
this.$v.selectedPage.$touch();
|
this.v$.selectedPage.$touch();
|
||||||
this.pageName = name;
|
this.pageName = name;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -270,8 +274,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
createChannel() {
|
createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (!this.$v.$error) {
|
if (!this.v$.$error) {
|
||||||
this.emptyStateMessage = this.$t('INBOX_MGMT.DETAILS.CREATING_CHANNEL');
|
this.emptyStateMessage = this.$t('INBOX_MGMT.DETAILS.CREATING_CHANNEL');
|
||||||
this.isCreating = true;
|
this.isCreating = true;
|
||||||
this.$store
|
this.$store
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/>
|
/>
|
||||||
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.channelName.$error }">
|
<label :class="{ error: v$.channelName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="channelName"
|
v-model.trim="channelName"
|
||||||
@@ -16,16 +16,16 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.channelName.$touch"
|
@blur="v$.channelName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.channelName.$error" class="message">{{
|
<span v-if="v$.channelName.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.ERROR')
|
$t('INBOX_MGMT.ADD.LINE_CHANNEL.CHANNEL_NAME.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.lineChannelId.$error }">
|
<label :class="{ error: v$.lineChannelId.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="lineChannelId"
|
v-model.trim="lineChannelId"
|
||||||
@@ -33,13 +33,13 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_ID.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.lineChannelId.$touch"
|
@blur="v$.lineChannelId.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.lineChannelSecret.$error }">
|
<label :class="{ error: v$.lineChannelSecret.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="lineChannelSecret"
|
v-model.trim="lineChannelSecret"
|
||||||
@@ -47,13 +47,13 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_SECRET.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.lineChannelSecret.$touch"
|
@blur="v$.lineChannelSecret.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.lineChannelToken.$error }">
|
<label :class="{ error: v$.lineChannelToken.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="lineChannelToken"
|
v-model.trim="lineChannelToken"
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.LINE_CHANNEL.LINE_CHANNEL_TOKEN.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.lineChannelToken.$touch"
|
@blur="v$.lineChannelToken.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,8 +78,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
import PageHeader from '../../SettingsSubPageHeader.vue';
|
import PageHeader from '../../SettingsSubPageHeader.vue';
|
||||||
|
|
||||||
@@ -87,6 +88,9 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
PageHeader,
|
PageHeader,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
channelName: '',
|
channelName: '',
|
||||||
@@ -108,8 +112,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/>
|
/>
|
||||||
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.botToken.$error }">
|
<label :class="{ error: v$.botToken.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="botToken"
|
v-model.trim="botToken"
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.BOT_TOKEN.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.botToken.$touch"
|
@blur="v$.botToken.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<p class="help-text">
|
<p class="help-text">
|
||||||
@@ -36,8 +36,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
import PageHeader from '../../SettingsSubPageHeader.vue';
|
import PageHeader from '../../SettingsSubPageHeader.vue';
|
||||||
|
|
||||||
@@ -45,6 +46,9 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
PageHeader,
|
PageHeader,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
botToken: '',
|
botToken: '',
|
||||||
@@ -60,8 +64,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<!-- Deprecated in favour of separate files for SMS and Whatsapp and also to implement new providers for each platform in the future-->
|
<!-- Deprecated in favour of separate files for SMS and Whatsapp and also to implement new providers for each platform in the future-->
|
||||||
<template>
|
<template>
|
||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.channelName.$error }">
|
<label :class="{ error: v$.channelName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="channelName"
|
v-model.trim="channelName"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.PLACEHOLDER')"
|
||||||
@blur="$v.channelName.$touch"
|
@blur="v$.channelName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.channelName.$error" class="message">{{
|
<span v-if="v$.channelName.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.ERROR')
|
$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label
|
<label
|
||||||
v-if="useMessagingService"
|
v-if="useMessagingService"
|
||||||
:class="{ error: $v.messagingServiceSID.$error }"
|
:class="{ error: v$.messagingServiceSID.$error }"
|
||||||
>
|
>
|
||||||
{{ $t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.LABEL') }}
|
||||||
<input
|
<input
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.messagingServiceSID.$touch"
|
@blur="v$.messagingServiceSID.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.messagingServiceSID.$error" class="message">{{
|
<span v-if="v$.messagingServiceSID.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.ERROR')
|
$t('INBOX_MGMT.ADD.TWILIO.MESSAGING_SERVICE_SID.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -40,15 +40,15 @@
|
|||||||
v-if="!useMessagingService"
|
v-if="!useMessagingService"
|
||||||
class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"
|
class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"
|
||||||
>
|
>
|
||||||
<label :class="{ error: $v.phoneNumber.$error }">
|
<label :class="{ error: v$.phoneNumber.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="phoneNumber"
|
v-model.trim="phoneNumber"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.PLACEHOLDER')"
|
||||||
@blur="$v.phoneNumber.$touch"
|
@blur="v$.phoneNumber.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.phoneNumber.$error" class="message">{{
|
<span v-if="v$.phoneNumber.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.ERROR')
|
$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -71,15 +71,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.accountSID.$error }">
|
<label :class="{ error: v$.accountSID.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="accountSID"
|
v-model.trim="accountSID"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.PLACEHOLDER')"
|
||||||
@blur="$v.accountSID.$touch"
|
@blur="v$.accountSID.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.accountSID.$error" class="message">{{
|
<span v-if="v$.accountSID.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.ERROR')
|
$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -96,21 +96,21 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="useAPIKey" class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div v-if="useAPIKey" class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.apiKeySID.$error }">
|
<label :class="{ error: v$.apiKeySID.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.TWILIO.API_KEY.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.TWILIO.API_KEY.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="apiKeySID"
|
v-model.trim="apiKeySID"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.API_KEY.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.API_KEY.PLACEHOLDER')"
|
||||||
@blur="$v.apiKeySID.$touch"
|
@blur="v$.apiKeySID.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.apiKeySID.$error" class="message">{{
|
<span v-if="v$.apiKeySID.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.API_KEY.ERROR')
|
$t('INBOX_MGMT.ADD.TWILIO.API_KEY.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.authToken.$error }">
|
<label :class="{ error: v$.authToken.$error }">
|
||||||
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.LABEL`) }}
|
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.LABEL`) }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="authToken"
|
v-model.trim="authToken"
|
||||||
@@ -118,9 +118,9 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.PLACEHOLDER`)
|
$t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.PLACEHOLDER`)
|
||||||
"
|
"
|
||||||
@blur="$v.authToken.$touch"
|
@blur="v$.authToken.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.authToken.$error" class="message">
|
<span v-if="v$.authToken.$error" class="message">
|
||||||
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.ERROR`) }}
|
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.ERROR`) }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -137,8 +137,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
|
import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
|
||||||
|
|
||||||
@@ -149,6 +150,9 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
accountSID: '',
|
accountSID: '',
|
||||||
@@ -202,8 +206,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/>
|
/>
|
||||||
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
<form class="flex flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.channelName.$error }">
|
<label :class="{ error: v$.channelName.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="channelName"
|
v-model.trim="channelName"
|
||||||
@@ -16,22 +16,22 @@
|
|||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
@blur="$v.channelName.$touch"
|
@blur="v$.channelName.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.channelName.$error" class="message">{{
|
<span v-if="v$.channelName.$error" class="message">{{
|
||||||
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.ERROR')
|
$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.CHANNEL_NAME.ERROR')
|
||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
<label :class="{ error: $v.email.$error }">
|
<label :class="{ error: v$.email.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.LABEL') }}
|
{{ $t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="email"
|
v-model.trim="email"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.EMAIL.PLACEHOLDER')"
|
||||||
@blur="$v.email.$touch"
|
@blur="v$.email.$touch"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<p class="help-text">
|
<p class="help-text">
|
||||||
@@ -51,8 +51,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, email } from 'vuelidate/lib/validators';
|
import { required, email } from '@vuelidate/validators';
|
||||||
import router from '../../../../../index';
|
import router from '../../../../../index';
|
||||||
import PageHeader from '../../../SettingsSubPageHeader.vue';
|
import PageHeader from '../../../SettingsSubPageHeader.vue';
|
||||||
|
|
||||||
@@ -60,6 +61,9 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
PageHeader,
|
PageHeader,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
channelName: '',
|
channelName: '',
|
||||||
@@ -78,8 +82,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
selected-label
|
selected-label
|
||||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||||
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
:deselect-label="$t('FORMS.MULTISELECT.ENTER_TO_REMOVE')"
|
||||||
@select="$v.selectedAgents.$touch"
|
@select="v$.selectedAgents.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
@@ -56,10 +56,10 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="maxAssignmentLimit"
|
v-model.trim="maxAssignmentLimit"
|
||||||
type="number"
|
type="number"
|
||||||
:class="{ error: $v.maxAssignmentLimit.$error }"
|
:class="{ error: v$.maxAssignmentLimit.$error }"
|
||||||
:error="maxAssignmentLimitErrors"
|
:error="maxAssignmentLimitErrors"
|
||||||
:label="$t('INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT')"
|
:label="$t('INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT')"
|
||||||
@blur="$v.maxAssignmentLimit.$touch"
|
@blur="v$.maxAssignmentLimit.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p class="pb-1 text-sm not-italic text-slate-600 dark:text-slate-400">
|
<p class="pb-1 text-sm not-italic text-slate-600 dark:text-slate-400">
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SETTINGS_POPUP.UPDATE')"
|
||||||
:disabled="$v.maxAssignmentLimit.$invalid"
|
:disabled="v$.maxAssignmentLimit.$invalid"
|
||||||
@click="updateInbox"
|
@click="updateInbox"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,7 +78,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { minValue } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { minValue } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import configMixin from 'shared/mixins/configMixin';
|
import configMixin from 'shared/mixins/configMixin';
|
||||||
import SettingsSection from '../../../../../components/SettingsSection.vue';
|
import SettingsSection from '../../../../../components/SettingsSection.vue';
|
||||||
@@ -94,6 +95,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedAgents: [],
|
selectedAgents: [],
|
||||||
@@ -107,7 +111,7 @@ export default {
|
|||||||
agentList: 'agents/getAgents',
|
agentList: 'agents/getAgents',
|
||||||
}),
|
}),
|
||||||
maxAssignmentLimitErrors() {
|
maxAssignmentLimitErrors() {
|
||||||
if (this.$v.maxAssignmentLimit.$error) {
|
if (this.v$.maxAssignmentLimit.$error) {
|
||||||
return this.$t(
|
return this.$t(
|
||||||
'INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT_RANGE_ERROR'
|
'INBOX_MGMT.AUTO_ASSIGNMENT.MAX_ASSIGNMENT_LIMIT_RANGE_ERROR'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -139,7 +139,7 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<woot-button
|
<woot-button
|
||||||
:disabled="$v.whatsAppInboxAPIKey.$invalid"
|
:disabled="v$.whatsAppInboxAPIKey.$invalid"
|
||||||
@click="updateWhatsAppInboxAPIKey"
|
@click="updateWhatsAppInboxAPIKey"
|
||||||
>
|
>
|
||||||
{{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_BUTTON') }}
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_SECTION_UPDATE_BUTTON') }}
|
||||||
@@ -156,7 +156,8 @@ import inboxMixin from 'shared/mixins/inboxMixin';
|
|||||||
import SettingsSection from '../../../../../components/SettingsSection.vue';
|
import SettingsSection from '../../../../../components/SettingsSection.vue';
|
||||||
import ImapSettings from '../ImapSettings.vue';
|
import ImapSettings from '../ImapSettings.vue';
|
||||||
import SmtpSettings from '../SmtpSettings.vue';
|
import SmtpSettings from '../SmtpSettings.vue';
|
||||||
import { required } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required } from '@vuelidate/validators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -171,6 +172,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hmacMandatory: false,
|
hmacMandatory: false,
|
||||||
|
|||||||
@@ -5,40 +5,40 @@
|
|||||||
<form class="w-full" @submit.prevent="submit">
|
<form class="w-full" @submit.prevent="submit">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="app.title"
|
v-model.trim="app.title"
|
||||||
:class="{ error: $v.app.title.$error }"
|
:class="{ error: v$.app.title.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_LABEL')"
|
:label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_LABEL')"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_PLACEHOLDER')
|
$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_PLACEHOLDER')
|
||||||
"
|
"
|
||||||
:error="
|
:error="
|
||||||
$v.app.title.$error
|
v$.app.title.$error
|
||||||
? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_ERROR')
|
? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.TITLE_ERROR')
|
||||||
: null
|
: null
|
||||||
"
|
"
|
||||||
data-testid="app-title"
|
data-testid="app-title"
|
||||||
@input="$v.app.title.$touch"
|
@input="v$.app.title.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="app.content.url"
|
v-model.trim="app.content.url"
|
||||||
:class="{ error: $v.app.content.url.$error }"
|
:class="{ error: v$.app.content.url.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_LABEL')"
|
:label="$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_LABEL')"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_PLACEHOLDER')
|
$t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_PLACEHOLDER')
|
||||||
"
|
"
|
||||||
:error="
|
:error="
|
||||||
$v.app.content.url.$error
|
v$.app.content.url.$error
|
||||||
? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_ERROR')
|
? $t('INTEGRATION_SETTINGS.DASHBOARD_APPS.FORM.URL_ERROR')
|
||||||
: null
|
: null
|
||||||
"
|
"
|
||||||
data-testid="app-url"
|
data-testid="app-url"
|
||||||
@input="$v.app.content.url.$touch"
|
@input="v$.app.content.url.$touch"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-loading="isLoading"
|
:is-loading="isLoading"
|
||||||
:is-disabled="$v.$invalid"
|
:is-disabled="v$.$invalid"
|
||||||
data-testid="label-submit"
|
data-testid="label-submit"
|
||||||
>
|
>
|
||||||
{{ submitButtonLabel }}
|
{{ submitButtonLabel }}
|
||||||
@@ -53,7 +53,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, url } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, url } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -71,6 +72,9 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
app: {
|
app: {
|
||||||
title: { required },
|
title: { required },
|
||||||
@@ -119,8 +123,8 @@ export default {
|
|||||||
},
|
},
|
||||||
async submit() {
|
async submit() {
|
||||||
try {
|
try {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<form class="flex flex-col w-full" @submit.prevent="onSubmit">
|
<form class="flex flex-col w-full" @submit.prevent="onSubmit">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label :class="{ error: $v.url.$error }">
|
<label :class="{ error: v$.url.$error }">
|
||||||
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.LABEL') }}
|
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.LABEL') }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="url"
|
v-model.trim="url"
|
||||||
type="text"
|
type="text"
|
||||||
name="url"
|
name="url"
|
||||||
:placeholder="webhookURLInputPlaceholder"
|
:placeholder="webhookURLInputPlaceholder"
|
||||||
@input="$v.url.$touch"
|
@input="v$.url.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.url.$error" class="message">
|
<span v-if="v$.url.$error" class="message">
|
||||||
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.ERROR') }}
|
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.END_POINT.ERROR') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label :class="{ error: $v.url.$error }" class="mb-2">
|
<label :class="{ error: v$.url.$error }" class="mb-2">
|
||||||
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.LABEL') }}
|
{{ $t('INTEGRATION_SETTINGS.WEBHOOK.FORM.SUBSCRIPTIONS.LABEL') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="flex flex-col gap-2.5 mb-4">
|
<div class="flex flex-col gap-2.5 mb-4">
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<woot-button
|
<woot-button
|
||||||
:disabled="$v.$invalid || isSubmitting"
|
:disabled="v$.$invalid || isSubmitting"
|
||||||
:is-loading="isSubmitting"
|
:is-loading="isSubmitting"
|
||||||
>
|
>
|
||||||
{{ submitLabel }}
|
{{ submitLabel }}
|
||||||
@@ -55,7 +55,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, url, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, url, minLength } from '@vuelidate/validators';
|
||||||
import webhookMixin from './webhookMixin';
|
import webhookMixin from './webhookMixin';
|
||||||
import wootConstants from 'dashboard/constants/globals';
|
import wootConstants from 'dashboard/constants/globals';
|
||||||
|
|
||||||
@@ -88,6 +89,9 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
validations: {
|
validations: {
|
||||||
url: {
|
url: {
|
||||||
required,
|
required,
|
||||||
|
|||||||
@@ -7,23 +7,23 @@
|
|||||||
<form class="flex flex-wrap mx-0" @submit.prevent="addLabel">
|
<form class="flex flex-wrap mx-0" @submit.prevent="addLabel">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="title"
|
v-model.trim="title"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
class="w-full label-name--input"
|
class="w-full label-name--input"
|
||||||
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="labelTitleErrorMessage"
|
:error="labelTitleErrorMessage"
|
||||||
data-testid="label-title"
|
data-testid="label-title"
|
||||||
@input="$v.title.$touch"
|
@input="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
:class="{ error: $v.description.$error }"
|
:class="{ error: v$.description.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')"
|
:label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')"
|
||||||
:placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')"
|
:placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')"
|
||||||
data-testid="label-description"
|
data-testid="label-description"
|
||||||
@input="$v.description.$touch"
|
@input="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-end w-full gap-2 px-0 py-2">
|
<div class="flex items-center justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-disabled="$v.title.$invalid || uiFlags.isCreating"
|
:is-disabled="v$.title.$invalid || uiFlags.isCreating"
|
||||||
:is-loading="uiFlags.isCreating"
|
:is-loading="uiFlags.isCreating"
|
||||||
data-testid="label-submit"
|
data-testid="label-submit"
|
||||||
>
|
>
|
||||||
@@ -59,6 +59,7 @@ import { mapGetters } from 'vuex';
|
|||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import validations, { getLabelTitleErrorMessage } from './validations';
|
import validations, { getLabelTitleErrorMessage } from './validations';
|
||||||
import { getRandomColor } from 'dashboard/helper/labelColor';
|
import { getRandomColor } from 'dashboard/helper/labelColor';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -67,6 +68,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
color: '#000',
|
color: '#000',
|
||||||
@@ -81,7 +85,7 @@ export default {
|
|||||||
uiFlags: 'labels/getUIFlags',
|
uiFlags: 'labels/getUIFlags',
|
||||||
}),
|
}),
|
||||||
labelTitleErrorMessage() {
|
labelTitleErrorMessage() {
|
||||||
const errorMessage = getLabelTitleErrorMessage(this.$v);
|
const errorMessage = getLabelTitleErrorMessage(this.v$);
|
||||||
return this.$t(errorMessage);
|
return this.$t(errorMessage);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
<form class="flex flex-wrap mx-0" @submit.prevent="editLabel">
|
<form class="flex flex-wrap mx-0" @submit.prevent="editLabel">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="title"
|
v-model.trim="title"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
class="w-full label-name--input"
|
class="w-full label-name--input"
|
||||||
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
:label="$t('LABEL_MGMT.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('LABEL_MGMT.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="labelTitleErrorMessage"
|
:error="labelTitleErrorMessage"
|
||||||
@input="$v.title.$touch"
|
@input="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
:class="{ error: $v.description.$error }"
|
:class="{ error: v$.description.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')"
|
:label="$t('LABEL_MGMT.FORM.DESCRIPTION.LABEL')"
|
||||||
:placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')"
|
:placeholder="$t('LABEL_MGMT.FORM.DESCRIPTION.PLACEHOLDER')"
|
||||||
@input="$v.description.$touch"
|
@input="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-end w-full gap-2 px-0 py-2">
|
<div class="flex items-center justify-end w-full gap-2 px-0 py-2">
|
||||||
<woot-button
|
<woot-button
|
||||||
:is-disabled="$v.title.$invalid || uiFlags.isUpdating"
|
:is-disabled="v$.title.$invalid || uiFlags.isUpdating"
|
||||||
:is-loading="uiFlags.isUpdating"
|
:is-loading="uiFlags.isUpdating"
|
||||||
>
|
>
|
||||||
{{ $t('LABEL_MGMT.FORM.EDIT') }}
|
{{ $t('LABEL_MGMT.FORM.EDIT') }}
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import validations, { getLabelTitleErrorMessage } from './validations';
|
import validations, { getLabelTitleErrorMessage } from './validations';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -59,6 +60,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '',
|
title: '',
|
||||||
@@ -78,7 +82,7 @@ export default {
|
|||||||
}`;
|
}`;
|
||||||
},
|
},
|
||||||
labelTitleErrorMessage() {
|
labelTitleErrorMessage() {
|
||||||
const errorMessage = getLabelTitleErrorMessage(this.$v);
|
const errorMessage = getLabelTitleErrorMessage(this.v$);
|
||||||
return this.$t(errorMessage);
|
return this.$t(errorMessage);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
|
||||||
export const validLabelCharacters = (str = '') => !!str && !str.includes(' ');
|
export const validLabelCharacters = (str = '') => !!str && !str.includes(' ');
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<macro-nodes
|
<macro-nodes
|
||||||
v-model="macro.actions"
|
v-model="macro.actions"
|
||||||
:files="files"
|
:files="files"
|
||||||
|
:errors="errors"
|
||||||
@addNewNode="appendNode"
|
@addNewNode="appendNode"
|
||||||
@deleteNode="deleteNode"
|
@deleteNode="deleteNode"
|
||||||
@resetAction="resetNode"
|
@resetAction="resetNode"
|
||||||
@@ -24,29 +25,34 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { provide } from 'vue';
|
||||||
import MacroNodes from './MacroNodes.vue';
|
import MacroNodes from './MacroNodes.vue';
|
||||||
import MacroProperties from './MacroProperties.vue';
|
import MacroProperties from './MacroProperties.vue';
|
||||||
import { required, requiredIf } from 'vuelidate/lib/validators';
|
import { required } from '@vuelidate/validators';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { validateActions } from 'dashboard/helper/validations';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MacroNodes,
|
MacroNodes,
|
||||||
MacroProperties,
|
MacroProperties,
|
||||||
},
|
},
|
||||||
provide() {
|
|
||||||
return {
|
|
||||||
$v: this.$v,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
macroData: {
|
macroData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const v$ = useVuelidate();
|
||||||
|
provide('v$', v$);
|
||||||
|
|
||||||
|
return { v$ };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
macro: this.macroData,
|
macro: this.macroData,
|
||||||
|
errors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -77,25 +83,14 @@ export default {
|
|||||||
visibility: {
|
visibility: {
|
||||||
required,
|
required,
|
||||||
},
|
},
|
||||||
actions: {
|
|
||||||
required,
|
|
||||||
$each: {
|
|
||||||
action_params: {
|
|
||||||
required: requiredIf(prop => {
|
|
||||||
if (prop.action_name === 'send_email_to_team') return true;
|
|
||||||
return !(
|
|
||||||
prop.action_name === 'mute_conversation' ||
|
|
||||||
prop.action_name === 'snooze_conversation' ||
|
|
||||||
prop.action_name === 'resolve_conversation' ||
|
|
||||||
prop.action_name === 'remove_assigned_team'
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
removeObjectProperty(obj, keyToRemove) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(obj).filter(([key]) => key !== keyToRemove)
|
||||||
|
);
|
||||||
|
},
|
||||||
updateName(value) {
|
updateName(value) {
|
||||||
this.macro.name = value;
|
this.macro.name = value;
|
||||||
},
|
},
|
||||||
@@ -109,19 +104,29 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteNode(index) {
|
deleteNode(index) {
|
||||||
|
// remove that index specifically
|
||||||
|
// so that the next item does not get marked invalid
|
||||||
|
this.errors = this.removeObjectProperty(this.errors, `action_${index}`);
|
||||||
this.macro.actions.splice(index, 1);
|
this.macro.actions.splice(index, 1);
|
||||||
},
|
},
|
||||||
submit() {
|
submit() {
|
||||||
this.$v.$touch();
|
this.errors = validateActions(this.macro.actions);
|
||||||
if (this.$v.$invalid) return;
|
if (Object.keys(this.errors).length !== 0) return;
|
||||||
|
|
||||||
|
this.v$.$touch();
|
||||||
|
if (this.v$.$invalid) return;
|
||||||
|
|
||||||
this.$emit('submit', this.macro);
|
this.$emit('submit', this.macro);
|
||||||
},
|
},
|
||||||
resetNode(index) {
|
resetNode(index) {
|
||||||
this.$v.macro.actions.$each[index].$reset();
|
// remove that index specifically
|
||||||
|
// so that the next item does not get marked invalid
|
||||||
|
this.errors = this.removeObjectProperty(this.errors, `action_${index}`);
|
||||||
this.macro.actions[index].action_params = [];
|
this.macro.actions[index].action_params = [];
|
||||||
},
|
},
|
||||||
resetValidation() {
|
resetValidation() {
|
||||||
this.$v.$reset();
|
this.errors = {};
|
||||||
|
this.v$?.$reset?.();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<div
|
<div
|
||||||
class="macro__node-action-item"
|
class="macro__node-action-item"
|
||||||
:class="{
|
:class="{
|
||||||
'has-error': hasError($v.macro.actions.$each[index]),
|
'has-error': errorKey,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<action-input
|
<action-input
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
:show-action-input="showActionInput"
|
:show-action-input="showActionInput"
|
||||||
:show-remove-button="false"
|
:show-remove-button="false"
|
||||||
:is-macro="true"
|
:is-macro="true"
|
||||||
:v="$v.macro.actions.$each[index]"
|
:error-message="errorMessage"
|
||||||
:initial-file-name="fileName"
|
:initial-file-name="fileName"
|
||||||
@resetAction="$emit('resetAction')"
|
@resetAction="$emit('resetAction')"
|
||||||
/>
|
/>
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { inject } from 'vue';
|
||||||
import ActionInput from 'dashboard/components/widgets/AutomationActionInput.vue';
|
import ActionInput from 'dashboard/components/widgets/AutomationActionInput.vue';
|
||||||
import macrosMixin from 'dashboard/mixins/macrosMixin';
|
import macrosMixin from 'dashboard/mixins/macrosMixin';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
@@ -48,7 +49,6 @@ export default {
|
|||||||
ActionInput,
|
ActionInput,
|
||||||
},
|
},
|
||||||
mixins: [macrosMixin],
|
mixins: [macrosMixin],
|
||||||
inject: ['macroActionTypes', '$v'],
|
|
||||||
props: {
|
props: {
|
||||||
singleNode: {
|
singleNode: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -58,6 +58,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
|
errorKey: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
index: {
|
index: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
@@ -67,6 +71,10 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const macroActionTypes = inject('macroActionTypes');
|
||||||
|
return { macroActionTypes };
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
labels: 'labels/getLabels',
|
labels: 'labels/getLabels',
|
||||||
@@ -81,6 +89,11 @@ export default {
|
|||||||
this.$emit('input', value);
|
this.$emit('input', value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errorMessage() {
|
||||||
|
if (!this.errorKey) return '';
|
||||||
|
|
||||||
|
return this.$t(`MACROS.ERRORS.${this.errorKey}`);
|
||||||
|
},
|
||||||
showActionInput() {
|
showActionInput() {
|
||||||
if (
|
if (
|
||||||
this.actionData.action_name === 'send_email_to_team' ||
|
this.actionData.action_name === 'send_email_to_team' ||
|
||||||
@@ -97,9 +110,6 @@ export default {
|
|||||||
dropdownValues() {
|
dropdownValues() {
|
||||||
return this.getDropdownValues(this.value.action_name, this.$store);
|
return this.getDropdownValues(this.value.action_name, this.$store);
|
||||||
},
|
},
|
||||||
hasError(v) {
|
|
||||||
return !!(v.action_params.$dirty && v.action_params.$error);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
class="macros__node-action"
|
class="macros__node-action"
|
||||||
type="add"
|
type="add"
|
||||||
:index="i"
|
:index="i"
|
||||||
|
:error-key="errors[`action_${i}`]"
|
||||||
:file-name="
|
:file-name="
|
||||||
fileName(
|
fileName(
|
||||||
actionData[i].action_params[0],
|
actionData[i].action_params[0],
|
||||||
@@ -64,12 +65,17 @@
|
|||||||
import Draggable from 'vuedraggable';
|
import Draggable from 'vuedraggable';
|
||||||
import MacroNode from './MacroNode.vue';
|
import MacroNode from './MacroNode.vue';
|
||||||
import { getFileName } from './macroHelper';
|
import { getFileName } from './macroHelper';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Draggable,
|
Draggable,
|
||||||
MacroNode,
|
MacroNode,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
errors: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
value: {
|
value: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
:value="macroName"
|
:value="macroName"
|
||||||
:label="$t('MACROS.ADD.FORM.NAME.LABEL')"
|
:label="$t('MACROS.ADD.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('MACROS.ADD.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('MACROS.ADD.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="$v.macro.name.$error ? $t('MACROS.ADD.FORM.NAME.ERROR') : null"
|
:error="v$.macro.name.$error ? $t('MACROS.ADD.FORM.NAME.ERROR') : null"
|
||||||
:class="{ error: $v.macro.name.$error }"
|
:class="{ error: v$.macro.name.$error }"
|
||||||
@input="onUpdateName($event)"
|
@input="onUpdateName($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
inject: ['$v'],
|
inject: ['v$'],
|
||||||
props: {
|
props: {
|
||||||
macroName: {
|
macroName: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -5,45 +5,45 @@
|
|||||||
v-model="currentPassword"
|
v-model="currentPassword"
|
||||||
type="password"
|
type="password"
|
||||||
:styles="inputStyles"
|
:styles="inputStyles"
|
||||||
:class="{ error: $v.currentPassword.$error }"
|
:class="{ error: v$.currentPassword.$error }"
|
||||||
:label="$t('PROFILE_SETTINGS.FORM.CURRENT_PASSWORD.LABEL')"
|
:label="$t('PROFILE_SETTINGS.FORM.CURRENT_PASSWORD.LABEL')"
|
||||||
:placeholder="$t('PROFILE_SETTINGS.FORM.CURRENT_PASSWORD.PLACEHOLDER')"
|
:placeholder="$t('PROFILE_SETTINGS.FORM.CURRENT_PASSWORD.PLACEHOLDER')"
|
||||||
:error="`${
|
:error="`${
|
||||||
$v.currentPassword.$error
|
v$.currentPassword.$error
|
||||||
? $t('PROFILE_SETTINGS.FORM.CURRENT_PASSWORD.ERROR')
|
? $t('PROFILE_SETTINGS.FORM.CURRENT_PASSWORD.ERROR')
|
||||||
: ''
|
: ''
|
||||||
}`"
|
}`"
|
||||||
@input="$v.currentPassword.$touch"
|
@input="v$.currentPassword.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="password"
|
v-model="password"
|
||||||
type="password"
|
type="password"
|
||||||
:styles="inputStyles"
|
:styles="inputStyles"
|
||||||
:class="{ error: $v.password.$error }"
|
:class="{ error: v$.password.$error }"
|
||||||
:label="$t('PROFILE_SETTINGS.FORM.PASSWORD.LABEL')"
|
:label="$t('PROFILE_SETTINGS.FORM.PASSWORD.LABEL')"
|
||||||
:placeholder="$t('PROFILE_SETTINGS.FORM.PASSWORD.PLACEHOLDER')"
|
:placeholder="$t('PROFILE_SETTINGS.FORM.PASSWORD.PLACEHOLDER')"
|
||||||
:error="`${
|
:error="`${
|
||||||
$v.password.$error ? $t('PROFILE_SETTINGS.FORM.PASSWORD.ERROR') : ''
|
v$.password.$error ? $t('PROFILE_SETTINGS.FORM.PASSWORD.ERROR') : ''
|
||||||
}`"
|
}`"
|
||||||
@input="$v.password.$touch"
|
@input="v$.password.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="passwordConfirmation"
|
v-model="passwordConfirmation"
|
||||||
type="password"
|
type="password"
|
||||||
:styles="inputStyles"
|
:styles="inputStyles"
|
||||||
:class="{ error: $v.passwordConfirmation.$error }"
|
:class="{ error: v$.passwordConfirmation.$error }"
|
||||||
:label="$t('PROFILE_SETTINGS.FORM.PASSWORD_CONFIRMATION.LABEL')"
|
:label="$t('PROFILE_SETTINGS.FORM.PASSWORD_CONFIRMATION.LABEL')"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('PROFILE_SETTINGS.FORM.PASSWORD_CONFIRMATION.PLACEHOLDER')
|
$t('PROFILE_SETTINGS.FORM.PASSWORD_CONFIRMATION.PLACEHOLDER')
|
||||||
"
|
"
|
||||||
:error="`${
|
:error="`${
|
||||||
$v.passwordConfirmation.$error
|
v$.passwordConfirmation.$error
|
||||||
? $t('PROFILE_SETTINGS.FORM.PASSWORD_CONFIRMATION.ERROR')
|
? $t('PROFILE_SETTINGS.FORM.PASSWORD_CONFIRMATION.ERROR')
|
||||||
: ''
|
: ''
|
||||||
}`"
|
}`"
|
||||||
@input="$v.passwordConfirmation.$touch"
|
@input="v$.passwordConfirmation.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<form-button
|
<form-button
|
||||||
@@ -60,14 +60,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { parseAPIErrorResponse } from 'dashboard/store/utils/api';
|
import { parseAPIErrorResponse } from 'dashboard/store/utils/api';
|
||||||
import FormButton from 'v3/components/Form/Button.vue';
|
import FormButton from 'v3/components/Form/Button.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FormButton,
|
FormButton,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentPassword: '',
|
currentPassword: '',
|
||||||
@@ -105,14 +110,14 @@ export default {
|
|||||||
return (
|
return (
|
||||||
!this.currentPassword ||
|
!this.currentPassword ||
|
||||||
!this.passwordConfirmation ||
|
!this.passwordConfirmation ||
|
||||||
!this.$v.passwordConfirmation.isEqPassword
|
!this.v$.passwordConfirmation.isEqPassword
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async changePassword() {
|
async changePassword() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
useAlert(this.$t('PROFILE_SETTINGS.FORM.ERROR'));
|
useAlert(this.$t('PROFILE_SETTINGS.FORM.ERROR'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,38 +3,38 @@
|
|||||||
<woot-input
|
<woot-input
|
||||||
v-model="userName"
|
v-model="userName"
|
||||||
:styles="inputStyles"
|
:styles="inputStyles"
|
||||||
:class="{ error: $v.userName.$error }"
|
:class="{ error: v$.userName.$error }"
|
||||||
:label="$t('PROFILE_SETTINGS.FORM.NAME.LABEL')"
|
:label="$t('PROFILE_SETTINGS.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('PROFILE_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('PROFILE_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="`${
|
:error="`${
|
||||||
$v.userName.$error ? $t('PROFILE_SETTINGS.FORM.NAME.ERROR') : ''
|
v$.userName.$error ? $t('PROFILE_SETTINGS.FORM.NAME.ERROR') : ''
|
||||||
}`"
|
}`"
|
||||||
@input="$v.userName.$touch"
|
@input="v$.userName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="userDisplayName"
|
v-model="userDisplayName"
|
||||||
:styles="inputStyles"
|
:styles="inputStyles"
|
||||||
:class="{ error: $v.userDisplayName.$error }"
|
:class="{ error: v$.userDisplayName.$error }"
|
||||||
:label="$t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.LABEL')"
|
:label="$t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.LABEL')"
|
||||||
:placeholder="$t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.PLACEHOLDER')"
|
:placeholder="$t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.PLACEHOLDER')"
|
||||||
:error="`${
|
:error="`${
|
||||||
$v.userDisplayName.$error
|
v$.userDisplayName.$error
|
||||||
? $t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.ERROR')
|
? $t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.ERROR')
|
||||||
: ''
|
: ''
|
||||||
}`"
|
}`"
|
||||||
@input="$v.userDisplayName.$touch"
|
@input="v$.userDisplayName.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-if="emailEnabled"
|
v-if="emailEnabled"
|
||||||
v-model="userEmail"
|
v-model="userEmail"
|
||||||
:styles="inputStyles"
|
:styles="inputStyles"
|
||||||
:class="{ error: $v.userEmail.$error }"
|
:class="{ error: v$.userEmail.$error }"
|
||||||
:label="$t('PROFILE_SETTINGS.FORM.EMAIL.LABEL')"
|
:label="$t('PROFILE_SETTINGS.FORM.EMAIL.LABEL')"
|
||||||
:placeholder="$t('PROFILE_SETTINGS.FORM.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('PROFILE_SETTINGS.FORM.EMAIL.PLACEHOLDER')"
|
||||||
:error="`${
|
:error="`${
|
||||||
$v.userEmail.$error ? $t('PROFILE_SETTINGS.FORM.EMAIL.ERROR') : ''
|
v$.userEmail.$error ? $t('PROFILE_SETTINGS.FORM.EMAIL.ERROR') : ''
|
||||||
}`"
|
}`"
|
||||||
@input="$v.userEmail.$touch"
|
@input="v$.userEmail.$touch"
|
||||||
/>
|
/>
|
||||||
<form-button
|
<form-button
|
||||||
type="submit"
|
type="submit"
|
||||||
@@ -49,7 +49,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import FormButton from 'v3/components/Form/Button.vue';
|
import FormButton from 'v3/components/Form/Button.vue';
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FormButton,
|
FormButton,
|
||||||
@@ -72,6 +73,9 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
userName: this.name,
|
userName: this.name,
|
||||||
@@ -118,8 +122,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async updateUser() {
|
async updateUser() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
useAlert(this.$t('PROFILE_SETTINGS.FORM.ERROR'));
|
useAlert(this.$t('PROFILE_SETTINGS.FORM.ERROR'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<form class="flex flex-wrap mx-0" @submit.prevent="onSubmit">
|
<form class="flex flex-wrap mx-0" @submit.prevent="onSubmit">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="name"
|
v-model="name"
|
||||||
:class="{ error: $v.name.$error }"
|
:class="{ error: v$.name.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:styles="{
|
:styles="{
|
||||||
borderRadius: '12px',
|
borderRadius: '12px',
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
:label="$t('SLA.FORM.NAME.LABEL')"
|
:label="$t('SLA.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('SLA.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('SLA.FORM.NAME.PLACEHOLDER')"
|
||||||
:error="slaNameErrorMessage"
|
:error="slaNameErrorMessage"
|
||||||
@input="$v.name.$touch"
|
@input="v$.name.$touch"
|
||||||
/>
|
/>
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="description"
|
v-model="description"
|
||||||
@@ -72,6 +72,7 @@ import { mapGetters } from 'vuex';
|
|||||||
import { convertSecondsToTimeUnit } from '@chatwoot/utils';
|
import { convertSecondsToTimeUnit } from '@chatwoot/utils';
|
||||||
import validations from './validations';
|
import validations from './validations';
|
||||||
import SlaTimeInput from './SlaTimeInput.vue';
|
import SlaTimeInput from './SlaTimeInput.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -87,6 +88,9 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -123,17 +127,17 @@ export default {
|
|||||||
}),
|
}),
|
||||||
isSubmitDisabled() {
|
isSubmitDisabled() {
|
||||||
return (
|
return (
|
||||||
this.$v.name.$invalid ||
|
this.v$.name.$invalid ||
|
||||||
this.isSlaTimeInputsInvalid ||
|
this.isSlaTimeInputsInvalid ||
|
||||||
this.uiFlags.isUpdating
|
this.uiFlags.isUpdating
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
slaNameErrorMessage() {
|
slaNameErrorMessage() {
|
||||||
let errorMessage = '';
|
let errorMessage = '';
|
||||||
if (this.$v.name.$error) {
|
if (this.v$.name.$error) {
|
||||||
if (!this.$v.name.required) {
|
if (!this.v$.name.required) {
|
||||||
errorMessage = this.$t('SLA.FORM.NAME.REQUIRED_ERROR');
|
errorMessage = this.$t('SLA.FORM.NAME.REQUIRED_ERROR');
|
||||||
} else if (!this.$v.name.minLength) {
|
} else if (!this.v$.name.minLength) {
|
||||||
errorMessage = this.$t('SLA.FORM.NAME.MINIMUM_LENGTH_ERROR');
|
errorMessage = this.$t('SLA.FORM.NAME.MINIMUM_LENGTH_ERROR');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="flex items-center w-full gap-3">
|
<div class="flex items-center w-full gap-3">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model="thresholdTime"
|
v-model="thresholdTime"
|
||||||
:class="{ error: $v.thresholdTime.$error }"
|
:class="{ error: v$.thresholdTime.$error }"
|
||||||
class="flex-grow"
|
class="flex-grow"
|
||||||
:styles="{
|
:styles="{
|
||||||
borderRadius: '12px',
|
borderRadius: '12px',
|
||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import validations from './validations';
|
import validations from './validations';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -55,6 +56,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
thresholdTime: this.threshold || '',
|
thresholdTime: this.threshold || '',
|
||||||
@@ -70,8 +74,8 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
thresholdTimeErrorMessage() {
|
thresholdTimeErrorMessage() {
|
||||||
let errorMessage = '';
|
let errorMessage = '';
|
||||||
if (this.$v.thresholdTime.$error) {
|
if (this.v$.thresholdTime.$error) {
|
||||||
if (!this.$v.thresholdTime.numeric || !this.$v.thresholdTime.minValue) {
|
if (!this.v$.thresholdTime.numeric || !this.v$.thresholdTime.minValue) {
|
||||||
errorMessage = this.$t(
|
errorMessage = this.$t(
|
||||||
'SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR'
|
'SLA.FORM.THRESHOLD_TIME.INVALID_FORMAT_ERROR'
|
||||||
);
|
);
|
||||||
@@ -101,8 +105,8 @@ export default {
|
|||||||
this.$emit('unit', this.thresholdUnitValue);
|
this.$emit('unit', this.thresholdUnitValue);
|
||||||
},
|
},
|
||||||
onThresholdTimeChange() {
|
onThresholdTimeChange() {
|
||||||
this.$v.thresholdTime.$touch();
|
this.v$.thresholdTime.$touch();
|
||||||
const isInvalid = this.$v.thresholdTime.$invalid;
|
const isInvalid = this.v$.thresholdTime.$invalid;
|
||||||
this.$emit('isInValid', isInvalid);
|
this.$emit('isInValid', isInvalid);
|
||||||
this.$emit('input', Number(this.thresholdTime));
|
this.$emit('input', Number(this.thresholdTime));
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
import {
|
import { required, minLength, minValue, decimal } from '@vuelidate/validators';
|
||||||
required,
|
|
||||||
minLength,
|
|
||||||
minValue,
|
|
||||||
decimal,
|
|
||||||
} from 'vuelidate/lib/validators';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: {
|
name: {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div v-if="$v.selectedAgents.$error">
|
<div v-if="v$.selectedAgents.$error">
|
||||||
<p class="error-message">
|
<p class="error-message">
|
||||||
{{ $t('TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR') }}
|
{{ $t('TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR') }}
|
||||||
</p>
|
</p>
|
||||||
@@ -38,6 +38,7 @@ import { useAlert } from 'dashboard/composables';
|
|||||||
import router from '../../../../index';
|
import router from '../../../../index';
|
||||||
import PageHeader from '../../SettingsSubPageHeader.vue';
|
import PageHeader from '../../SettingsSubPageHeader.vue';
|
||||||
import AgentSelector from '../AgentSelector.vue';
|
import AgentSelector from '../AgentSelector.vue';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -58,6 +59,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedAgents: [],
|
selectedAgents: [],
|
||||||
@@ -89,7 +94,7 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
updateSelectedAgents(newAgentList) {
|
updateSelectedAgents(newAgentList) {
|
||||||
this.$v.selectedAgents.$touch();
|
this.v$.selectedAgents.$touch();
|
||||||
this.selectedAgents = [...newAgentList];
|
this.selectedAgents = [...newAgentList];
|
||||||
},
|
},
|
||||||
selectAllAgents() {
|
selectAllAgents() {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div v-if="$v.selectedAgents.$error">
|
<div v-if="v$.selectedAgents.$error">
|
||||||
<p class="error-message">
|
<p class="error-message">
|
||||||
{{ $t('TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR') }}
|
{{ $t('TEAMS_SETTINGS.ADD.AGENT_VALIDATION_ERROR') }}
|
||||||
</p>
|
</p>
|
||||||
@@ -37,10 +37,11 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import router from '../../../../index';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
import Spinner from 'shared/components/Spinner.vue';
|
import Spinner from 'shared/components/Spinner.vue';
|
||||||
import router from '../../../../index';
|
|
||||||
import PageHeader from '../../SettingsSubPageHeader.vue';
|
import PageHeader from '../../SettingsSubPageHeader.vue';
|
||||||
import AgentSelector from '../AgentSelector.vue';
|
import AgentSelector from '../AgentSelector.vue';
|
||||||
|
|
||||||
@@ -64,7 +65,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedAgents: [],
|
selectedAgents: [],
|
||||||
@@ -114,7 +117,7 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
updateSelectedAgents(newAgentList) {
|
updateSelectedAgents(newAgentList) {
|
||||||
this.$v.selectedAgents.$touch();
|
this.v$.selectedAgents.$touch();
|
||||||
this.selectedAgents = [...newAgentList];
|
this.selectedAgents = [...newAgentList];
|
||||||
},
|
},
|
||||||
async addAgents() {
|
async addAgents() {
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
<form class="mx-0 flex flex-wrap" @submit.prevent="handleSubmit">
|
<form class="mx-0 flex flex-wrap" @submit.prevent="handleSubmit">
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="title"
|
v-model.trim="title"
|
||||||
:class="{ error: $v.title.$error }"
|
:class="{ error: v$.title.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:label="$t('TEAMS_SETTINGS.FORM.NAME.LABEL')"
|
:label="$t('TEAMS_SETTINGS.FORM.NAME.LABEL')"
|
||||||
:placeholder="$t('TEAMS_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
:placeholder="$t('TEAMS_SETTINGS.FORM.NAME.PLACEHOLDER')"
|
||||||
@input="$v.title.$touch"
|
@input="v$.title.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<woot-input
|
<woot-input
|
||||||
v-model.trim="description"
|
v-model.trim="description"
|
||||||
:class="{ error: $v.description.$error }"
|
:class="{ error: v$.description.$error }"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:label="$t('TEAMS_SETTINGS.FORM.DESCRIPTION.LABEL')"
|
:label="$t('TEAMS_SETTINGS.FORM.DESCRIPTION.LABEL')"
|
||||||
:placeholder="$t('TEAMS_SETTINGS.FORM.DESCRIPTION.PLACEHOLDER')"
|
:placeholder="$t('TEAMS_SETTINGS.FORM.DESCRIPTION.PLACEHOLDER')"
|
||||||
@input="$v.description.$touch"
|
@input="v$.description.$touch"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="w-full flex items-center gap-2">
|
<div class="w-full flex items-center gap-2">
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
<div class="flex flex-row justify-end gap-2 py-2 px-0 w-full">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:disabled="$v.title.$invalid || submitInProgress"
|
:disabled="v$.title.$invalid || submitInProgress"
|
||||||
:button-text="submitButtonText"
|
:button-text="submitButtonText"
|
||||||
:loading="submitInProgress"
|
:loading="submitInProgress"
|
||||||
/>
|
/>
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vue';
|
||||||
import validations from './helpers/validations';
|
import validations from './helpers/validations';
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -67,6 +68,9 @@ export default {
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const formData = this.formData || {};
|
const formData = this.formData || {};
|
||||||
const {
|
const {
|
||||||
@@ -84,8 +88,8 @@ export default {
|
|||||||
validations,
|
validations,
|
||||||
methods: {
|
methods: {
|
||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.onSubmit({
|
this.onSubmit({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: {
|
title: {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import VueFormulate from '@braid/vue-formulate';
|
|||||||
import WootSwitch from 'components/ui/Switch';
|
import WootSwitch from 'components/ui/Switch';
|
||||||
import WootWizard from 'components/ui/Wizard';
|
import WootWizard from 'components/ui/Wizard';
|
||||||
import { sync } from 'vuex-router-sync';
|
import { sync } from 'vuex-router-sync';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import VTooltip from 'v-tooltip';
|
import VTooltip from 'v-tooltip';
|
||||||
import WootUiKit from '../dashboard/components';
|
import WootUiKit from '../dashboard/components';
|
||||||
import App from '../dashboard/App';
|
import App from '../dashboard/App';
|
||||||
@@ -65,7 +64,6 @@ Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
|||||||
Vue.use(VueRouter);
|
Vue.use(VueRouter);
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
Vue.use(WootUiKit);
|
Vue.use(WootUiKit);
|
||||||
Vue.use(Vuelidate);
|
|
||||||
Vue.use(VueFormulate, {
|
Vue.use(VueFormulate, {
|
||||||
rules: {
|
rules: {
|
||||||
JSON: ({ value }) => isJSONValid(value),
|
JSON: ({ value }) => isJSONValid(value),
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import VueI18n from 'vue-i18n';
|
import VueI18n from 'vue-i18n';
|
||||||
import App from '../survey/App.vue';
|
import App from '../survey/App.vue';
|
||||||
import i18n from '../survey/i18n';
|
import i18n from '../survey/i18n';
|
||||||
@@ -7,7 +6,6 @@ import store from '../survey/store';
|
|||||||
import { emitter } from 'shared/helpers/mitt';
|
import { emitter } from 'shared/helpers/mitt';
|
||||||
|
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
Vue.use(Vuelidate);
|
|
||||||
|
|
||||||
const i18nConfig = new VueI18n({
|
const i18nConfig = new VueI18n({
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueI18n from 'vue-i18n';
|
import VueI18n from 'vue-i18n';
|
||||||
import VueRouter from 'vue-router';
|
import VueRouter from 'vue-router';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import i18n from 'dashboard/i18n';
|
import i18n from 'dashboard/i18n';
|
||||||
import * as Sentry from '@sentry/vue';
|
import * as Sentry from '@sentry/vue';
|
||||||
import { Integrations } from '@sentry/tracing';
|
import { Integrations } from '@sentry/tracing';
|
||||||
@@ -44,7 +43,7 @@ if (window.errorLoggingConfig) {
|
|||||||
|
|
||||||
Vue.use(VueRouter);
|
Vue.use(VueRouter);
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
Vue.use(Vuelidate);
|
|
||||||
Vue.use(AnalyticsPlugin);
|
Vue.use(AnalyticsPlugin);
|
||||||
Vue.prototype.$emitter = emitter;
|
Vue.prototype.$emitter = emitter;
|
||||||
Vue.component('fluent-icon', FluentIcon);
|
Vue.component('fluent-icon', FluentIcon);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import VueI18n from 'vue-i18n';
|
import VueI18n from 'vue-i18n';
|
||||||
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
import VueDOMPurifyHTML from 'vue-dompurify-html';
|
||||||
import VueFormulate from '@braid/vue-formulate';
|
import VueFormulate from '@braid/vue-formulate';
|
||||||
@@ -18,7 +17,7 @@ import { domPurifyConfig } from '../shared/helpers/HTMLSanitizer';
|
|||||||
const PhoneInput = () => import('../widget/components/Form/PhoneInput');
|
const PhoneInput = () => import('../widget/components/Form/PhoneInput');
|
||||||
|
|
||||||
Vue.use(VueI18n);
|
Vue.use(VueI18n);
|
||||||
Vue.use(Vuelidate);
|
|
||||||
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
Vue.use(VueDOMPurifyHTML, domPurifyConfig);
|
||||||
Vue.directive('on-clickaway', onClickaway);
|
Vue.directive('on-clickaway', onClickaway);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import methodsMixin from '../../../dashboard/mixins/automations/methodsMixin';
|
import methodsMixin from '../../../dashboard/mixins/automations/methodsMixin';
|
||||||
import validationsMixin from '../../../dashboard/mixins/automations/validationsMixin';
|
|
||||||
import {
|
import {
|
||||||
automation,
|
automation,
|
||||||
customAttributes,
|
customAttributes,
|
||||||
@@ -30,8 +29,6 @@ const localVue = createLocalVue();
|
|||||||
localVue.use(Vuex);
|
localVue.use(Vuex);
|
||||||
|
|
||||||
// Vuelidate required to test submit method
|
// Vuelidate required to test submit method
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
Vue.use(Vuelidate);
|
|
||||||
|
|
||||||
const createComponent = (
|
const createComponent = (
|
||||||
mixins,
|
mixins,
|
||||||
@@ -451,13 +448,3 @@ describe('automationMethodsMixin', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('automationValidationsMixin', () => {
|
|
||||||
it('automationValidationsMixin is present', () => {
|
|
||||||
const data = () => {
|
|
||||||
return {};
|
|
||||||
};
|
|
||||||
const wrapper = createComponent([validationsMixin], data, {}, {});
|
|
||||||
expect(typeof wrapper.vm.$options.validations).toBe('object');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|||||||
import { templates } from './fixtures';
|
import { templates } from './fixtures';
|
||||||
const localVue = createLocalVue();
|
const localVue = createLocalVue();
|
||||||
import VueI18n from 'vue-i18n';
|
import VueI18n from 'vue-i18n';
|
||||||
import Vuelidate from 'vuelidate';
|
|
||||||
import i18n from 'dashboard/i18n';
|
import i18n from 'dashboard/i18n';
|
||||||
|
|
||||||
localVue.use(VueI18n);
|
localVue.use(VueI18n);
|
||||||
localVue.use(Vuelidate);
|
|
||||||
|
|
||||||
const i18nConfig = new VueI18n({ locale: 'en', messages: i18n });
|
const i18nConfig = new VueI18n({ locale: 'en', messages: i18n });
|
||||||
const config = {
|
const config = {
|
||||||
|
|||||||
@@ -18,25 +18,25 @@
|
|||||||
class="mt-3"
|
class="mt-3"
|
||||||
name="password"
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
:has-error="$v.credentials.password.$error"
|
:has-error="v$.credentials.password.$error"
|
||||||
:error-message="$t('SET_NEW_PASSWORD.PASSWORD.ERROR')"
|
:error-message="$t('SET_NEW_PASSWORD.PASSWORD.ERROR')"
|
||||||
:placeholder="$t('SET_NEW_PASSWORD.PASSWORD.PLACEHOLDER')"
|
:placeholder="$t('SET_NEW_PASSWORD.PASSWORD.PLACEHOLDER')"
|
||||||
@blur="$v.credentials.password.$touch"
|
@blur="v$.credentials.password.$touch"
|
||||||
/>
|
/>
|
||||||
<form-input
|
<form-input
|
||||||
v-model.trim="credentials.confirmPassword"
|
v-model.trim="credentials.confirmPassword"
|
||||||
class="mt-3"
|
class="mt-3"
|
||||||
name="confirm_password"
|
name="confirm_password"
|
||||||
type="password"
|
type="password"
|
||||||
:has-error="$v.credentials.confirmPassword.$error"
|
:has-error="v$.credentials.confirmPassword.$error"
|
||||||
:error-message="$t('SET_NEW_PASSWORD.CONFIRM_PASSWORD.ERROR')"
|
:error-message="$t('SET_NEW_PASSWORD.CONFIRM_PASSWORD.ERROR')"
|
||||||
:placeholder="$t('SET_NEW_PASSWORD.CONFIRM_PASSWORD.PLACEHOLDER')"
|
:placeholder="$t('SET_NEW_PASSWORD.CONFIRM_PASSWORD.PLACEHOLDER')"
|
||||||
@blur="$v.credentials.confirmPassword.$touch"
|
@blur="v$.credentials.confirmPassword.$touch"
|
||||||
/>
|
/>
|
||||||
<submit-button
|
<submit-button
|
||||||
:disabled="
|
:disabled="
|
||||||
$v.credentials.password.$invalid ||
|
v$.credentials.password.$invalid ||
|
||||||
$v.credentials.confirmPassword.$invalid ||
|
v$.credentials.confirmPassword.$invalid ||
|
||||||
newPasswordAPI.showLoading
|
newPasswordAPI.showLoading
|
||||||
"
|
"
|
||||||
:button-text="$t('SET_NEW_PASSWORD.SUBMIT')"
|
:button-text="$t('SET_NEW_PASSWORD.SUBMIT')"
|
||||||
@@ -48,7 +48,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import FormInput from '../../../components/Form/Input.vue';
|
import FormInput from '../../../components/Form/Input.vue';
|
||||||
import SubmitButton from '../../../components/Button/SubmitButton.vue';
|
import SubmitButton from '../../../components/Button/SubmitButton.vue';
|
||||||
@@ -65,6 +66,9 @@ export default {
|
|||||||
redirectUrl: { type: String, default: '' },
|
redirectUrl: { type: String, default: '' },
|
||||||
config: { type: String, default: '' },
|
config: { type: String, default: '' },
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// We need to initialize the component with any
|
// We need to initialize the component with any
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
<form-input
|
<form-input
|
||||||
v-model.trim="credentials.email"
|
v-model.trim="credentials.email"
|
||||||
name="email_address"
|
name="email_address"
|
||||||
:has-error="$v.credentials.email.$error"
|
:has-error="v$.credentials.email.$error"
|
||||||
:error-message="$t('RESET_PASSWORD.EMAIL.ERROR')"
|
:error-message="$t('RESET_PASSWORD.EMAIL.ERROR')"
|
||||||
:placeholder="$t('RESET_PASSWORD.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('RESET_PASSWORD.EMAIL.PLACEHOLDER')"
|
||||||
@input="$v.credentials.email.$touch"
|
@input="v$.credentials.email.$touch"
|
||||||
/>
|
/>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
:disabled="$v.credentials.email.$invalid || resetPassword.showLoading"
|
:disabled="v$.credentials.email.$invalid || resetPassword.showLoading"
|
||||||
:button-text="$t('RESET_PASSWORD.SUBMIT')"
|
:button-text="$t('RESET_PASSWORD.SUBMIT')"
|
||||||
:loading="resetPassword.showLoading"
|
:loading="resetPassword.showLoading"
|
||||||
/>
|
/>
|
||||||
@@ -47,9 +47,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||||
import FormInput from '../../../../components/Form/Input.vue';
|
import FormInput from '../../../../components/Form/Input.vue';
|
||||||
import { resetPassword } from '../../../../api/auth';
|
import { resetPassword } from '../../../../api/auth';
|
||||||
@@ -58,6 +59,9 @@ import SubmitButton from '../../../../components/Button/SubmitButton.vue';
|
|||||||
export default {
|
export default {
|
||||||
components: { FormInput, SubmitButton },
|
components: { FormInput, SubmitButton },
|
||||||
mixins: [globalConfigMixin],
|
mixins: [globalConfigMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
credentials: { email: '' },
|
credentials: { email: '' },
|
||||||
|
|||||||
@@ -6,46 +6,46 @@
|
|||||||
v-model.trim="credentials.fullName"
|
v-model.trim="credentials.fullName"
|
||||||
name="full_name"
|
name="full_name"
|
||||||
class="flex-1"
|
class="flex-1"
|
||||||
:class="{ error: $v.credentials.fullName.$error }"
|
:class="{ error: v$.credentials.fullName.$error }"
|
||||||
:label="$t('REGISTER.FULL_NAME.LABEL')"
|
:label="$t('REGISTER.FULL_NAME.LABEL')"
|
||||||
:placeholder="$t('REGISTER.FULL_NAME.PLACEHOLDER')"
|
:placeholder="$t('REGISTER.FULL_NAME.PLACEHOLDER')"
|
||||||
:has-error="$v.credentials.fullName.$error"
|
:has-error="v$.credentials.fullName.$error"
|
||||||
:error-message="$t('REGISTER.FULL_NAME.ERROR')"
|
:error-message="$t('REGISTER.FULL_NAME.ERROR')"
|
||||||
@blur="$v.credentials.fullName.$touch"
|
@blur="v$.credentials.fullName.$touch"
|
||||||
/>
|
/>
|
||||||
<form-input
|
<form-input
|
||||||
v-model.trim="credentials.accountName"
|
v-model.trim="credentials.accountName"
|
||||||
name="account_name"
|
name="account_name"
|
||||||
class="flex-1 ml-2"
|
class="flex-1 ml-2"
|
||||||
:class="{ error: $v.credentials.accountName.$error }"
|
:class="{ error: v$.credentials.accountName.$error }"
|
||||||
:label="$t('REGISTER.COMPANY_NAME.LABEL')"
|
:label="$t('REGISTER.COMPANY_NAME.LABEL')"
|
||||||
:placeholder="$t('REGISTER.COMPANY_NAME.PLACEHOLDER')"
|
:placeholder="$t('REGISTER.COMPANY_NAME.PLACEHOLDER')"
|
||||||
:has-error="$v.credentials.accountName.$error"
|
:has-error="v$.credentials.accountName.$error"
|
||||||
:error-message="$t('REGISTER.COMPANY_NAME.ERROR')"
|
:error-message="$t('REGISTER.COMPANY_NAME.ERROR')"
|
||||||
@blur="$v.credentials.accountName.$touch"
|
@blur="v$.credentials.accountName.$touch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<form-input
|
<form-input
|
||||||
v-model.trim="credentials.email"
|
v-model.trim="credentials.email"
|
||||||
type="email"
|
type="email"
|
||||||
name="email_address"
|
name="email_address"
|
||||||
:class="{ error: $v.credentials.email.$error }"
|
:class="{ error: v$.credentials.email.$error }"
|
||||||
:label="$t('REGISTER.EMAIL.LABEL')"
|
:label="$t('REGISTER.EMAIL.LABEL')"
|
||||||
:placeholder="$t('REGISTER.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('REGISTER.EMAIL.PLACEHOLDER')"
|
||||||
:has-error="$v.credentials.email.$error"
|
:has-error="v$.credentials.email.$error"
|
||||||
:error-message="$t('REGISTER.EMAIL.ERROR')"
|
:error-message="$t('REGISTER.EMAIL.ERROR')"
|
||||||
@blur="$v.credentials.email.$touch"
|
@blur="v$.credentials.email.$touch"
|
||||||
/>
|
/>
|
||||||
<form-input
|
<form-input
|
||||||
v-model.trim="credentials.password"
|
v-model.trim="credentials.password"
|
||||||
type="password"
|
type="password"
|
||||||
name="password"
|
name="password"
|
||||||
:class="{ error: $v.credentials.password.$error }"
|
:class="{ error: v$.credentials.password.$error }"
|
||||||
:label="$t('LOGIN.PASSWORD.LABEL')"
|
:label="$t('LOGIN.PASSWORD.LABEL')"
|
||||||
:placeholder="$t('SET_NEW_PASSWORD.PASSWORD.PLACEHOLDER')"
|
:placeholder="$t('SET_NEW_PASSWORD.PASSWORD.PLACEHOLDER')"
|
||||||
:has-error="$v.credentials.password.$error"
|
:has-error="v$.credentials.password.$error"
|
||||||
:error-message="passwordErrorText"
|
:error-message="passwordErrorText"
|
||||||
@blur="$v.credentials.password.$touch"
|
@blur="v$.credentials.password.$touch"
|
||||||
/>
|
/>
|
||||||
<div v-if="globalConfig.hCaptchaSiteKey" class="mb-3">
|
<div v-if="globalConfig.hCaptchaSiteKey" class="mb-3">
|
||||||
<vue-hcaptcha
|
<vue-hcaptcha
|
||||||
@@ -79,7 +79,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, minLength, email } from '@vuelidate/validators';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||||
@@ -100,6 +101,9 @@ export default {
|
|||||||
VueHcaptcha,
|
VueHcaptcha,
|
||||||
},
|
},
|
||||||
mixins: [globalConfigMixin],
|
mixins: [globalConfigMixin],
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
credentials: {
|
credentials: {
|
||||||
@@ -155,7 +159,7 @@ export default {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
passwordErrorText() {
|
passwordErrorText() {
|
||||||
const { password } = this.$v.credentials;
|
const { password } = this.v$.credentials;
|
||||||
if (!password.$error) {
|
if (!password.$error) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -173,8 +177,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async submit() {
|
async submit() {
|
||||||
this.$v.$touch();
|
this.v$.$touch();
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
this.resetCaptcha();
|
this.resetCaptcha();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@
|
|||||||
required
|
required
|
||||||
:label="$t('LOGIN.EMAIL.LABEL')"
|
:label="$t('LOGIN.EMAIL.LABEL')"
|
||||||
:placeholder="$t('LOGIN.EMAIL.PLACEHOLDER')"
|
:placeholder="$t('LOGIN.EMAIL.PLACEHOLDER')"
|
||||||
:has-error="$v.credentials.email.$error"
|
:has-error="v$.credentials.email.$error"
|
||||||
@input="$v.credentials.email.$touch"
|
@input="v$.credentials.email.$touch"
|
||||||
/>
|
/>
|
||||||
<form-input
|
<form-input
|
||||||
v-model.trim="credentials.password"
|
v-model.trim="credentials.password"
|
||||||
@@ -62,8 +62,8 @@
|
|||||||
:tabindex="2"
|
:tabindex="2"
|
||||||
:label="$t('LOGIN.PASSWORD.LABEL')"
|
:label="$t('LOGIN.PASSWORD.LABEL')"
|
||||||
:placeholder="$t('LOGIN.PASSWORD.PLACEHOLDER')"
|
:placeholder="$t('LOGIN.PASSWORD.PLACEHOLDER')"
|
||||||
:has-error="$v.credentials.password.$error"
|
:has-error="v$.credentials.password.$error"
|
||||||
@input="$v.credentials.password.$touch"
|
@input="v$.credentials.password.$touch"
|
||||||
>
|
>
|
||||||
<p v-if="!globalConfig.disableUserProfileUpdate">
|
<p v-if="!globalConfig.disableUserProfileUpdate">
|
||||||
<router-link
|
<router-link
|
||||||
@@ -91,8 +91,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, email } from '@vuelidate/validators';
|
||||||
import { useAlert } from 'dashboard/composables';
|
import { useAlert } from 'dashboard/composables';
|
||||||
import { required, email } from 'vuelidate/lib/validators';
|
|
||||||
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
||||||
import SubmitButton from '../../components/Button/SubmitButton.vue';
|
import SubmitButton from '../../components/Button/SubmitButton.vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
@@ -122,6 +123,9 @@ export default {
|
|||||||
email: { type: String, default: '' },
|
email: { type: String, default: '' },
|
||||||
authError: { type: String, default: '' },
|
authError: { type: String, default: '' },
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// We need to initialize the component with any
|
// We need to initialize the component with any
|
||||||
@@ -194,7 +198,7 @@ export default {
|
|||||||
useAlert(this.loginApi.message);
|
useAlert(this.loginApi.message);
|
||||||
},
|
},
|
||||||
submitLogin() {
|
submitLogin() {
|
||||||
if (this.$v.credentials.email.$invalid && !this.email) {
|
if (this.v$.credentials.email.$invalid && !this.email) {
|
||||||
this.showAlertMessage(this.$t('LOGIN.EMAIL.ERROR'));
|
this.showAlertMessage(this.$t('LOGIN.EMAIL.ERROR'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
class="form-input"
|
class="form-input"
|
||||||
:placeholder="$t('EMAIL_PLACEHOLDER')"
|
:placeholder="$t('EMAIL_PLACEHOLDER')"
|
||||||
:class="inputHasError"
|
:class="inputHasError"
|
||||||
@input="$v.email.$touch"
|
@input="v$.email.$touch"
|
||||||
@keydown.enter="onSubmit"
|
@keydown.enter="onSubmit"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
class="button small"
|
class="button small"
|
||||||
:disabled="$v.email.$invalid"
|
:disabled="v$.email.$invalid"
|
||||||
:style="{
|
:style="{
|
||||||
background: widgetColor,
|
background: widgetColor,
|
||||||
borderColor: widgetColor,
|
borderColor: widgetColor,
|
||||||
@@ -31,7 +31,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { required, email } from 'vuelidate/lib/validators';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
|
import { required, email } from '@vuelidate/validators';
|
||||||
import { getContrastingTextColor } from '@chatwoot/utils';
|
import { getContrastingTextColor } from '@chatwoot/utils';
|
||||||
|
|
||||||
import FluentIcon from 'shared/components/FluentIcon/Index.vue';
|
import FluentIcon from 'shared/components/FluentIcon/Index.vue';
|
||||||
@@ -54,6 +55,9 @@ export default {
|
|||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return { v$: useVuelidate() };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
email: '',
|
email: '',
|
||||||
@@ -79,7 +83,7 @@ export default {
|
|||||||
${this.$dm('border-black-200', 'dark:border-black-500')}`;
|
${this.$dm('border-black-200', 'dark:border-black-500')}`;
|
||||||
},
|
},
|
||||||
inputHasError() {
|
inputHasError() {
|
||||||
return this.$v.email.$error
|
return this.v$.email.$error
|
||||||
? `${this.inputColor} error`
|
? `${this.inputColor} error`
|
||||||
: `${this.inputColor}`;
|
: `${this.inputColor}`;
|
||||||
},
|
},
|
||||||
@@ -92,7 +96,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onSubmit() {
|
async onSubmit() {
|
||||||
if (this.$v.$invalid) {
|
if (this.v$.$invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isUpdating = true;
|
this.isUpdating = true;
|
||||||
|
|||||||
@@ -96,7 +96,6 @@
|
|||||||
"vue-virtual-scroll-list": "^2.3.5",
|
"vue-virtual-scroll-list": "^2.3.5",
|
||||||
"vue2-datepicker": "^3.9.1",
|
"vue2-datepicker": "^3.9.1",
|
||||||
"vuedraggable": "^2.24.3",
|
"vuedraggable": "^2.24.3",
|
||||||
"vuelidate": "0.7.7",
|
|
||||||
"vuex": "~2.1.1",
|
"vuex": "~2.1.1",
|
||||||
"vuex-router-sync": "~4.1.2",
|
"vuex-router-sync": "~4.1.2",
|
||||||
"wavesurfer.js": "^6.0.4",
|
"wavesurfer.js": "^6.0.4",
|
||||||
|
|||||||
36
yarn.lock
36
yarn.lock
@@ -18413,16 +18413,7 @@ string-argv@0.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
|
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
|
||||||
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
|
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0":
|
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.2.2, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
|
||||||
dependencies:
|
|
||||||
emoji-regex "^8.0.0"
|
|
||||||
is-fullwidth-code-point "^3.0.0"
|
|
||||||
strip-ansi "^6.0.1"
|
|
||||||
|
|
||||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.2.2, string-width@^4.2.3:
|
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@@ -18574,7 +18565,7 @@ string_decoder@~1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
@@ -18602,13 +18593,6 @@ strip-ansi@^6.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^5.0.0"
|
ansi-regex "^5.0.0"
|
||||||
|
|
||||||
strip-ansi@^6.0.1:
|
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^5.0.1"
|
|
||||||
|
|
||||||
strip-ansi@^7.0.1:
|
strip-ansi@^7.0.1:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||||
@@ -20126,11 +20110,6 @@ vuedraggable@^2.24.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sortablejs "1.10.2"
|
sortablejs "1.10.2"
|
||||||
|
|
||||||
vuelidate@0.7.7:
|
|
||||||
version "0.7.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/vuelidate/-/vuelidate-0.7.7.tgz#5df3930a63ddecf56fde7bdacea9dbaf0c9bf899"
|
|
||||||
integrity sha512-pT/U2lDI67wkIqI4tum7cMSIfGcAMfB+Phtqh2ttdXURwvHRBJEAQ0tVbUsW9Upg83Q5QH59bnCoXI7A9JDGnA==
|
|
||||||
|
|
||||||
vuex-router-sync@~4.1.2:
|
vuex-router-sync@~4.1.2:
|
||||||
version "4.1.3"
|
version "4.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/vuex-router-sync/-/vuex-router-sync-4.1.3.tgz#f209ec3174de04179bfadd7994437e4c5a81c975"
|
resolved "https://registry.yarnpkg.com/vuex-router-sync/-/vuex-router-sync-4.1.3.tgz#f209ec3174de04179bfadd7994437e4c5a81c975"
|
||||||
@@ -20547,7 +20526,7 @@ worker-rpc@^0.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
microevent.ts "~0.1.1"
|
microevent.ts "~0.1.1"
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
@@ -20574,15 +20553,6 @@ wrap-ansi@^6.2.0:
|
|||||||
string-width "^4.1.0"
|
string-width "^4.1.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
|
||||||
dependencies:
|
|
||||||
ansi-styles "^4.0.0"
|
|
||||||
string-width "^4.1.0"
|
|
||||||
strip-ansi "^6.0.0"
|
|
||||||
|
|
||||||
wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
|
wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
|
||||||
version "8.1.0"
|
version "8.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||||
|
|||||||
Reference in New Issue
Block a user