Files
chatwoot/app/javascript/dashboard/components/buttons/ResolveAction.vue
Shivam Mishra 7fd8b4d03a feat: update colors for v4 (#10660)
Porting changes from https://github.com/chatwoot/chatwoot/pull/10552

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Vishnu Narayanan <vishnu@chatwoot.com>
Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
2025-01-15 17:13:03 +05:30

220 lines
6.2 KiB
Vue

<script setup>
import { ref, computed } from 'vue';
import { useAlert } from 'dashboard/composables';
import { useToggle } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
import { useStore, useStoreGetters } from 'dashboard/composables/store';
import { useEmitter } from 'dashboard/composables/emitter';
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
import wootConstants from 'dashboard/constants/globals';
import {
CMD_REOPEN_CONVERSATION,
CMD_RESOLVE_CONVERSATION,
} from 'dashboard/helper/commandbar/events';
import Button from 'dashboard/components-next/button/Button.vue';
const store = useStore();
const getters = useStoreGetters();
const { t } = useI18n();
const arrowDownButtonRef = ref(null);
const isLoading = ref(false);
const [showActionsDropdown, toggleDropdown] = useToggle();
const closeDropdown = () => toggleDropdown(false);
const openDropdown = () => toggleDropdown(true);
const currentChat = computed(() => getters.getSelectedChat.value);
const isOpen = computed(
() => currentChat.value.status === wootConstants.STATUS_TYPE.OPEN
);
const isPending = computed(
() => currentChat.value.status === wootConstants.STATUS_TYPE.PENDING
);
const isResolved = computed(
() => currentChat.value.status === wootConstants.STATUS_TYPE.RESOLVED
);
const isSnoozed = computed(
() => currentChat.value.status === wootConstants.STATUS_TYPE.SNOOZED
);
const showAdditionalActions = computed(
() => !isPending.value && !isSnoozed.value
);
const showOpenButton = computed(() => {
return isPending.value || isSnoozed.value;
});
const getConversationParams = () => {
const allConversations = document.querySelectorAll(
'.conversations-list .conversation'
);
const activeConversation = document.querySelector(
'div.conversations-list div.conversation.active'
);
const activeConversationIndex = [...allConversations].indexOf(
activeConversation
);
const lastConversationIndex = allConversations.length - 1;
return {
all: allConversations,
activeIndex: activeConversationIndex,
lastIndex: lastConversationIndex,
};
};
const openSnoozeModal = () => {
const ninja = document.querySelector('ninja-keys');
ninja.open({ parent: 'snooze_conversation' });
};
const toggleStatus = (status, snoozedUntil) => {
closeDropdown();
isLoading.value = true;
store
.dispatch('toggleStatus', {
conversationId: currentChat.value.id,
status,
snoozedUntil,
})
.then(() => {
useAlert(t('CONVERSATION.CHANGE_STATUS'));
isLoading.value = false;
});
};
const onCmdOpenConversation = () => {
toggleStatus(wootConstants.STATUS_TYPE.OPEN);
};
const onCmdResolveConversation = () => {
toggleStatus(wootConstants.STATUS_TYPE.RESOLVED);
};
const keyboardEvents = {
'Alt+KeyM': {
action: () => arrowDownButtonRef.value?.$el.click(),
allowOnFocusedInput: true,
},
'Alt+KeyE': {
action: async () => {
await toggleStatus(wootConstants.STATUS_TYPE.RESOLVED);
},
},
'$mod+Alt+KeyE': {
action: async event => {
const { all, activeIndex, lastIndex } = getConversationParams();
await toggleStatus(wootConstants.STATUS_TYPE.RESOLVED);
if (activeIndex < lastIndex) {
all[activeIndex + 1].click();
} else if (all.length > 1) {
all[0].click();
document.querySelector('.conversations-list').scrollTop = 0;
}
event.preventDefault();
},
},
};
useKeyboardEvents(keyboardEvents);
useEmitter(CMD_REOPEN_CONVERSATION, onCmdOpenConversation);
useEmitter(CMD_RESOLVE_CONVERSATION, onCmdResolveConversation);
</script>
<template>
<div class="relative flex items-center justify-end resolve-actions">
<div
class="rounded-lg shadow button-group outline-1 outline"
:class="!showOpenButton ? 'outline-n-container' : 'outline-transparent'"
>
<Button
v-if="isOpen"
:label="t('CONVERSATION.HEADER.RESOLVE_ACTION')"
size="sm"
color="slate"
class="ltr:rounded-r-none rtl:rounded-l-none !outline-0"
:is-loading="isLoading"
@click="onCmdResolveConversation"
/>
<Button
v-else-if="isResolved"
:label="t('CONVERSATION.HEADER.REOPEN_ACTION')"
size="sm"
color="slate"
class="ltr:rounded-r-none rtl:rounded-l-none !outline-0"
:is-loading="isLoading"
@click="onCmdOpenConversation"
/>
<Button
v-else-if="showOpenButton"
:label="t('CONVERSATION.HEADER.OPEN_ACTION')"
size="sm"
color="slate"
:is-loading="isLoading"
@click="onCmdOpenConversation"
/>
<Button
v-if="showAdditionalActions"
ref="arrowDownButtonRef"
icon="i-lucide-chevron-down"
:disabled="isLoading"
size="sm"
class="ltr:rounded-l-none rtl:rounded-r-none !outline-0"
color="slate"
trailing-icon
@click="openDropdown"
/>
</div>
<div
v-if="showActionsDropdown"
v-on-clickaway="closeDropdown"
class="dropdown-pane dropdown-pane--open left-auto top-full mt-0.5 ltr:right-0 rtl:left-0 max-w-[12.5rem] min-w-[9.75rem]"
>
<WootDropdownMenu class="mb-0">
<WootDropdownItem v-if="!isPending">
<Button
:label="t('CONVERSATION.RESOLVE_DROPDOWN.SNOOZE_UNTIL')"
ghost
slate
sm
start
icon="i-lucide-alarm-clock-minus"
class="w-full"
@click="() => openSnoozeModal()"
/>
</WootDropdownItem>
<WootDropdownItem v-if="!isPending">
<Button
:label="t('CONVERSATION.RESOLVE_DROPDOWN.MARK_PENDING')"
ghost
slate
sm
start
icon="i-lucide-circle-dot-dashed"
class="w-full"
@click="() => toggleStatus(wootConstants.STATUS_TYPE.PENDING)"
/>
</WootDropdownItem>
</WootDropdownMenu>
</div>
</div>
</template>
<style lang="scss" scoped>
.dropdown-pane {
.dropdown-menu__item {
@apply mb-0;
}
}
</style>