feat: Create component to merge contacts (#2412)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
committed by
GitHub
parent
e11b3c4f17
commit
104ae8de2e
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="option-item--user">
|
||||
<thumbnail :src="thumbnail" size="24px" :username="name" />
|
||||
<span class="option__title">
|
||||
{{ name }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Thumbnail from '../../../components/widgets/Thumbnail';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Thumbnail,
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
thumbnail: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.option-item--user {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<form @submit.prevent="onSubmit">
|
||||
<div class="merge-contacts">
|
||||
<div class="multiselect-wrap--small">
|
||||
<label class="multiselect__label">
|
||||
{{ $t('MERGE_CONTACTS.PRIMARY.TITLE') }}
|
||||
</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"
|
||||
/>
|
||||
</template>
|
||||
</multiselect>
|
||||
</div>
|
||||
|
||||
<div class="child-contact-wrap">
|
||||
<div class="child-arrow">
|
||||
<i class="ion-ios-arrow-up up" />
|
||||
</div>
|
||||
<div
|
||||
class="child-contact multiselect-wrap--small"
|
||||
:class="{ error: $v.childContact.$error }"
|
||||
>
|
||||
<label class="multiselect__label">
|
||||
{{ $t('MERGE_CONTACTS.CHILD.TITLE') }}
|
||||
</label>
|
||||
<multiselect
|
||||
v-model="childContact"
|
||||
:options="searchResults"
|
||||
label="name"
|
||||
track-by="id"
|
||||
:internal-search="false"
|
||||
:clear-on-select="false"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('MERGE_CONTACTS.CHILD.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"
|
||||
:name="props.option.name"
|
||||
/>
|
||||
</template>
|
||||
<span slot="noResult">
|
||||
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
|
||||
</span>
|
||||
</multiselect>
|
||||
<span v-if="$v.childContact.$error" class="message">
|
||||
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<merge-contact-summary
|
||||
:primary-contact-name="primaryContact.name"
|
||||
:child-contact-name="childContactName"
|
||||
/>
|
||||
<div class="footer">
|
||||
<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 alertMixin from 'shared/mixins/alertMixin';
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
|
||||
import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary';
|
||||
import ContactDropdownItem from './ContactDropdownItem';
|
||||
|
||||
export default {
|
||||
components: { MergeContactSummary, ContactDropdownItem },
|
||||
mixins: [alertMixin],
|
||||
props: {
|
||||
primaryContact: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
isSearching: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isMerging: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
searchResults: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
validations: {
|
||||
primaryContact: {
|
||||
required,
|
||||
},
|
||||
childContact: {
|
||||
required,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
childContact: undefined,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
childContactName() {
|
||||
return this.childContact ? this.childContact.name : '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
searchChange(query) {
|
||||
this.$emit('search', query);
|
||||
},
|
||||
onSubmit() {
|
||||
this.$v.$touch();
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
this.$emit('submit', this.childContact.id);
|
||||
},
|
||||
onCancel() {
|
||||
this.$emit('cancel');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.child-contact-wrap {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
.child-contact {
|
||||
flex: 1 0 0;
|
||||
min-width: 0;
|
||||
}
|
||||
.child-arrow {
|
||||
width: var(--space-larger);
|
||||
position: relative;
|
||||
font-size: var(--font-size-default);
|
||||
color: var(--color-border-dark);
|
||||
}
|
||||
.multiselect {
|
||||
margin-bottom: var(--space-small);
|
||||
}
|
||||
.child-contact {
|
||||
margin-top: var(--space-smaller);
|
||||
}
|
||||
.child-arrow::after {
|
||||
content: '';
|
||||
height: var(--space-larger);
|
||||
width: 0;
|
||||
left: var(--space-two);
|
||||
position: absolute;
|
||||
border-left: 1px solid var(--color-border-dark);
|
||||
}
|
||||
|
||||
.child-arrow::before {
|
||||
content: '';
|
||||
height: 0;
|
||||
width: var(--space-normal);
|
||||
left: var(--space-two);
|
||||
top: var(--space-larger);
|
||||
position: absolute;
|
||||
border-bottom: 1px solid var(--color-border-dark);
|
||||
}
|
||||
|
||||
.up {
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
left: var(--space-normal);
|
||||
}
|
||||
|
||||
::v-deep .multiselect__tags .option__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-left: var(--space-small);
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: var(--space-medium);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* TDOD: Clean errors in forms style */
|
||||
.error .message {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div v-if="childContactName" class="merge-summary callout">
|
||||
<h5 class="text-block-title">
|
||||
{{ $t('MERGE_CONTACTS.SUMMARY.TITLE') }}
|
||||
</h5>
|
||||
<ul class="summary-items">
|
||||
<li>
|
||||
<span>❌</span>
|
||||
<span
|
||||
v-html="
|
||||
$t('MERGE_CONTACTS.SUMMARY.DELETE_WARNING', {
|
||||
childContactName,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<span>✅</span>
|
||||
<span
|
||||
v-html="
|
||||
$t('MERGE_CONTACTS.SUMMARY.ATTRIBUTE_WARNING', {
|
||||
childContactName,
|
||||
primaryContactName,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
primaryContactName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
childContactName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
computed: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.merge-summary {
|
||||
margin-top: var(--space-normal);
|
||||
}
|
||||
|
||||
.summary-items {
|
||||
margin-left: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
margin-bottom: var(--space-smaller);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user