fix: Persist compose form state on accidental outside click (#13529)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, watch } from 'vue';
|
import { reactive, ref, computed, onMounted, watch } from 'vue';
|
||||||
import { useStore, useMapGetter } from 'dashboard/composables/store';
|
import { useStore, useMapGetter } from 'dashboard/composables/store';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useWindowSize } from '@vueuse/core';
|
import { useWindowSize } from '@vueuse/core';
|
||||||
@@ -59,6 +59,23 @@ const isFetchingInboxes = ref(false);
|
|||||||
const isSearching = ref(false);
|
const isSearching = ref(false);
|
||||||
const showComposeNewConversation = ref(false);
|
const showComposeNewConversation = ref(false);
|
||||||
|
|
||||||
|
const formState = reactive({
|
||||||
|
message: '',
|
||||||
|
subject: '',
|
||||||
|
ccEmails: '',
|
||||||
|
bccEmails: '',
|
||||||
|
attachedFiles: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const clearFormState = () => {
|
||||||
|
Object.assign(formState, {
|
||||||
|
subject: '',
|
||||||
|
ccEmails: '',
|
||||||
|
bccEmails: '',
|
||||||
|
attachedFiles: [],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const contactById = useMapGetter('contacts/getContactById');
|
const contactById = useMapGetter('contacts/getContactById');
|
||||||
const contactsUiFlags = useMapGetter('contacts/getUIFlags');
|
const contactsUiFlags = useMapGetter('contacts/getUIFlags');
|
||||||
const currentUser = useMapGetter('getCurrentUser');
|
const currentUser = useMapGetter('getCurrentUser');
|
||||||
@@ -140,12 +157,14 @@ const handleSelectedContact = async ({ value, action, ...rest }) => {
|
|||||||
|
|
||||||
const handleTargetInbox = inbox => {
|
const handleTargetInbox = inbox => {
|
||||||
targetInbox.value = inbox;
|
targetInbox.value = inbox;
|
||||||
|
if (!inbox) clearFormState();
|
||||||
resetContacts();
|
resetContacts();
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearSelectedContact = () => {
|
const clearSelectedContact = () => {
|
||||||
selectedContact.value = null;
|
selectedContact.value = null;
|
||||||
targetInbox.value = null;
|
targetInbox.value = null;
|
||||||
|
clearFormState();
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeCompose = () => {
|
const closeCompose = () => {
|
||||||
@@ -160,6 +179,12 @@ const closeCompose = () => {
|
|||||||
emit('close');
|
emit('close');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const discardCompose = () => {
|
||||||
|
clearFormState();
|
||||||
|
formState.message = '';
|
||||||
|
closeCompose();
|
||||||
|
};
|
||||||
|
|
||||||
const createConversation = async ({ payload, isFromWhatsApp }) => {
|
const createConversation = async ({ payload, isFromWhatsApp }) => {
|
||||||
try {
|
try {
|
||||||
const data = await store.dispatch('contactConversations/create', {
|
const data = await store.dispatch('contactConversations/create', {
|
||||||
@@ -171,7 +196,7 @@ const createConversation = async ({ payload, isFromWhatsApp }) => {
|
|||||||
to: `/app/accounts/${data.account_id}/conversations/${data.id}`,
|
to: `/app/accounts/${data.account_id}/conversations/${data.id}`,
|
||||||
message: t('COMPOSE_NEW_CONVERSATION.FORM.GO_TO_CONVERSATION'),
|
message: t('COMPOSE_NEW_CONVERSATION.FORM.GO_TO_CONVERSATION'),
|
||||||
};
|
};
|
||||||
closeCompose();
|
discardCompose();
|
||||||
useAlert(t('COMPOSE_NEW_CONVERSATION.FORM.SUCCESS_MESSAGE'), action);
|
useAlert(t('COMPOSE_NEW_CONVERSATION.FORM.SUCCESS_MESSAGE'), action);
|
||||||
return true; // Return success
|
return true; // Return success
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -193,7 +218,11 @@ watch(
|
|||||||
(currentContact, previousContact) => {
|
(currentContact, previousContact) => {
|
||||||
if (currentContact && props.contactId) {
|
if (currentContact && props.contactId) {
|
||||||
// Reset on contact change
|
// Reset on contact change
|
||||||
if (currentContact?.id !== previousContact?.id) clearSelectedContact();
|
if (currentContact?.id !== previousContact?.id) {
|
||||||
|
clearSelectedContact();
|
||||||
|
clearFormState();
|
||||||
|
formState.message = '';
|
||||||
|
}
|
||||||
|
|
||||||
// First process the contactable inboxes to get the right structure
|
// First process the contactable inboxes to get the right structure
|
||||||
const processedInboxes = processContactableInboxes(
|
const processedInboxes = processContactableInboxes(
|
||||||
@@ -265,6 +294,7 @@ useKeyboardEvents(keyboardEvents);
|
|||||||
@click.self="onModalBackdropClick"
|
@click.self="onModalBackdropClick"
|
||||||
>
|
>
|
||||||
<ComposeNewConversationForm
|
<ComposeNewConversationForm
|
||||||
|
:form-state="formState"
|
||||||
:class="[{ 'mt-2': !viewInModal }, composePopoverClass]"
|
:class="[{ 'mt-2': !viewInModal }, composePopoverClass]"
|
||||||
:contacts="contacts"
|
:contacts="contacts"
|
||||||
:contact-id="contactId"
|
:contact-id="contactId"
|
||||||
@@ -285,7 +315,7 @@ useKeyboardEvents(keyboardEvents);
|
|||||||
@update-target-inbox="handleTargetInbox"
|
@update-target-inbox="handleTargetInbox"
|
||||||
@clear-selected-contact="clearSelectedContact"
|
@clear-selected-contact="clearSelectedContact"
|
||||||
@create-conversation="createConversation"
|
@create-conversation="createConversation"
|
||||||
@discard="closeCompose"
|
@discard="discardCompose"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useVuelidate } from '@vuelidate/core';
|
import { useVuelidate } from '@vuelidate/core';
|
||||||
import { required, requiredIf } from '@vuelidate/validators';
|
import { required, requiredIf } from '@vuelidate/validators';
|
||||||
import { INBOX_TYPES } from 'dashboard/helper/inbox';
|
import { INBOX_TYPES } from 'dashboard/helper/inbox';
|
||||||
@@ -37,6 +37,7 @@ const props = defineProps({
|
|||||||
contactsUiFlags: { type: Object, default: null },
|
contactsUiFlags: { type: Object, default: null },
|
||||||
messageSignature: { type: String, default: '' },
|
messageSignature: { type: String, default: '' },
|
||||||
sendWithSignature: { type: Boolean, default: false },
|
sendWithSignature: { type: Boolean, default: false },
|
||||||
|
formState: { type: Object, required: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
@@ -57,13 +58,13 @@ const showBccEmailsDropdown = ref(false);
|
|||||||
|
|
||||||
const isCreating = computed(() => props.contactConversationsUiFlags.isCreating);
|
const isCreating = computed(() => props.contactConversationsUiFlags.isCreating);
|
||||||
|
|
||||||
const state = reactive({
|
const state = props.formState || {
|
||||||
message: '',
|
message: '',
|
||||||
subject: '',
|
subject: '',
|
||||||
ccEmails: '',
|
ccEmails: '',
|
||||||
bccEmails: '',
|
bccEmails: '',
|
||||||
attachedFiles: [],
|
attachedFiles: [],
|
||||||
});
|
};
|
||||||
|
|
||||||
const inboxTypes = computed(() => ({
|
const inboxTypes = computed(() => ({
|
||||||
isEmail: props.targetInbox?.channelType === INBOX_TYPES.EMAIL,
|
isEmail: props.targetInbox?.channelType === INBOX_TYPES.EMAIL,
|
||||||
|
|||||||
Reference in New Issue
Block a user