🗂️ fix: Optimize Conversation Grouping and Sorting (#4173)

* chore: remove double import of TrashIcon

* fix(convos): eslint warnings

* ci(convos): add test for month sorting

* fix(convos): grouping by month in chronological order instead of alphabetical, optimize sort

* ci: additional tests for conversation sorting

* chore: fix eslint disable rule

* chore: imports, use constant enum for 'new' value

* fix: test dependent on current date
This commit is contained in:
Danny Avila 2024-09-21 10:20:30 -04:00 committed by GitHub
parent 44458d3832
commit c1c13a69dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 243 additions and 39 deletions

View file

@ -60,6 +60,32 @@ const getGroupName = (date: Date) => {
return ' ' + getYear(date).toString();
};
const monthOrderMap = new Map([
['december', 11],
['november', 10],
['october', 9],
['september', 8],
['august', 7],
['july', 6],
['june', 5],
['may', 4],
['april', 3],
['march', 2],
['february', 1],
['january', 0],
]);
const dateKeysReverse = Object.fromEntries(
Object.entries(dateKeys).map(([key, value]) => [value, key]),
);
const dateGroupsSet = new Set([
dateKeys.today,
dateKeys.yesterday,
dateKeys.previous7Days,
dateKeys.previous30Days,
]);
export const groupConversationsByDate = (
conversations: Array<TConversation | null>,
): GroupedConversations => {
@ -68,47 +94,60 @@ export const groupConversationsByDate = (
}
const seenConversationIds = new Set();
const groups = conversations.reduce((acc, conversation) => {
if (!conversation) {
return acc;
}
const groups = new Map();
const today = startOfToday();
if (seenConversationIds.has(conversation.conversationId)) {
return acc;
conversations.forEach((conversation) => {
if (!conversation || seenConversationIds.has(conversation.conversationId)) {
return;
}
seenConversationIds.add(conversation.conversationId);
const date = conversation.updatedAt ? parseISO(conversation.updatedAt) : startOfToday();
const date = conversation.updatedAt ? parseISO(conversation.updatedAt) : today;
const groupName = getGroupName(date);
if (!acc[groupName]) {
acc[groupName] = [];
if (!groups.has(groupName)) {
groups.set(groupName, []);
}
acc[groupName].push(conversation);
return acc;
}, {});
groups.get(groupName).push(conversation);
});
const sortedGroups = {};
const dateGroups = [
dateKeys.today,
dateKeys.yesterday,
dateKeys.previous7Days,
dateKeys.previous30Days,
];
dateGroups.forEach((group) => {
if (groups[group]) {
sortedGroups[group] = groups[group];
const sortedGroups = new Map();
// Add date groups first
dateGroupsSet.forEach((group) => {
if (groups.has(group)) {
sortedGroups.set(group, groups.get(group));
}
});
Object.keys(groups)
.filter((group) => !dateGroups.includes(group))
.sort()
.reverse()
.forEach((year) => {
sortedGroups[year] = groups[year];
// Sort and add year/month groups
const yearMonthGroups = Array.from(groups.keys())
.filter((group) => !dateGroupsSet.has(group))
.sort((a, b) => {
const [yearA, yearB] = [parseInt(a.trim()), parseInt(b.trim())];
if (yearA !== yearB) {
return yearB - yearA;
}
const [monthA, monthB] = [dateKeysReverse[a], dateKeysReverse[b]];
const bOrder = monthOrderMap.get(monthB) ?? -1;
const aOrder = monthOrderMap.get(monthA) ?? -1;
return bOrder - aOrder;
});
return Object.entries(sortedGroups);
yearMonthGroups.forEach((group) => {
sortedGroups.set(group, groups.get(group));
});
// Sort conversations within each group
sortedGroups.forEach((conversations) => {
conversations.sort(
(a: TConversation, b: TConversation) =>
new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),
);
});
return Array.from(sortedGroups, ([key, value]) => [key, value]);
};
export const addConversation = (
@ -195,7 +234,7 @@ export const getConversationById = (
data: ConversationData | undefined,
conversationId: string | null,
): TConversation | undefined => {
if (!data || !conversationId) {
if (!data || !(conversationId ?? '')) {
return undefined;
}
@ -224,11 +263,11 @@ export function storeEndpointSettings(conversation: TConversation | null) {
return;
}
const lastModel = JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_MODEL) || '{}');
const lastModel = JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_MODEL) ?? '{}');
lastModel[endpoint] = model;
if (endpoint === EModelEndpoint.gptPlugins) {
lastModel.secondaryModel = agentOptions?.model || model || '';
lastModel.secondaryModel = agentOptions?.model ?? model ?? '';
}
localStorage.setItem(LocalStorageKeys.LAST_MODEL, JSON.stringify(lastModel));