feat: Adds the ability to sort conversations (#6853)

* Add sort filter

* Change UI

* Change filter

* Complete sort by filters

* Style fixes

* Fix default sort

* Update app/javascript/dashboard/components/widgets/conversation/ConversationBasicFilter.vue

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>

* Update app/javascript/dashboard/components/widgets/conversation/ConversationBasicFilter.vue

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>

* Update app/javascript/dashboard/components/ChatList.vue

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>

* Added translation

* Added review fixes

* Add more updates

* Code cleanups

* Update last_activity_at on message received event

* Cleans up the design for chatlist and icons

* Fix sort

* Remove inline styles

* Add tag along with the title

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
This commit is contained in:
Muhsin Keloth
2023-05-06 05:38:32 +05:30
committed by GitHub
parent 85e57c2e94
commit 59433d9d3c
19 changed files with 326 additions and 31 deletions

View File

@@ -38,8 +38,8 @@ export default {
this.onTabChange();
},
onTabChange() {
this.$store.dispatch('setChatFilter', this.activeStatus);
this.$emit('statusFilterChange', this.activeStatus);
this.$store.dispatch('setChatStatusFilter', this.activeStatus);
this.$emit('onChangeFilter', this.activeStatus);
},
},
};

View File

@@ -0,0 +1,122 @@
<template>
<div class="position-relative">
<woot-button
v-tooltip.right="$t('CHAT_LIST.SORT_TOOLTIP_LABEL')"
variant="smooth"
size="tiny"
color-scheme="secondary"
class="selector-button"
icon="sort-icon"
@click="toggleDropdown"
/>
<div
v-if="showActionsDropdown"
v-on-clickaway="closeDropdown"
class="dropdown-pane dropdown-pane--open basic-filter"
>
<div class="filter__item">
<span>{{ this.$t('CHAT_LIST.CHAT_SORT.STATUS') }}</span>
<filter-item
type="status"
:selected-value="chatStatus"
:items="chatStatusItems"
path-prefix="CHAT_LIST.CHAT_STATUS_FILTER_ITEMS"
@onChangeFilter="onChangeFilter"
/>
</div>
<div class="filter__item">
<span>{{ this.$t('CHAT_LIST.CHAT_SORT.ORDER_BY') }}</span>
<filter-item
type="sort"
:selected-value="chatSortFilter"
:items="chatSortItems"
path-prefix="CHAT_LIST.CHAT_SORT_FILTER_ITEMS"
@onChangeFilter="onChangeFilter"
/>
</div>
</div>
</div>
</template>
<script>
import wootConstants from 'dashboard/constants/globals';
import { mapGetters } from 'vuex';
import { mixin as clickaway } from 'vue-clickaway';
import FilterItem from './FilterItem';
export default {
components: {
FilterItem,
},
mixins: [clickaway],
data() {
return {
showActionsDropdown: false,
chatStatusItems: this.$t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS'),
chatSortItems: this.$t('CHAT_LIST.CHAT_SORT_FILTER_ITEMS'),
};
},
computed: {
...mapGetters({
chatStatusFilter: 'getChatStatusFilter',
chatSortFilter: 'getChatSortFilter',
}),
chatStatus() {
return this.chatStatusFilter || wootConstants.STATUS_TYPE.OPEN;
},
sortFilter() {
return this.chatSortFilter || wootConstants.SORT_BY_TYPE.LATEST;
},
},
methods: {
onTabChange(value) {
this.$emit('changeFilter', value);
this.closeDropdown();
},
toggleDropdown() {
this.showActionsDropdown = !this.showActionsDropdown;
},
closeDropdown() {
this.showActionsDropdown = false;
},
onChangeFilter(type, value) {
this.$emit('changeFilter', type, value);
},
},
};
</script>
<style lang="scss" scoped>
.basic-filter {
margin-top: var(--space-smaller);
padding: var(--space-normal);
right: 0;
width: 21rem;
span {
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
}
.filter__item {
align-items: center;
display: flex;
justify-content: space-between;
&:last-child {
margin-top: var(--space-normal);
}
span {
font-size: var(--font-size-mini);
}
}
}
.icon {
margin-right: var(--space-smaller);
}
.dropdown-icon {
margin-left: var(--space-smaller);
}
</style>

View File

@@ -0,0 +1,55 @@
<template>
<select v-model="activeValue" class="status--filter" @change="onTabChange()">
<option v-for="(value, status) in items" :key="status" :value="status">
{{ $t(`${pathPrefix}.${status}.TEXT`) }}
</option>
</select>
</template>
<script>
export default {
props: {
selectedValue: {
type: String,
required: true,
},
items: {
type: Object,
required: true,
},
type: {
type: String,
required: true,
},
pathPrefix: {
type: String,
required: true,
},
},
data() {
return {
activeValue: this.selectedValue,
};
},
methods: {
onTabChange() {
if (this.type === 'status') {
this.$store.dispatch('setChatStatusFilter', this.activeValue);
} else {
this.$store.dispatch('setChatSortFilter', this.activeValue);
}
this.$emit('onChangeFilter', this.activeValue, this.type);
},
},
};
</script>
<style lang="scss" scoped>
.status--filter {
background-color: var(--color-background-light);
border: 1px solid var(--color-border);
font-size: var(--font-size-mini);
height: var(--space-medium);
margin: 0 var(--space-smaller);
padding: 0 var(--space-medium) 0 var(--space-small);
width: 126px;
}
</style>