feat: Advanced conversation sort options (#8532)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
@@ -269,7 +269,7 @@ export default {
|
||||
return {
|
||||
activeAssigneeTab: wootConstants.ASSIGNEE_TYPE.ME,
|
||||
activeStatus: wootConstants.STATUS_TYPE.OPEN,
|
||||
activeSortBy: wootConstants.SORT_BY_TYPE.LATEST,
|
||||
activeSortBy: wootConstants.SORT_BY_TYPE.LAST_ACTIVITY_AT_DESC,
|
||||
showAdvancedFilters: false,
|
||||
advancedFilterTypes: advancedFilterTypes.map(filter => ({
|
||||
...filter,
|
||||
@@ -553,7 +553,10 @@ export default {
|
||||
const { conversations_filter_by: filterBy = {} } = this.uiSettings;
|
||||
const { status, order_by: orderBy } = filterBy;
|
||||
this.activeStatus = status || wootConstants.STATUS_TYPE.OPEN;
|
||||
this.activeSortBy = orderBy || wootConstants.SORT_BY_TYPE.LATEST;
|
||||
this.activeSortBy =
|
||||
Object.keys(wootConstants.SORT_BY_TYPE).find(
|
||||
sortField => sortField === orderBy
|
||||
) || wootConstants.SORT_BY_TYPE.LAST_ACTIVITY_AT_DESC;
|
||||
},
|
||||
onClickOpenAddFoldersModal() {
|
||||
this.showAddFoldersModal = true;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
type="sort"
|
||||
:selected-value="sortFilter"
|
||||
:items="chatSortItems"
|
||||
path-prefix="CHAT_LIST.CHAT_SORT_FILTER_ITEMS"
|
||||
path-prefix="CHAT_LIST.SORT_ORDER_ITEMS"
|
||||
@onChangeFilter="onChangeFilter"
|
||||
/>
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
return {
|
||||
showActionsDropdown: false,
|
||||
chatStatusItems: this.$t('CHAT_LIST.CHAT_STATUS_FILTER_ITEMS'),
|
||||
chatSortItems: this.$t('CHAT_LIST.CHAT_SORT_FILTER_ITEMS'),
|
||||
chatSortItems: this.$t('CHAT_LIST.SORT_ORDER_ITEMS'),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -70,7 +70,9 @@ export default {
|
||||
return this.chatStatusFilter || wootConstants.STATUS_TYPE.OPEN;
|
||||
},
|
||||
sortFilter() {
|
||||
return this.chatSortFilter || wootConstants.SORT_BY_TYPE.LATEST;
|
||||
return (
|
||||
this.chatSortFilter || wootConstants.SORT_BY_TYPE.LAST_ACTIVITY_AT_DESC
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -13,10 +13,14 @@ export default {
|
||||
ALL: 'all',
|
||||
},
|
||||
SORT_BY_TYPE: {
|
||||
LATEST: 'latest',
|
||||
CREATED_AT: 'sort_on_created_at',
|
||||
PRIORITY: 'sort_on_priority',
|
||||
WATIING_SINCE: 'waiting_since',
|
||||
LAST_ACTIVITY_AT_ASC: 'last_activity_at_asc',
|
||||
LAST_ACTIVITY_AT_DESC: 'last_activity_at_desc',
|
||||
CREATED_AT_ASC: 'created_at_asc',
|
||||
CREATED_AT_DESC: 'created_at_desc',
|
||||
PRIORITY_ASC: 'priority_asc',
|
||||
PRIORITY_DESC: 'priority_desc',
|
||||
WAITING_SINCE_ASC: 'waiting_since_asc',
|
||||
WAITING_SINCE_DESC: 'waiting_since_desc',
|
||||
},
|
||||
ARTICLE_STATUS_TYPES: {
|
||||
DRAFT: 0,
|
||||
|
||||
@@ -51,18 +51,30 @@
|
||||
"ACTIVE": "Last activity"
|
||||
}
|
||||
},
|
||||
"CHAT_SORT_FILTER_ITEMS": {
|
||||
"latest": {
|
||||
"TEXT": "Last activity"
|
||||
"SORT_ORDER_ITEMS": {
|
||||
"last_activity_at_asc": {
|
||||
"TEXT": "Last activity: Oldest first"
|
||||
},
|
||||
"sort_on_created_at": {
|
||||
"TEXT": "Created at"
|
||||
"last_activity_at_desc": {
|
||||
"TEXT": "Last activity: Newest first"
|
||||
},
|
||||
"sort_on_priority": {
|
||||
"TEXT": "Priority"
|
||||
"created_at_desc": {
|
||||
"TEXT": "Created at: Newest first"
|
||||
},
|
||||
"sort_on_waiting_since": {
|
||||
"TEXT": "Pending Response"
|
||||
"created_at_asc": {
|
||||
"TEXT": "Created at: Oldest first"
|
||||
},
|
||||
"priority_desc": {
|
||||
"TEXT": "Priority: Highest first"
|
||||
},
|
||||
"priority_asc": {
|
||||
"TEXT": "Priority: Lowest first"
|
||||
},
|
||||
"waiting_since_asc": {
|
||||
"TEXT": "Pending Response: Longest first"
|
||||
},
|
||||
"waiting_since_desc": {
|
||||
"TEXT": "Pending Response: Shortest first"
|
||||
}
|
||||
},
|
||||
"ATTACHMENTS": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import {
|
||||
MESSAGE_TYPE,
|
||||
CONVERSATION_PRIORITY_ORDER,
|
||||
} from 'shared/constants/messages';
|
||||
import { applyPageFilters } from './helpers';
|
||||
import { MESSAGE_TYPE } from 'shared/constants/messages';
|
||||
import { applyPageFilters, sortComparator } from './helpers';
|
||||
|
||||
export const getSelectedChatConversation = ({
|
||||
allConversations,
|
||||
@@ -10,36 +7,9 @@ export const getSelectedChatConversation = ({
|
||||
}) =>
|
||||
allConversations.filter(conversation => conversation.id === selectedChatId);
|
||||
|
||||
const sortComparator = {
|
||||
latest: (a, b) => b.last_activity_at - a.last_activity_at,
|
||||
sort_on_created_at: (a, b) => a.created_at - b.created_at,
|
||||
sort_on_priority: (a, b) => {
|
||||
return (
|
||||
CONVERSATION_PRIORITY_ORDER[a.priority] -
|
||||
CONVERSATION_PRIORITY_ORDER[b.priority]
|
||||
);
|
||||
},
|
||||
sort_on_waiting_since: (a, b) => {
|
||||
if (!a.waiting_since && !b.waiting_since) {
|
||||
return a.created_at - b.created_at;
|
||||
}
|
||||
|
||||
if (!a.waiting_since) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!b.waiting_since) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return a.waiting_since - b.waiting_since;
|
||||
},
|
||||
};
|
||||
|
||||
// getters
|
||||
const getters = {
|
||||
getAllConversations: ({ allConversations, chatSortFilter }) => {
|
||||
return allConversations.sort(sortComparator[chatSortFilter]);
|
||||
getAllConversations: ({ allConversations, chatSortFilter: sortKey }) => {
|
||||
return allConversations.sort((a, b) => sortComparator(a, b, sortKey));
|
||||
},
|
||||
getSelectedChat: ({ selectedChatId, allConversations }) => {
|
||||
const selectedChat = allConversations.find(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CONVERSATION_PRIORITY_ORDER } from 'shared/constants/messages';
|
||||
|
||||
export const findPendingMessageIndex = (chat, message) => {
|
||||
const { echo_id: tempMessageId } = message;
|
||||
return chat.messages.findIndex(
|
||||
@@ -59,3 +61,53 @@ export const applyPageFilters = (conversation, filters) => {
|
||||
|
||||
return shouldFilter;
|
||||
};
|
||||
|
||||
const SORT_OPTIONS = {
|
||||
last_activity_at_asc: ['sortOnLastActivityAt', 'asc'],
|
||||
last_activity_at_desc: ['sortOnLastActivityAt', 'desc'],
|
||||
created_at_asc: ['sortOnCreatedAt', 'asc'],
|
||||
created_at_desc: ['sortOnCreatedAt', 'desc'],
|
||||
priority_asc: ['sortOnPriority', 'asc'],
|
||||
priority_desc: ['sortOnPriority', 'desc'],
|
||||
waiting_since_asc: ['sortOnWaitingSince', 'asc'],
|
||||
waiting_since_desc: ['sortOnWaitingSince', 'desc'],
|
||||
};
|
||||
const sortAscending = (valueA, valueB) => valueA - valueB;
|
||||
const sortDescending = (valueA, valueB) => valueB - valueA;
|
||||
|
||||
const getSortOrderFunction = sortOrder =>
|
||||
sortOrder === 'asc' ? sortAscending : sortDescending;
|
||||
|
||||
const sortConfig = {
|
||||
sortOnLastActivityAt: (a, b, sortDirection) =>
|
||||
getSortOrderFunction(sortDirection)(a.last_activity_at, b.last_activity_at),
|
||||
|
||||
sortOnCreatedAt: (a, b, sortDirection) =>
|
||||
getSortOrderFunction(sortDirection)(a.created_at, b.created_at),
|
||||
|
||||
sortOnPriority: (a, b, sortDirection) => {
|
||||
const DEFAULT_FOR_NULL = sortDirection === 'asc' ? 5 : 0;
|
||||
|
||||
const p1 = CONVERSATION_PRIORITY_ORDER[a.priority] || DEFAULT_FOR_NULL;
|
||||
const p2 = CONVERSATION_PRIORITY_ORDER[b.priority] || DEFAULT_FOR_NULL;
|
||||
|
||||
return getSortOrderFunction(sortDirection)(p1, p2);
|
||||
},
|
||||
|
||||
sortOnWaitingSince: (a, b, sortDirection) => {
|
||||
const sortFunc = getSortOrderFunction(sortDirection);
|
||||
if (!a.waiting_since || !b.waiting_since) {
|
||||
if (!a.waiting_since && !b.waiting_since) {
|
||||
return sortFunc(a.created_at, b.created_at);
|
||||
}
|
||||
return sortFunc(a.waiting_since ? 0 : 1, b.waiting_since ? 0 : 1);
|
||||
}
|
||||
|
||||
return sortFunc(a.waiting_since, b.waiting_since);
|
||||
},
|
||||
};
|
||||
|
||||
export const sortComparator = (a, b, sortKey) => {
|
||||
const [sortMethod, sortDirection] = SORT_OPTIONS[sortKey] || [];
|
||||
return sortConfig[sortMethod](a, b, sortDirection);
|
||||
};
|
||||
|
||||
@@ -47,6 +47,49 @@ describe('#getters', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('order conversations based on last activity with ascending order', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
content: 'test1',
|
||||
},
|
||||
],
|
||||
created_at: 2466424490,
|
||||
last_activity_at: 2466424490,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
messages: [{ content: 'test2' }],
|
||||
created_at: 1466424480,
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
],
|
||||
chatSortFilter: 'latest_last',
|
||||
};
|
||||
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
{
|
||||
id: 2,
|
||||
messages: [{ content: 'test2' }],
|
||||
created_at: 1466424480,
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
content: 'test1',
|
||||
},
|
||||
],
|
||||
created_at: 2466424490,
|
||||
last_activity_at: 2466424490,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('order conversations based on created at', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
@@ -67,7 +110,7 @@ describe('#getters', () => {
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
],
|
||||
chatSortFilter: 'sort_on_created_at',
|
||||
chatSortFilter: 'created_at_last',
|
||||
};
|
||||
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
@@ -89,6 +132,50 @@ describe('#getters', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('order conversations based on created at with descending order', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
content: 'test1',
|
||||
},
|
||||
],
|
||||
created_at: 1683645801, // Tuesday, 9 May 2023
|
||||
last_activity_at: 2466424490,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
messages: [{ content: 'test2' }],
|
||||
created_at: 1652109801, // Monday, 9 May 2022
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
],
|
||||
chatSortFilter: 'created_at_first',
|
||||
};
|
||||
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
content: 'test1',
|
||||
},
|
||||
],
|
||||
created_at: 1683645801,
|
||||
last_activity_at: 2466424490,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
messages: [{ content: 'test2' }],
|
||||
created_at: 1652109801,
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('order conversations based on default order', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
@@ -159,7 +246,7 @@ describe('#getters', () => {
|
||||
last_activity_at: 1466421280,
|
||||
},
|
||||
],
|
||||
chatSortFilter: 'sort_on_priority',
|
||||
chatSortFilter: 'priority_first',
|
||||
};
|
||||
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
@@ -190,6 +277,68 @@ describe('#getters', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('order conversations based on with descending order', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
content: 'test1',
|
||||
},
|
||||
],
|
||||
priority: 'low',
|
||||
created_at: 1683645801,
|
||||
last_activity_at: 2466424490,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
messages: [{ content: 'test2' }],
|
||||
priority: 'urgent',
|
||||
created_at: 1652109801,
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
messages: [{ content: 'test3' }],
|
||||
priority: 'medium',
|
||||
created_at: 1652109801,
|
||||
last_activity_at: 1466421280,
|
||||
},
|
||||
],
|
||||
chatSortFilter: 'priority_last',
|
||||
};
|
||||
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
content: 'test1',
|
||||
},
|
||||
],
|
||||
priority: 'low',
|
||||
created_at: 1683645801,
|
||||
last_activity_at: 2466424490,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
messages: [{ content: 'test3' }],
|
||||
priority: 'medium',
|
||||
created_at: 1652109801,
|
||||
last_activity_at: 1466421280,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
messages: [{ content: 'test2' }],
|
||||
priority: 'urgent',
|
||||
created_at: 1652109801,
|
||||
last_activity_at: 1466424480,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('order conversations based on waiting_since', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
@@ -214,7 +363,7 @@ describe('#getters', () => {
|
||||
waiting_since: 1683645800,
|
||||
},
|
||||
],
|
||||
chatSortFilter: 'sort_on_waiting_since',
|
||||
chatSortFilter: 'waiting_since_last',
|
||||
};
|
||||
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
|
||||
@@ -28,11 +28,10 @@ export const CONVERSATION_PRIORITY = {
|
||||
};
|
||||
|
||||
export const CONVERSATION_PRIORITY_ORDER = {
|
||||
urgent: 1,
|
||||
high: 2,
|
||||
medium: 3,
|
||||
low: 4,
|
||||
null: 5,
|
||||
urgent: 4,
|
||||
high: 3,
|
||||
medium: 2,
|
||||
low: 1,
|
||||
};
|
||||
|
||||
// Size in mega bytes
|
||||
|
||||
Reference in New Issue
Block a user