feat: Reverse the contact merge (#8057)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
@@ -9,7 +9,6 @@ class Api::V1::Accounts::Actions::ContactMergesController < Api::V1::Accounts::B
|
||||
mergee_contact: @mergee_contact
|
||||
)
|
||||
contact_merge_action.perform
|
||||
render json: @base_contact
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -343,17 +343,17 @@
|
||||
"DESCRIPTION": "Merge contacts to combine two profiles into one, including all attributes and conversations. In case of conflict, the Primary contact’s attributes will take precedence.",
|
||||
"PRIMARY": {
|
||||
"TITLE": "Primary contact",
|
||||
"HELP_LABEL": "To be kept"
|
||||
"HELP_LABEL": "To be deleted"
|
||||
},
|
||||
"CHILD": {
|
||||
"PARENT": {
|
||||
"TITLE": "Contact to merge",
|
||||
"PLACEHOLDER": "Search for a contact",
|
||||
"HELP_LABEL": "To be deleted"
|
||||
"HELP_LABEL": "To be kept"
|
||||
},
|
||||
"SUMMARY": {
|
||||
"TITLE": "Summary",
|
||||
"DELETE_WARNING": "Contact of <strong>%{childContactName}</strong> will be deleted.",
|
||||
"ATTRIBUTE_WARNING": "Contact details of <strong>%{childContactName}</strong> will be copied to <strong>%{primaryContactName}</strong>."
|
||||
"DELETE_WARNING": "Contact of <strong>%{primaryContactName}</strong> will be deleted.",
|
||||
"ATTRIBUTE_WARNING": "Contact details of <strong>%{primaryContactName}</strong> will be copied to <strong>%{parentContactName}</strong>."
|
||||
},
|
||||
"SEARCH": {
|
||||
"ERROR": "ERROR_MESSAGE"
|
||||
|
||||
@@ -73,12 +73,12 @@ export default {
|
||||
this.isSearching = false;
|
||||
}
|
||||
},
|
||||
async onMergeContacts(childContactId) {
|
||||
async onMergeContacts(parentContactId) {
|
||||
this.$track(CONTACTS_EVENTS.MERGED_CONTACTS);
|
||||
try {
|
||||
await this.$store.dispatch('contacts/merge', {
|
||||
childId: childContactId,
|
||||
parentId: this.primaryContact.id,
|
||||
childId: this.primaryContact.id,
|
||||
parentId: parentContactId,
|
||||
});
|
||||
this.showAlert(this.$t('MERGE_CONTACTS.FORM.SUCCESS_MESSAGE'));
|
||||
this.onClose();
|
||||
|
||||
@@ -1,62 +1,29 @@
|
||||
<template>
|
||||
<form @submit.prevent="onSubmit">
|
||||
<div class="merge-contacts">
|
||||
<div class="multiselect-wrap--medium">
|
||||
<label class="multiselect__label">
|
||||
{{ $t('MERGE_CONTACTS.PRIMARY.TITLE') }}
|
||||
<woot-label
|
||||
:title="$t('MERGE_CONTACTS.PRIMARY.HELP_LABEL')"
|
||||
color-scheme="success"
|
||||
small
|
||||
class="label--merge-warning"
|
||||
/>
|
||||
</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 class="child-contact-wrap">
|
||||
<div class="child-arrow">
|
||||
<fluent-icon icon="arrow-up" class="up" size="17" />
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="child-contact multiselect-wrap--medium"
|
||||
:class="{ error: $v.childContact.$error }"
|
||||
class="mt-1 multiselect-wrap--medium"
|
||||
:class="{ error: $v.parentContact.$error }"
|
||||
>
|
||||
<label class="multiselect__label">
|
||||
{{ $t('MERGE_CONTACTS.CHILD.TITLE')
|
||||
}}<woot-label
|
||||
:title="$t('MERGE_CONTACTS.CHILD.HELP_LABEL')"
|
||||
color-scheme="alert"
|
||||
{{ $t('MERGE_CONTACTS.PARENT.TITLE') }}
|
||||
<woot-label
|
||||
:title="$t('MERGE_CONTACTS.PARENT.HELP_LABEL')"
|
||||
color-scheme="success"
|
||||
small
|
||||
class="label--merge-warning"
|
||||
class="ml-2"
|
||||
/>
|
||||
</label>
|
||||
<multiselect
|
||||
v-model="childContact"
|
||||
v-model="parentContact"
|
||||
:options="searchResults"
|
||||
label="name"
|
||||
track-by="id"
|
||||
:internal-search="false"
|
||||
:clear-on-select="false"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('MERGE_CONTACTS.CHILD.PLACEHOLDER')"
|
||||
:placeholder="$t('MERGE_CONTACTS.PARENT.PLACEHOLDER')"
|
||||
:allow-empty="true"
|
||||
:loading="isSearching"
|
||||
:max-height="150"
|
||||
@@ -85,17 +52,57 @@
|
||||
{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}
|
||||
</span>
|
||||
</multiselect>
|
||||
<span v-if="$v.childContact.$error" class="message">
|
||||
<span v-if="$v.parentContact.$error" class="message">
|
||||
{{ $t('MERGE_CONTACTS.FORM.CHILD_CONTACT.ERROR') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="multiselect-wrap--medium flex">
|
||||
<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"
|
||||
:child-contact-name="childContactName"
|
||||
:parent-contact-name="parentContactName"
|
||||
/>
|
||||
<div class="footer">
|
||||
<div class="mt-6 flex justify-end">
|
||||
<woot-button variant="clear" @click.prevent="onCancel">
|
||||
{{ $t('MERGE_CONTACTS.FORM.CANCEL') }}
|
||||
</woot-button>
|
||||
@@ -138,19 +145,19 @@ export default {
|
||||
primaryContact: {
|
||||
required,
|
||||
},
|
||||
childContact: {
|
||||
parentContact: {
|
||||
required,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
childContact: undefined,
|
||||
parentContact: undefined,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
childContactName() {
|
||||
return this.childContact ? this.childContact.name : '';
|
||||
parentContactName() {
|
||||
return this.parentContact ? this.parentContact.name : '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@@ -162,7 +169,7 @@ export default {
|
||||
if (this.$v.$invalid) {
|
||||
return;
|
||||
}
|
||||
this.$emit('submit', this.childContact.id);
|
||||
this.$emit('submit', this.parentContact.id);
|
||||
},
|
||||
onCancel() {
|
||||
this.$emit('cancel');
|
||||
@@ -172,51 +179,24 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.child-contact-wrap {
|
||||
@apply flex w-full;
|
||||
}
|
||||
.child-contact {
|
||||
@apply min-w-0 flex-grow flex-shrink-0;
|
||||
}
|
||||
.child-arrow {
|
||||
@apply w-8 relative text-base text-slate-100 dark:text-slate-600;
|
||||
}
|
||||
.multiselect {
|
||||
@apply mb-2;
|
||||
}
|
||||
.child-contact {
|
||||
@apply mt-1;
|
||||
}
|
||||
.child-arrow::after {
|
||||
@apply content-[''] h-12 w-0 left-5 absolute border-l border-solid border-slate-100 dark:border-slate-600;
|
||||
}
|
||||
|
||||
.child-arrow::before {
|
||||
@apply content-[''] h-0 w-4 left-5 top-12 absolute border-b border-solid border-slate-100 dark:border-slate-600;
|
||||
}
|
||||
|
||||
.up {
|
||||
@apply absolute -top-1 left-3;
|
||||
}
|
||||
|
||||
.footer {
|
||||
@apply mt-6 flex justify-end;
|
||||
}
|
||||
|
||||
/* TDOD: Clean errors in forms style */
|
||||
.error .message {
|
||||
@apply mt-0;
|
||||
}
|
||||
|
||||
.label--merge-warning {
|
||||
@apply ml-2;
|
||||
}
|
||||
|
||||
::v-deep {
|
||||
.multiselect {
|
||||
@apply rounded-md;
|
||||
}
|
||||
|
||||
.multiselect--disabled {
|
||||
@apply border-0;
|
||||
|
||||
.multiselect__tags {
|
||||
@apply border;
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect__tags {
|
||||
@apply h-[52px];
|
||||
}
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
<template>
|
||||
<div v-if="childContactName" class="merge-summary callout">
|
||||
<h5 class="text-block-title">
|
||||
<div
|
||||
v-if="parentContactName"
|
||||
class="my-4 relative p-2.5 border rounded-[4px] text-slate-800 dark:text-slate-100 border-slate-100 dark:border-slate-700 bg-white dark:bg-slate-800"
|
||||
>
|
||||
<h5 class="text-base font-medium text-slate-900 dark:text-white">
|
||||
{{ $t('MERGE_CONTACTS.SUMMARY.TITLE') }}
|
||||
</h5>
|
||||
<ul class="summary-items">
|
||||
<ul class="ml-0 list-none">
|
||||
<li>
|
||||
<span class="bullet">❌</span>
|
||||
<span class="inline-block mr-1">❌</span>
|
||||
<span
|
||||
v-dompurify-html="
|
||||
$t('MERGE_CONTACTS.SUMMARY.DELETE_WARNING', {
|
||||
childContactName,
|
||||
primaryContactName,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<span class="bullet">✅</span>
|
||||
<span class="inline-block mr-1">✅</span>
|
||||
<span
|
||||
v-dompurify-html="
|
||||
$t('MERGE_CONTACTS.SUMMARY.ATTRIBUTE_WARNING', {
|
||||
childContactName,
|
||||
primaryContactName,
|
||||
parentContactName,
|
||||
})
|
||||
"
|
||||
/>
|
||||
@@ -36,32 +39,10 @@ export default {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
childContactName: {
|
||||
parentContactName: {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
.bullet {
|
||||
display: inline-block;
|
||||
margin-right: var(--space-smaller);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
json.partial! 'api/v1/models/contact', formats: [:json], resource: @base_contact
|
||||
Reference in New Issue
Block a user