Files
chatwoot/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/AgentSelector.vue
Sivin Varghese dafedddc1a feat: Remove Foundation in favor of Tailwind (#8984)
* feat: Remove foundation

* chore: Minor fix

* Minor fix

* Update _forms.scss

* chore: More changes

* chore: Minor fix

* chore: Clean up

* fix: font-weight

* chore: More changes

* chore: Setting page

* chore: Editor fix

* chore: Reports page

* chore: More changes

* chore: Minor changes

* chore: More fixes

* chore: More changes

* chore: More changes

* chore: More changes

* chore: Minor fix

* chore: More changes

* chore: More changes

* chore: More changes

* chore: More changes

* chore: Clean up

* chore: Minor fix

* chore: Clean ups

* chore: Rename basic file

* chore: Remove unused files

* chore: Fix expanded input

* Fix campaign rendering

* chore: Clean up

* chore: More changes

* chore: Remove unused files

* fix: Overflow issue

* chore: Minor fix

* chore: Clean up

* chore: Minor fix

* chore: Remove unused files

* chore: Minor fix

* chore: Minor fix

* fix: autoprefixer start/end value has mixed support

* chore: Minor fix

* chore: Remove unused files

* chore: Minor fix

* chore: Minor fix

* chore: Minor fix

* Add responsive design to label settings

* fix inbox view

* chore: Minor fix

* w-60% to w-2/3

* chore: Fix team

* chore: Fix button

* w-[34%] to w-1/3

* chore: Fix border

* Add support mobile views in team page

* chore: fix snackbar

* chore: clean up

* chore: Clean up

* fix: loading state alignment

* fix: alert styles

* chore: Minor fix

* fix: spacing for agent bot row

* fix: layout

* fix: layout for SLA

* fix: checkbox

* fix: SLA checkbox spacing

* Update inbox settings pages

* fix macros listing page layout

* fix canned responses

* chore: Fix bot page

* chore: fix automation page

* chore: fix agents page

* chore: fix canned response editor

* chore: Fix settings table

* chore: fix settings layout

* chore: Minor fix

* fix: canned response table layou

* fix: layout for table header for webhooks

* fix: webhook row layout

* fix: dashboard app modal layout

* fix: add title to canned response truncated shortcode

* fix: dashboard apps row layuot

* fix: layouts hooks

* fix: body color

* fix: delete action color in portal locales

* fix: text color for campagin title

* fix: success button color

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2024-02-28 13:56:28 +05:30

261 lines
6.7 KiB
Vue

<template>
<div v-on-clickaway="onCloseAgentList" class="bulk-action__agents">
<div class="triangle">
<svg height="12" viewBox="0 0 24 12" width="24">
<path d="M20 12l-8-8-12 12" fill-rule="evenodd" stroke-width="1px" />
</svg>
</div>
<div class="header flex items-center justify-between">
<span>{{ $t('BULK_ACTION.AGENT_SELECT_LABEL') }}</span>
<woot-button
size="tiny"
variant="clear"
color-scheme="secondary"
icon="dismiss"
@click="onClose"
/>
</div>
<div class="container">
<div
v-if="assignableAgentsUiFlags.isFetching"
class="agent__list-loading"
>
<spinner />
<p>{{ $t('BULK_ACTION.AGENT_LIST_LOADING') }}</p>
</div>
<div v-else class="agent__list-container">
<ul v-if="!selectedAgent">
<li class="search-container">
<div
class="agent-list-search h-8 flex justify-between items-center gap-2"
>
<fluent-icon icon="search" class="search-icon" size="16" />
<input
ref="search"
v-model="query"
type="search"
placeholder="Search"
class="agent--search_input"
/>
</div>
</li>
<li v-for="agent in filteredAgents" :key="agent.id">
<div class="agent-list-item" @click="assignAgent(agent)">
<thumbnail
:src="agent.thumbnail"
:status="agent.availability_status"
:username="agent.name"
size="22px"
/>
<span class="my-0 text-slate-800 dark:text-slate-75">
{{ agent.name }}
</span>
</div>
</li>
</ul>
<div v-else class="agent-confirmation-container">
<p v-if="selectedAgent.id">
{{
$t('BULK_ACTION.ASSIGN_CONFIRMATION_LABEL', {
conversationCount,
conversationLabel,
})
}}
<strong>
{{ selectedAgent.name }}
</strong>
<span>?</span>
</p>
<p v-else>
{{
$t('BULK_ACTION.UNASSIGN_CONFIRMATION_LABEL', {
conversationCount,
conversationLabel,
})
}}
</p>
<div class="agent-confirmation-actions">
<woot-button
color-scheme="primary"
variant="smooth"
@click="goBack"
>
{{ $t('BULK_ACTION.GO_BACK_LABEL') }}
</woot-button>
<woot-button
color-scheme="primary"
variant="flat"
:is-loading="uiFlags.isUpdating"
@click="submit"
>
{{ $t('BULK_ACTION.YES') }}
</woot-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import Spinner from 'shared/components/Spinner.vue';
import { mixin as clickaway } from 'vue-clickaway';
export default {
components: {
Thumbnail,
Spinner,
},
mixins: [clickaway],
props: {
selectedInboxes: {
type: Array,
default: () => [],
},
conversationCount: {
type: Number,
default: 0,
},
},
data() {
return {
query: '',
selectedAgent: null,
goBackToAgentList: false,
};
},
computed: {
...mapGetters({
uiFlags: 'bulkActions/getUIFlags',
inboxes: 'inboxes/getInboxes',
assignableAgentsUiFlags: 'inboxAssignableAgents/getUIFlags',
}),
filteredAgents() {
if (this.query) {
return this.assignableAgents.filter(agent =>
agent.name.toLowerCase().includes(this.query.toLowerCase())
);
}
return [
{
confirmed: true,
name: 'None',
id: null,
role: 'agent',
account_id: 0,
email: 'None',
},
...this.assignableAgents,
];
},
assignableAgents() {
return this.$store.getters['inboxAssignableAgents/getAssignableAgents'](
this.selectedInboxes.join(',')
);
},
conversationLabel() {
return this.conversationCount > 1 ? 'conversations' : 'conversation';
},
},
mounted() {
this.$store.dispatch('inboxAssignableAgents/fetch', this.selectedInboxes);
},
methods: {
submit() {
this.$emit('select', this.selectedAgent);
},
goBack() {
this.goBackToAgentList = true;
this.selectedAgent = null;
},
assignAgent(agent) {
this.selectedAgent = agent;
},
onClose() {
this.$emit('close');
},
onCloseAgentList() {
if (this.selectedAgent === null && !this.goBackToAgentList) {
this.onClose();
}
this.goBackToAgentList = false;
},
},
};
</script>
<style scoped lang="scss">
.bulk-action__agents {
@apply max-w-[75%] absolute right-2 top-12 origin-top-right w-auto z-20 min-w-[15rem] bg-white dark:bg-slate-800 rounded-lg border border-solid border-slate-50 dark:border-slate-700 shadow-md;
.header {
@apply p-2.5;
span {
@apply text-sm font-medium;
}
}
.container {
@apply overflow-y-auto max-h-[15rem];
.agent__list-container {
@apply h-full;
}
.agent-list-search {
@apply py-0 px-2.5 bg-slate-50 dark:bg-slate-900 border border-solid border-slate-100 dark:border-slate-600/70 rounded-md;
.search-icon {
@apply text-slate-400 dark:text-slate-200;
}
.agent--search_input {
@apply border-0 text-xs m-0 dark:bg-transparent bg-transparent h-[unset] w-full;
}
}
}
.triangle {
right: var(--triangle-position);
@apply block z-10 absolute -top-3 text-left;
svg path {
@apply fill-white dark:fill-slate-800 stroke-slate-50 dark:stroke-slate-600/50;
}
}
}
ul {
@apply m-0 list-none;
li {
&:last-child {
.agent-list-item {
@apply last:rounded-b-lg;
}
}
}
}
.agent-list-item {
@apply flex items-center p-2.5 gap-2 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-900;
span {
@apply text-sm;
}
}
.agent-confirmation-container {
@apply flex flex-col h-full p-2.5;
p {
@apply flex-grow;
}
.agent-confirmation-actions {
@apply w-full grid grid-cols-2 gap-2.5;
}
}
.search-container {
@apply py-0 px-2.5 sticky top-0 z-20 bg-white dark:bg-slate-800;
}
.agent__list-loading {
@apply m-2.5 rounded-md bg-slate-25 dark:bg-slate-900 flex items-center justify-center flex-col p-5 h-[calc(95%-6.25rem)];
}
</style>