feat: Eslint rules (#9839)

# Pull Request Template

## Description

This PR adds new eslint rules to the code base.

**Error rules**

|    Rule name     | Type | Files updated |
| ----------------- | --- | - |
| `vue/block-order`  | error  |    |
| `vue/component-name-in-template-casing`  | error  |    |
| `vue/component-options-name-casing`  | error  |    |
| `vue/custom-event-name-casing`  | error  |    |
| `vue/define-emits-declaration`  | error  |    |
| `vue/no-unused-properties`  | error  |    |
| `vue/define-macros-order`  | error  |    |
| `vue/define-props-declaration`  | error  |    |
| `vue/match-component-import-name`  | error  |    |
| `vue/next-tick-style`  | error  |    |
| `vue/no-bare-strings-in-template`  | error  |    |
| `vue/no-empty-component-block`  | error  |    |
| `vue/no-multiple-objects-in-class`  | error  |    |
| `vue/no-required-prop-with-default`  | error  |    |
| `vue/no-static-inline-styles`  | error  |    |
| `vue/no-template-target-blank`  | error  |    |
| `vue/no-this-in-before-route-enter`  | error  |    |
| `vue/no-undef-components`  | error  |    |
| `vue/no-unused-emit-declarations`  | error  |    |
| `vue/no-unused-refs`  | error  |    |
| `vue/no-use-v-else-with-v-for`  | error  |    |
| `vue/no-useless-v-bind`  | error  |    |
| `vue/no-v-text`  | error  |    |
| `vue/padding-line-between-blocks`  | error  |    |
| ~`vue/prefer-prop-type-boolean-first`~ | ~error~ |  (removed this
rule, cause a bug in displaying custom attributes) |
| `vue/prefer-separate-static-class`  | error  |    |
| `vue/prefer-true-attribute-shorthand`  | error  |    |
| `vue/require-explicit-slots`  | error  |    |
| `vue/require-macro-variable-name`  | error  |    |


**Warn rules**

|    Rule name     | Type | Files updated |
| ---- | ------------- | ------------- |
| `vue/no-root-v-if`  | warn  |    |


Fixes https://linear.app/chatwoot/issue/CW-3492/vue-eslint-rules

## Type of change

- [x] New feature (non-breaking change which adds functionality)


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Fayaz Ahmed <fayazara@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
Sivin Varghese
2024-08-05 14:02:16 +05:30
committed by GitHub
parent 6166ccb014
commit b4b308336f
625 changed files with 23071 additions and 22980 deletions

View File

@@ -1,41 +1,3 @@
<!-- eslint-disable vue/no-mutating-props -->
<template>
<modal :show.sync="show" :on-close="onClose">
<woot-modal-header
:header-title="$t('CUSTOM_ATTRIBUTES.ADD.TITLE')"
:header-content="$t('CUSTOM_ATTRIBUTES.ADD.DESC')"
/>
<form class="w-full" @submit.prevent="addCustomAttribute">
<woot-input
v-model.trim="attributeName"
:class="{ error: v$.attributeName.$error }"
class="w-full"
:error="attributeNameError"
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
@input="v$.attributeName.$touch"
/>
<woot-input
v-model.trim="attributeValue"
class="w-full"
:label="$t('CUSTOM_ATTRIBUTES.FORM.VALUE.LABEL')"
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.VALUE.PLACEHOLDER')"
/>
<div class="flex items-center justify-end gap-2 px-0 py-2">
<woot-button
:is-disabled="v$.attributeName.$invalid || isCreating"
:is-loading="isCreating"
>
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
</woot-button>
<woot-button variant="clear" @click.prevent="onClose">
{{ $t('CUSTOM_ATTRIBUTES.FORM.CANCEL') }}
</woot-button>
</div>
</form>
</modal>
</template>
<script>
import Modal from 'dashboard/components/Modal.vue';
import { useVuelidate } from '@vuelidate/core';
@@ -98,3 +60,41 @@ export default {
},
};
</script>
<!-- eslint-disable vue/no-mutating-props -->
<template>
<Modal :show.sync="show" :on-close="onClose">
<woot-modal-header
:header-title="$t('CUSTOM_ATTRIBUTES.ADD.TITLE')"
:header-content="$t('CUSTOM_ATTRIBUTES.ADD.DESC')"
/>
<form class="w-full" @submit.prevent="addCustomAttribute">
<woot-input
v-model.trim="attributeName"
:class="{ error: v$.attributeName.$error }"
class="w-full"
:error="attributeNameError"
:label="$t('CUSTOM_ATTRIBUTES.FORM.NAME.LABEL')"
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.NAME.PLACEHOLDER')"
@input="v$.attributeName.$touch"
/>
<woot-input
v-model.trim="attributeValue"
class="w-full"
:label="$t('CUSTOM_ATTRIBUTES.FORM.VALUE.LABEL')"
:placeholder="$t('CUSTOM_ATTRIBUTES.FORM.VALUE.PLACEHOLDER')"
/>
<div class="flex items-center justify-end gap-2 px-0 py-2">
<woot-button
:is-disabled="v$.attributeName.$invalid || isCreating"
:is-loading="isCreating"
>
{{ $t('CUSTOM_ATTRIBUTES.FORM.CREATE') }}
</woot-button>
<woot-button variant="clear" @click.prevent="onClose">
{{ $t('CUSTOM_ATTRIBUTES.FORM.CANCEL') }}
</woot-button>
</div>
</form>
</Modal>
</template>

View File

@@ -1,9 +1,47 @@
<script>
import EmojiOrIcon from 'shared/components/EmojiOrIcon.vue';
export default {
components: {
EmojiOrIcon,
},
props: {
label: { type: String, required: true },
icon: { type: String, default: '' },
emoji: { type: String, default: '' },
value: { type: [String, Number], default: '' },
showEdit: { type: Boolean, default: false },
},
data() {
return {
isEditing: false,
editedValue: this.value,
};
},
methods: {
focusInput() {
this.$refs.inputfield.focus();
},
onEdit() {
this.isEditing = true;
this.$nextTick(() => {
this.focusInput();
});
},
onUpdate() {
this.isEditing = false;
this.$emit('update', this.editedValue);
},
},
};
</script>
<template>
<div class="contact-attribute">
<div class="title-wrap">
<h4 class="text-sm title">
<div class="title--icon">
<emoji-or-icon :icon="icon" :emoji="emoji" />
<EmojiOrIcon :icon="icon" :emoji="emoji" />
</div>
{{ label }}
</h4>
@@ -49,44 +87,6 @@
</div>
</template>
<script>
import EmojiOrIcon from 'shared/components/EmojiOrIcon.vue';
export default {
components: {
EmojiOrIcon,
},
props: {
label: { type: String, required: true },
icon: { type: String, default: '' },
emoji: { type: String, default: '' },
value: { type: [String, Number], default: '' },
showEdit: { type: Boolean, default: false },
},
data() {
return {
isEditing: false,
editedValue: this.value,
};
},
methods: {
focusInput() {
this.$refs.inputfield.focus();
},
onEdit() {
this.isEditing = true;
this.$nextTick(() => {
this.focusInput();
});
},
onUpdate() {
this.isEditing = false;
this.$emit('update', this.editedValue);
},
},
};
</script>
<style lang="scss" scoped>
.contact-attribute {
margin-bottom: var(--space-small);

View File

@@ -1,28 +1,3 @@
<template>
<div class="option-item--user">
<thumbnail :src="thumbnail" size="28px" :username="name" />
<div class="option__user-data">
<h5 class="option__title">
{{ name }}
<span v-if="identifier" class="user-identifier">
(ID: {{ identifier }})
</span>
</h5>
<p class="option__body">
<span v-if="email" class="email-icon-wrap">
<fluent-icon class="merge-contact--icon" icon="mail" size="12" />
{{ email }}
</span>
<span v-if="phoneNumber" class="phone-icon-wrap">
<fluent-icon class="merge-contact--icon" icon="call" size="12" />
{{ phoneNumber }}
</span>
<span v-if="!phoneNumber && !email">{{ '---' }}</span>
</p>
</div>
</div>
</template>
<script>
import Thumbnail from '../../../components/widgets/Thumbnail.vue';
@@ -55,6 +30,31 @@ export default {
};
</script>
<template>
<div class="option-item--user">
<Thumbnail :src="thumbnail" size="28px" :username="name" />
<div class="option__user-data">
<h5 class="option__title">
{{ name }}
<span v-if="identifier" class="user-identifier">
{{ $t('MERGE_CONTACTS.DROPDOWN_ITEM.ID', { identifier }) }}
</span>
</h5>
<p class="option__body">
<span v-if="email" class="email-icon-wrap">
<fluent-icon class="merge-contact--icon" icon="mail" size="12" />
{{ email }}
</span>
<span v-if="phoneNumber" class="phone-icon-wrap">
<fluent-icon class="merge-contact--icon" icon="call" size="12" />
{{ phoneNumber }}
</span>
<span v-if="!phoneNumber && !email">{{ '---' }}</span>
</p>
</div>
</div>
</template>
<style lang="scss" scoped>
.option-item--user {
@apply flex items-center;

View File

@@ -1,56 +1,3 @@
<template>
<div class="contact-fields">
<h3 class="text-lg title">
{{ $t('CONTACTS_PAGE.FIELDS') }}
</h3>
<attribute
:label="$t('CONTACT_PANEL.EMAIL_ADDRESS')"
icon="mail"
emoji=""
:value="contact.email"
:show-edit="true"
@update="onEmailUpdate"
/>
<attribute
:label="$t('CONTACT_PANEL.PHONE_NUMBER')"
icon="call"
emoji=""
:value="contact.phone_number"
:show-edit="true"
@update="onPhoneUpdate"
/>
<attribute
v-if="additionalAttributes.location"
:label="$t('CONTACT_PANEL.LOCATION')"
icon="map"
emoji="🌍"
:value="additionalAttributes.location"
:show-edit="true"
@update="onLocationUpdate"
/>
<div
v-for="attribute in customAttributekeys"
:key="attribute"
class="custom-attribute--row"
>
<attribute
:label="attribute"
icon="chevron-right"
:value="customAttributes[attribute]"
:show-edit="true"
@update="value => onCustomAttributeUpdate(attribute, value)"
/>
</div>
<woot-button
size="small"
variant="link"
icon="add"
@click="handleCustomCreate"
>
{{ $t('CUSTOM_ATTRIBUTES.ADD.TITLE') }}
</woot-button>
</div>
</template>
<script>
import Attribute from './ContactAttribute.vue';
@@ -93,7 +40,7 @@ export default {
this.$emit('update', { location: value });
},
handleCustomCreate() {
this.$emit('create-attribute');
this.$emit('createAttribute');
},
onCustomAttributeUpdate(key, value) {
this.$emit('update', { custom_attributes: { [key]: value } });
@@ -102,6 +49,60 @@ export default {
};
</script>
<template>
<div class="contact-fields">
<h3 class="text-lg title">
{{ $t('CONTACTS_PAGE.FIELDS') }}
</h3>
<Attribute
:label="$t('CONTACT_PANEL.EMAIL_ADDRESS')"
icon="mail"
emoji=""
:value="contact.email"
show-edit
@update="onEmailUpdate"
/>
<Attribute
:label="$t('CONTACT_PANEL.PHONE_NUMBER')"
icon="call"
emoji=""
:value="contact.phone_number"
show-edit
@update="onPhoneUpdate"
/>
<Attribute
v-if="additionalAttributes.location"
:label="$t('CONTACT_PANEL.LOCATION')"
icon="map"
emoji="🌍"
:value="additionalAttributes.location"
show-edit
@update="onLocationUpdate"
/>
<div
v-for="attribute in customAttributekeys"
:key="attribute"
class="custom-attribute--row"
>
<Attribute
:label="attribute"
icon="chevron-right"
:value="customAttributes[attribute]"
show-edit
@update="value => onCustomAttributeUpdate(attribute, value)"
/>
</div>
<woot-button
size="small"
variant="link"
icon="add"
@click="handleCustomCreate"
>
{{ $t('CUSTOM_ATTRIBUTES.ADD.TITLE') }}
</woot-button>
</div>
</template>
<style scoped lang="scss">
.contact-fields {
margin-top: var(--space-medium);

View File

@@ -1,46 +1,3 @@
<template>
<div class="contact--intro">
<thumbnail
:src="contact.thumbnail"
size="64px"
:username="contact.name"
:status="contact.availability_status"
/>
<div class="contact--details">
<h2 class="text-lg contact--name">
{{ contact.name }}
</h2>
<h3 class="text-base contact--work">
{{ contact.title }}
<i v-if="company.name" class="icon ion-minus-round" />
<span class="company-name">{{ company.name }}</span>
</h3>
<p v-if="additionalAttributes.description" class="contact--bio">
{{ additionalAttributes.description }}
</p>
<social-icons :social-profiles="socialProfiles" />
</div>
<div class="contact-actions">
<woot-button
class="new-message"
size="small expanded"
icon="ion-paper-airplane"
@click="onNewMessageClick"
>
{{ $t('CONTACT_PANEL.NEW_MESSAGE') }}
</woot-button>
<woot-button
variant="hollow"
size="small expanded"
icon="edit"
@click="onEditClick"
>
{{ $t('EDIT_CONTACT.BUTTON_LABEL') }}
</woot-button>
</div>
</div>
</template>
<script>
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import SocialIcons from 'dashboard/routes/dashboard/conversation/contact/SocialIcons.vue';
@@ -85,6 +42,50 @@ export default {
};
</script>
<template>
<div class="contact--intro">
<Thumbnail
:src="contact.thumbnail"
size="64px"
:username="contact.name"
:status="contact.availability_status"
/>
<div class="contact--details">
<h2 class="text-lg contact--name">
{{ contact.name }}
</h2>
<h3 class="text-base contact--work">
{{ contact.title }}
<i v-if="company.name" class="icon ion-minus-round" />
<span class="company-name">{{ company.name }}</span>
</h3>
<p v-if="additionalAttributes.description" class="contact--bio">
{{ additionalAttributes.description }}
</p>
<SocialIcons :social-profiles="socialProfiles" />
</div>
<div class="contact-actions">
<woot-button
class="new-message"
size="small expanded"
icon="ion-paper-airplane"
@click="onNewMessageClick"
>
{{ $t('CONTACT_PANEL.NEW_MESSAGE') }}
</woot-button>
<woot-button
variant="hollow"
size="small expanded"
icon="edit"
@click="onEditClick"
>
{{ $t('EDIT_CONTACT.BUTTON_LABEL') }}
</woot-button>
</div>
</div>
</template>
<style scoped lang="scss">
.contact--details {
margin-top: var(--space-small);

View File

@@ -1,34 +1,3 @@
<template>
<div class="panel">
<contact-intro
:contact="contact"
@message="toggleConversationModal"
@edit="toggleEditModal"
/>
<contact-fields
:contact="contact"
@update="updateField"
@create-attribute="toggleCustomAttributeModal"
/>
<edit-contact
v-if="showEditModal"
:show="showEditModal"
:contact="contact"
@cancel="toggleEditModal"
/>
<new-conversation
v-if="enableNewConversation"
:show="showConversationModal"
:contact="contact"
@cancel="toggleConversationModal"
/>
<add-custom-attribute
:show="showCustomAttributeModal"
@cancel="toggleCustomAttributeModal"
@create="createCustomAttribute"
/>
</div>
</template>
<script>
import EditContact from 'dashboard/routes/dashboard/conversation/contact/EditContact.vue';
import NewConversation from 'dashboard/routes/dashboard/conversation/contact/NewConversation.vue';
@@ -98,6 +67,38 @@ export default {
};
</script>
<template>
<div class="panel">
<ContactIntro
:contact="contact"
@message="toggleConversationModal"
@edit="toggleEditModal"
/>
<ContactFields
:contact="contact"
@update="updateField"
@createAttribute="toggleCustomAttributeModal"
/>
<EditContact
v-if="showEditModal"
:show="showEditModal"
:contact="contact"
@cancel="toggleEditModal"
/>
<NewConversation
v-if="enableNewConversation"
:show="showConversationModal"
:contact="contact"
@cancel="toggleConversationModal"
/>
<AddCustomAttribute
:show="showCustomAttributeModal"
@cancel="toggleCustomAttributeModal"
@create="createCustomAttribute"
/>
</div>
</template>
<style scoped lang="scss">
.panel {
padding: var(--space-normal) var(--space-normal);

View File

@@ -1,118 +1,3 @@
<template>
<form @submit.prevent="onSubmit">
<div>
<div>
<div
class="mt-1 multiselect-wrap--medium"
:class="{ error: v$.parentContact.$error }"
>
<label class="multiselect__label">
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
<woot-label
:title="$t('MERGE_CONTACTS.PARENT.HELP_LABEL')"
color-scheme="success"
small
class="ml-2"
/>
</label>
<multiselect
v-model="parentContact"
:options="searchResults"
label="name"
track-by="id"
:internal-search="false"
:clear-on-select="false"
:show-labels="false"
:placeholder="$t('MERGE_CONTACTS.PARENT.PLACEHOLDER')"
:allow-empty="true"
:loading="isSearching"
:max-height="150"
open-direction="top"
@search-change="searchChange"
>
<template slot="singleLabel" slot-scope="props">
<contact-dropdown-item
:thumbnail="props.option.thumbnail"
:identifier="props.option.id"
:name="props.option.name"
:email="props.option.email"
:phone-number="props.option.phone_number"
/>
</template>
<template slot="option" slot-scope="props">
<contact-dropdown-item
:thumbnail="props.option.thumbnail"
:identifier="props.option.id"
:name="props.option.name"
:email="props.option.email"
:phone-number="props.option.phone_number"
/>
</template>
<span slot="noResult">
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
</span>
</multiselect>
<span v-if="v$.parentContact.$error" class="message">
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
</span>
</div>
</div>
<div class="flex multiselect-wrap--medium">
<div
class="w-8 relative text-base text-slate-100 dark:text-slate-600 after:content-[''] after:h-12 after:w-0 after:left-4 after:absolute after:border-l after:border-solid after:border-slate-100 after:dark:border-slate-600 before:content-[''] before:h-0 before:w-4 before:left-4 before:top-12 before:absolute before:border-b before:border-solid before:border-slate-100 before:dark:border-slate-600"
>
<fluent-icon
icon="arrow-up"
class="absolute -top-1 left-2"
size="17"
/>
</div>
<div class="flex flex-col w-full">
<label class="multiselect__label">
{{ $t('MERGE_CONTACTS.PRIMARY.TITLE') }}
<woot-label
:title="$t('MERGE_CONTACTS.PRIMARY.HELP_LABEL')"
color-scheme="alert"
small
class="ml-2"
/>
</label>
<multiselect
:value="primaryContact"
disabled
:options="[]"
:show-labels="false"
label="name"
track-by="id"
>
<template slot="singleLabel" slot-scope="props">
<contact-dropdown-item
:thumbnail="props.option.thumbnail"
:name="props.option.name"
:identifier="props.option.id"
:email="props.option.email"
:phone-number="props.option.phoneNumber"
/>
</template>
</multiselect>
</div>
</div>
</div>
<merge-contact-summary
:primary-contact-name="primaryContact.name"
:parent-contact-name="parentContactName"
/>
<div class="flex justify-end gap-2 mt-6">
<woot-button variant="clear" @click.prevent="onCancel">
{{ $t('MERGE_CONTACTS.FORM.CANCEL') }}
</woot-button>
<woot-button type="submit" :is-loading="isMerging">
{{ $t('MERGE_CONTACTS.FORM.SUBMIT') }}
</woot-button>
</div>
</form>
</template>
<script>
import { useVuelidate } from '@vuelidate/core';
import { required } from '@vuelidate/validators';
@@ -180,6 +65,121 @@ export default {
};
</script>
<template>
<form @submit.prevent="onSubmit">
<div>
<div>
<div
class="mt-1 multiselect-wrap--medium"
:class="{ error: v$.parentContact.$error }"
>
<label class="multiselect__label">
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
<woot-label
:title="$t('MERGE_CONTACTS.PARENT.HELP_LABEL')"
color-scheme="success"
small
class="ml-2"
/>
</label>
<multiselect
v-model="parentContact"
:options="searchResults"
label="name"
track-by="id"
:internal-search="false"
:clear-on-select="false"
:show-labels="false"
:placeholder="$t('MERGE_CONTACTS.PARENT.PLACEHOLDER')"
allow-empty
:loading="isSearching"
:max-height="150"
open-direction="top"
@search-change="searchChange"
>
<template slot="singleLabel" slot-scope="props">
<ContactDropdownItem
:thumbnail="props.option.thumbnail"
:identifier="props.option.id"
:name="props.option.name"
:email="props.option.email"
:phone-number="props.option.phone_number"
/>
</template>
<template slot="option" slot-scope="props">
<ContactDropdownItem
:thumbnail="props.option.thumbnail"
:identifier="props.option.id"
:name="props.option.name"
:email="props.option.email"
:phone-number="props.option.phone_number"
/>
</template>
<span slot="noResult">
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
</span>
</multiselect>
<span v-if="v$.parentContact.$error" class="message">
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
</span>
</div>
</div>
<div class="flex multiselect-wrap--medium">
<div
class="w-8 relative text-base text-slate-100 dark:text-slate-600 after:content-[''] after:h-12 after:w-0 after:left-4 after:absolute after:border-l after:border-solid after:border-slate-100 after:dark:border-slate-600 before:content-[''] before:h-0 before:w-4 before:left-4 before:top-12 before:absolute before:border-b before:border-solid before:border-slate-100 before:dark:border-slate-600"
>
<fluent-icon
icon="arrow-up"
class="absolute -top-1 left-2"
size="17"
/>
</div>
<div class="flex flex-col w-full">
<label class="multiselect__label">
{{ $t('MERGE_CONTACTS.PRIMARY.TITLE') }}
<woot-label
:title="$t('MERGE_CONTACTS.PRIMARY.HELP_LABEL')"
color-scheme="alert"
small
class="ml-2"
/>
</label>
<multiselect
:value="primaryContact"
disabled
:options="[]"
:show-labels="false"
label="name"
track-by="id"
>
<template slot="singleLabel" slot-scope="props">
<ContactDropdownItem
:thumbnail="props.option.thumbnail"
:name="props.option.name"
:identifier="props.option.id"
:email="props.option.email"
:phone-number="props.option.phoneNumber"
/>
</template>
</multiselect>
</div>
</div>
</div>
<MergeContactSummary
:primary-contact-name="primaryContact.name"
:parent-contact-name="parentContactName"
/>
<div class="flex justify-end gap-2 mt-6">
<woot-button variant="clear" @click.prevent="onCancel">
{{ $t('MERGE_CONTACTS.FORM.CANCEL') }}
</woot-button>
<woot-button type="submit" :is-loading="isMerging">
{{ $t('MERGE_CONTACTS.FORM.SUBMIT') }}
</woot-button>
</div>
</form>
</template>
<style lang="scss" scoped>
/* TDOD: Clean errors in forms style */
.error .message {

View File

@@ -1,3 +1,18 @@
<script>
export default {
props: {
primaryContactName: {
type: String,
default: '',
},
parentContactName: {
type: String,
default: '',
},
},
};
</script>
<template>
<div
v-if="parentContactName"
@@ -31,18 +46,3 @@
</ul>
</div>
</template>
<script>
export default {
props: {
primaryContactName: {
type: String,
default: '',
},
parentContactName: {
type: String,
default: '',
},
},
};
</script>