2024-09-21 10:20:30 -04:00
|
|
|
import { Constants } from 'librechat-data-provider';
|
|
|
|
|
import type { TConversation, ConversationData } from 'librechat-data-provider';
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
import {
|
2024-05-14 11:00:01 -04:00
|
|
|
dateKeys,
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
addConversation,
|
|
|
|
|
updateConvoFields,
|
2024-05-14 11:00:01 -04:00
|
|
|
updateConversation,
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
deleteConversation,
|
|
|
|
|
findPageForConversation,
|
2024-05-14 11:00:01 -04:00
|
|
|
groupConversationsByDate,
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
} from './convos';
|
2024-09-21 10:20:30 -04:00
|
|
|
import { convoData } from './convos.fakeData';
|
2024-05-24 09:38:38 -07:00
|
|
|
import { normalizeData } from './collection';
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
|
2024-09-21 18:50:04 -04:00
|
|
|
jest.mock('date-fns', () => {
|
|
|
|
|
const actual = jest.requireActual('date-fns');
|
|
|
|
|
return {
|
|
|
|
|
...actual,
|
|
|
|
|
startOfToday: jest.fn(() => new Date('2023-07-15T00:00:00Z')),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
describe('Conversation Utilities', () => {
|
|
|
|
|
describe('groupConversationsByDate', () => {
|
|
|
|
|
it('groups conversations by date correctly', () => {
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-04-01T12:00:00Z' },
|
|
|
|
|
{ conversationId: '2', updatedAt: new Date().toISOString() },
|
2024-02-11 08:53:44 -05:00
|
|
|
{ conversationId: '3', updatedAt: new Date(Date.now() - 86400000).toISOString() }, // 86400 seconds ago = yesterday
|
|
|
|
|
{ conversationId: '4', updatedAt: new Date(Date.now() - 86400000 * 2).toISOString() }, // 2 days ago (previous 7 days)
|
|
|
|
|
{ conversationId: '5', updatedAt: new Date(Date.now() - 86400000 * 8).toISOString() }, // 8 days ago (previous 30 days)
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
];
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
2024-05-14 11:00:01 -04:00
|
|
|
expect(grouped[0][0]).toBe(dateKeys.today);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
expect(grouped[0][1]).toHaveLength(1);
|
2024-05-14 11:00:01 -04:00
|
|
|
expect(grouped[1][0]).toBe(dateKeys.yesterday);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
expect(grouped[1][1]).toHaveLength(1);
|
2024-05-14 11:00:01 -04:00
|
|
|
expect(grouped[2][0]).toBe(dateKeys.previous7Days);
|
2024-02-11 08:53:44 -05:00
|
|
|
expect(grouped[2][1]).toHaveLength(1);
|
2024-05-14 11:00:01 -04:00
|
|
|
expect(grouped[3][0]).toBe(dateKeys.previous30Days);
|
2024-02-11 08:53:44 -05:00
|
|
|
expect(grouped[3][1]).toHaveLength(1);
|
|
|
|
|
expect(grouped[4][0]).toBe(' 2023');
|
|
|
|
|
expect(grouped[4][1]).toHaveLength(1);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|
|
|
|
|
|
2024-09-21 18:50:04 -04:00
|
|
|
it('groups conversations correctly across multiple years', () => {
|
|
|
|
|
const fixedDate = new Date('2023-07-15T12:00:00Z');
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-07-15T10:00:00Z' }, // Today
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-07-14T12:00:00Z' }, // Yesterday
|
|
|
|
|
{ conversationId: '3', updatedAt: '2023-07-08T12:00:00Z' }, // This week
|
|
|
|
|
{ conversationId: '4', updatedAt: '2023-07-01T12:00:00Z' }, // This month (within last 30 days)
|
|
|
|
|
{ conversationId: '5', updatedAt: '2023-06-01T12:00:00Z' }, // Last month
|
|
|
|
|
{ conversationId: '6', updatedAt: '2023-01-01T12:00:00Z' }, // This year, January
|
|
|
|
|
{ conversationId: '7', updatedAt: '2022-12-01T12:00:00Z' }, // Last year, December
|
|
|
|
|
{ conversationId: '8', updatedAt: '2022-06-01T12:00:00Z' }, // Last year, June
|
|
|
|
|
{ conversationId: '9', updatedAt: '2021-12-01T12:00:00Z' }, // Two years ago
|
|
|
|
|
{ conversationId: '10', updatedAt: '2020-06-01T12:00:00Z' }, // Three years ago
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Mock Date.now
|
|
|
|
|
const originalDateNow = Date.now;
|
|
|
|
|
Date.now = jest.fn(() => fixedDate.getTime());
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
// Restore Date.now
|
|
|
|
|
Date.now = originalDateNow;
|
|
|
|
|
|
|
|
|
|
const expectedGroups = [
|
|
|
|
|
dateKeys.today,
|
|
|
|
|
dateKeys.yesterday,
|
|
|
|
|
dateKeys.previous7Days,
|
|
|
|
|
dateKeys.previous30Days,
|
|
|
|
|
dateKeys.june,
|
|
|
|
|
dateKeys.january,
|
|
|
|
|
' 2022',
|
|
|
|
|
' 2021',
|
|
|
|
|
' 2020',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
expect(grouped.map(([key]) => key)).toEqual(expectedGroups);
|
|
|
|
|
|
|
|
|
|
// Helper function to safely get group length
|
|
|
|
|
const getGroupLength = (key: string) => grouped.find(([k]) => k === key)?.[1]?.length ?? 0;
|
|
|
|
|
|
|
|
|
|
// Check specific group contents
|
|
|
|
|
expect(getGroupLength(dateKeys.today)).toBe(1);
|
|
|
|
|
expect(getGroupLength(dateKeys.yesterday)).toBe(1);
|
|
|
|
|
expect(getGroupLength(dateKeys.previous7Days)).toBe(1);
|
|
|
|
|
expect(getGroupLength(dateKeys.previous30Days)).toBe(1);
|
|
|
|
|
expect(getGroupLength(dateKeys.june)).toBe(1);
|
|
|
|
|
expect(getGroupLength(dateKeys.january)).toBe(1);
|
|
|
|
|
expect(getGroupLength(' 2022')).toBe(2); // December and June 2022
|
|
|
|
|
expect(getGroupLength(' 2021')).toBe(1);
|
|
|
|
|
expect(getGroupLength(' 2020')).toBe(1);
|
|
|
|
|
|
|
|
|
|
// Check that all conversations are accounted for
|
|
|
|
|
const totalGroupedConversations = grouped.reduce(
|
|
|
|
|
(total, [, convos]) => total + convos.length,
|
|
|
|
|
0,
|
|
|
|
|
);
|
|
|
|
|
expect(totalGroupedConversations).toBe(conversations.length);
|
|
|
|
|
});
|
|
|
|
|
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
it('returns an empty array for no conversations', () => {
|
|
|
|
|
expect(groupConversationsByDate([])).toEqual([]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('skips conversations with duplicate conversationIds', () => {
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-12-01T12:00:00Z' }, // " 2023"
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-11-25T12:00:00Z' }, // " 2023"
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-11-20T12:00:00Z' }, // Should be skipped because of duplicate ID
|
|
|
|
|
{ conversationId: '3', updatedAt: '2022-12-01T12:00:00Z' }, // " 2022"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
expect(grouped).toEqual(
|
|
|
|
|
expect.arrayContaining([
|
|
|
|
|
expect.arrayContaining([' 2023', expect.arrayContaining(conversations.slice(0, 2))]),
|
|
|
|
|
expect.arrayContaining([' 2022', expect.arrayContaining([conversations[3]])]),
|
|
|
|
|
]),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// No duplicate IDs are present
|
|
|
|
|
const allGroupedIds = grouped.flatMap(([, convs]) => convs.map((c) => c.conversationId));
|
|
|
|
|
const uniqueIds = [...new Set(allGroupedIds)];
|
|
|
|
|
expect(allGroupedIds.length).toBe(uniqueIds.length);
|
|
|
|
|
});
|
2024-09-21 10:20:30 -04:00
|
|
|
|
|
|
|
|
it('sorts conversations by month correctly', () => {
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-01-01T12:00:00Z' }, // January 2023
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-12-01T12:00:00Z' }, // December 2023
|
|
|
|
|
{ conversationId: '3', updatedAt: '2023-02-01T12:00:00Z' }, // February 2023
|
|
|
|
|
{ conversationId: '4', updatedAt: '2023-11-01T12:00:00Z' }, // November 2023
|
|
|
|
|
{ conversationId: '5', updatedAt: '2022-12-01T12:00:00Z' }, // December 2022
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
// Check if the years are in the correct order (most recent first)
|
|
|
|
|
expect(grouped.map(([key]) => key)).toEqual([' 2023', ' 2022']);
|
|
|
|
|
|
|
|
|
|
// Check if conversations within 2023 are sorted correctly by month
|
|
|
|
|
const conversationsIn2023 = grouped[0][1];
|
|
|
|
|
const monthsIn2023 = conversationsIn2023.map((c) => new Date(c.updatedAt).getMonth());
|
|
|
|
|
expect(monthsIn2023).toEqual([11, 10, 1, 0]); // December (11), November (10), February (1), January (0)
|
|
|
|
|
|
|
|
|
|
// Check if the conversation from 2022 is in its own group
|
|
|
|
|
expect(grouped[1][1].length).toBe(1);
|
|
|
|
|
expect(new Date(grouped[1][1][0].updatedAt).getFullYear()).toBe(2022);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('handles conversations from multiple years correctly', () => {
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-01-01T12:00:00Z' }, // January 2023
|
|
|
|
|
{ conversationId: '2', updatedAt: '2022-12-01T12:00:00Z' }, // December 2022
|
|
|
|
|
{ conversationId: '3', updatedAt: '2021-06-01T12:00:00Z' }, // June 2021
|
|
|
|
|
{ conversationId: '4', updatedAt: '2023-06-01T12:00:00Z' }, // June 2023
|
|
|
|
|
{ conversationId: '5', updatedAt: '2021-12-01T12:00:00Z' }, // December 2021
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
expect(grouped.map(([key]) => key)).toEqual([' 2023', ' 2022', ' 2021']);
|
|
|
|
|
expect(grouped[0][1].map((c) => new Date(c.updatedAt).getMonth())).toEqual([5, 0]); // June, January
|
|
|
|
|
expect(grouped[1][1].map((c) => new Date(c.updatedAt).getMonth())).toEqual([11]); // December
|
|
|
|
|
expect(grouped[2][1].map((c) => new Date(c.updatedAt).getMonth())).toEqual([11, 5]); // December, June
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('handles conversations from the same month correctly', () => {
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-06-01T12:00:00Z' },
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-06-15T12:00:00Z' },
|
|
|
|
|
{ conversationId: '3', updatedAt: '2023-06-30T12:00:00Z' },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
expect(grouped.length).toBe(1);
|
|
|
|
|
expect(grouped[0][0]).toBe(' 2023');
|
|
|
|
|
expect(grouped[0][1].map((c) => c.conversationId)).toEqual(['3', '2', '1']);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('handles conversations from today, yesterday, and previous days correctly', () => {
|
|
|
|
|
const today = new Date();
|
|
|
|
|
const yesterday = new Date(today);
|
|
|
|
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
|
|
|
const twoDaysAgo = new Date(today);
|
|
|
|
|
twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
|
|
|
|
|
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: today.toISOString() },
|
|
|
|
|
{ conversationId: '2', updatedAt: yesterday.toISOString() },
|
|
|
|
|
{ conversationId: '3', updatedAt: twoDaysAgo.toISOString() },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
expect(grouped.map(([key]) => key)).toEqual([
|
|
|
|
|
dateKeys.today,
|
|
|
|
|
dateKeys.yesterday,
|
|
|
|
|
dateKeys.previous7Days,
|
|
|
|
|
]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('handles conversations with null or undefined updatedAt correctly', () => {
|
|
|
|
|
const conversations = [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-06-01T12:00:00Z' },
|
|
|
|
|
{ conversationId: '2', updatedAt: null },
|
|
|
|
|
{ conversationId: '3', updatedAt: undefined },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
expect(grouped.length).toBe(2); // One group for 2023 and one for today (null/undefined dates)
|
|
|
|
|
expect(grouped[0][0]).toBe(dateKeys.today);
|
|
|
|
|
expect(grouped[0][1].length).toBe(2); // Two conversations with null/undefined dates
|
|
|
|
|
expect(grouped[1][0]).toBe(' 2023');
|
|
|
|
|
expect(grouped[1][1].length).toBe(1); // One conversation from 2023
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('handles an empty array of conversations', () => {
|
|
|
|
|
const grouped = groupConversationsByDate([]);
|
|
|
|
|
|
|
|
|
|
expect(grouped).toEqual([]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('correctly groups and sorts conversations for every month of the year', () => {
|
|
|
|
|
const months = [
|
|
|
|
|
'january',
|
|
|
|
|
'february',
|
|
|
|
|
'march',
|
|
|
|
|
'april',
|
|
|
|
|
'may',
|
|
|
|
|
'june',
|
|
|
|
|
'july',
|
|
|
|
|
'august',
|
|
|
|
|
'september',
|
|
|
|
|
'october',
|
|
|
|
|
'november',
|
|
|
|
|
'december',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Create conversations for each month in both 2023 and 2022
|
|
|
|
|
const conversations = months.flatMap((month, index) => [
|
|
|
|
|
{
|
|
|
|
|
conversationId: `2023-${month}`,
|
|
|
|
|
updatedAt: `2023-${String(index + 1).padStart(2, '0')}-15T12:00:00Z`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
conversationId: `2022-${month}`,
|
|
|
|
|
updatedAt: `2022-${String(index + 1).padStart(2, '0')}-15T12:00:00Z`,
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const grouped = groupConversationsByDate(conversations as TConversation[]);
|
|
|
|
|
|
|
|
|
|
// Check that we have two year groups
|
|
|
|
|
expect(grouped.length).toBe(2);
|
|
|
|
|
|
|
|
|
|
// Check 2023 months
|
|
|
|
|
const group2023 = grouped.find(([key]) => key === ' 2023') ?? [];
|
|
|
|
|
expect(group2023).toBeDefined();
|
|
|
|
|
const grouped2023 = group2023[1];
|
|
|
|
|
expect(grouped2023?.length).toBe(12);
|
|
|
|
|
expect(grouped2023?.map((c) => new Date(c.updatedAt).getMonth())).toEqual([
|
|
|
|
|
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// Check 2022 months
|
|
|
|
|
const group2022 = grouped.find(([key]) => key === ' 2022') ?? [];
|
|
|
|
|
expect(group2022).toBeDefined();
|
|
|
|
|
const grouped2022 = group2022[1];
|
|
|
|
|
expect(grouped2022?.length).toBe(12);
|
|
|
|
|
expect(grouped2022?.map((c) => new Date(c.updatedAt).getMonth())).toEqual([
|
|
|
|
|
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// Check that all conversations are accounted for
|
|
|
|
|
const totalGroupedConversations =
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
|
grouped.reduce((total, [_, convos]) => total + convos.length, 0);
|
|
|
|
|
expect(totalGroupedConversations).toBe(conversations.length);
|
|
|
|
|
|
|
|
|
|
// Check that the years are in the correct order
|
|
|
|
|
const yearOrder = grouped.map(([key]) => key);
|
|
|
|
|
expect(yearOrder).toEqual([' 2023', ' 2022']);
|
|
|
|
|
});
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('addConversation', () => {
|
|
|
|
|
it('adds a new conversation to the top of the list', () => {
|
|
|
|
|
const data = { pages: [{ conversations: [] }] };
|
2024-09-21 10:20:30 -04:00
|
|
|
const newConversation = {
|
|
|
|
|
conversationId: Constants.NEW_CONVO,
|
|
|
|
|
updatedAt: '2023-04-02T12:00:00Z',
|
|
|
|
|
};
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
const newData = addConversation(
|
|
|
|
|
data as unknown as ConversationData,
|
|
|
|
|
newConversation as TConversation,
|
|
|
|
|
);
|
|
|
|
|
expect(newData.pages[0].conversations).toHaveLength(1);
|
2024-09-21 10:20:30 -04:00
|
|
|
expect(newData.pages[0].conversations[0].conversationId).toBe(Constants.NEW_CONVO);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('updateConversation', () => {
|
|
|
|
|
it('updates an existing conversation and moves it to the top', () => {
|
|
|
|
|
const initialData = {
|
|
|
|
|
pages: [
|
|
|
|
|
{
|
|
|
|
|
conversations: [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-04-01T12:00:00Z' },
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-04-01T13:00:00Z' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
const updatedConversation = { conversationId: '1', updatedAt: '2023-04-02T12:00:00Z' };
|
|
|
|
|
const newData = updateConversation(
|
|
|
|
|
initialData as unknown as ConversationData,
|
|
|
|
|
updatedConversation as TConversation,
|
|
|
|
|
);
|
|
|
|
|
expect(newData.pages[0].conversations).toHaveLength(2);
|
|
|
|
|
expect(newData.pages[0].conversations[0].conversationId).toBe('1');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('updateConvoFields', () => {
|
|
|
|
|
it('updates specific fields of a conversation', () => {
|
|
|
|
|
const initialData = {
|
|
|
|
|
pages: [
|
|
|
|
|
{
|
|
|
|
|
conversations: [
|
|
|
|
|
{ conversationId: '1', title: 'Old Title', updatedAt: '2023-04-01T12:00:00Z' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
const updatedFields = { conversationId: '1', title: 'New Title' };
|
|
|
|
|
const newData = updateConvoFields(
|
|
|
|
|
initialData as ConversationData,
|
|
|
|
|
updatedFields as TConversation,
|
|
|
|
|
);
|
|
|
|
|
expect(newData.pages[0].conversations[0].title).toBe('New Title');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('deleteConversation', () => {
|
|
|
|
|
it('removes a conversation by id', () => {
|
|
|
|
|
const initialData = {
|
|
|
|
|
pages: [
|
|
|
|
|
{
|
|
|
|
|
conversations: [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-04-01T12:00:00Z' },
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-04-01T13:00:00Z' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
const newData = deleteConversation(initialData as ConversationData, '1');
|
|
|
|
|
expect(newData.pages[0].conversations).toHaveLength(1);
|
|
|
|
|
expect(newData.pages[0].conversations[0].conversationId).not.toBe('1');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('findPageForConversation', () => {
|
|
|
|
|
it('finds the correct page and index for a given conversation', () => {
|
|
|
|
|
const data = {
|
|
|
|
|
pages: [
|
|
|
|
|
{
|
|
|
|
|
conversations: [
|
|
|
|
|
{ conversationId: '1', updatedAt: '2023-04-01T12:00:00Z' },
|
|
|
|
|
{ conversationId: '2', updatedAt: '2023-04-02T13:00:00Z' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
🚀 feat: Shared Links (#2772)
* ✨ feat(types): add necessary types for shared link feature
* ✨ feat: add shared links functions to data service
Added functions for retrieving, creating, updating, and deleting shared links and shared messages.
* ✨ feat: Add useGetSharedMessages hook to fetch shared messages by shareId
Adds a new hook `useGetSharedMessages` which fetches shared messages based on the provided shareId.
* ✨ feat: Add share schema and data access functions to API models
* ✨ feat: Add share endpoint to API
The GET /api/share/${shareId} is exposed to the public, so authentication is not required. Other paths require authentication.
* ♻️ refactor(utils): generalize react-query cache manipulation functions
Introduces generic functions for manipulating react-query cache entries, marking a refinement in how query cache data is managed. It aims to enhance the flexibility and reusability of the cache interaction patterns within our application.
- Replaced specific index names with more generic terms in queries.ts, enhancing consistency across data handling functions.
- Introduced new utility functions in collection.ts for adding, updating, and deleting data entries in an InfiniteData<TCollection>. These utility functions (`addData`, `updateData`, `deleteData`, `findPage`) are designed to be re-usable across different data types and collections.
- Adapted existing conversation utility functions in convos.ts to leverage these new generic utilities.
* ✨ feat(shared-link): add functions to manipulate shared link cache list
implemented new utility functions to handle additions, updates, and deletions in the shared link cache list.
* ✨ feat: Add mutations and queries for shared links
* ✨ feat(shared-link): add `Share` button to conversation list
- Added a share button in each conversation in the conversation list.
- Implemented functionality where clicking the share button triggers a POST request to the API.
- The API checks if a share link was already created for the conversation today; if so, it returns the existing link.
- If no link was created for today, the API will create a new share link and return it.
- Each click on the share button results in a new API request, following the specification similar to ChatGPT's share link feature.
* ♻️ refactor(hooks): generalize useNavScrolling for broader use
- Modified `useNavScrolling` to accept a generic type parameter `TData`, allowing it to be used with different data structures besides `ConversationListResponse`.
- Updated instances in `Nav.tsx` and `ArchivedChatsTable.tsx` to explicitly specify `ConversationListResponse` as the type argument when invoking `useNavScrolling`.
* ✨ feat(settings): add shared links listing table with delete functionality in settings
- Integrated a delete button for each shared link in the table, allowing users to remove links as needed.
* ♻️ refactor(components): separate `EndpointIcon` from `Icon` component for standalone use
* ♻️ refactor: update useGetSharedMessages to return TSharedLink
- Modified the useGetSharedMessages hook to return not only a list of TMessage but also the TSharedLink itself.
- This change was necessary to support displaying the title and date in the Shared Message UI, which requires data from TSharedLink.
* ✨ feat(shared link): add UI for displaying shared conversations without authentication
- Implemented a new UI component to display shared conversations, designed to be accessible without requiring authentication.
- Reused components from the authenticated Messages module where possible. Copied and adapted components that could not be directly reused to fit the non-authenticated context.
* 🔧 chore: Add translations
Translate labels only. Messages remain in English as they are possibly subject to change.
* ♻️ refactor: add icon and tooltip props to EditMenuButton component
* moved icon and popover to arguments so that EditMenuButton can be reused.
* modified so that when a ShareButton is closed, the parent DropdownMenu is also closed.
* ♻️irefactor: added DropdownMenu for Export and Share
* ♻️ refactor: renamed component names more intuitive
* More accurate naming of the dropdown menu.
* When the export button is closed, the parent dropdown menu is also closed.
* 🌍 chore: updated translations
* 🐞 Fix: OpenID Profile Image Download (#2757)
* Add fetch requirement
Fixes - error: [openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": TypeError: response.buffer is not a function
* Update openidStrategy.js
---------
Co-authored-by: Danny Avila <danacordially@gmail.com>
* 🚑 fix(export): Issue exporting Conversation with Assistants (#2769)
* 🚑 fix(export): use content as text if content is present in the message
If the endpoint is assistants, the text of the message goes into content, not message.text.
* refactor(ExportModel): TypeScript, remove unused code
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
* 📤style: export button icon (#2752)
* refactor(ShareDialog): logic and styling
* refactor(ExportAndShareMenu): imports order and icon update
* chore: imports
* chore: imports/render logic
* feat: message branching
* refactor: add optional config to useGetStartupConfig
* refactor: disable endpoints query
* chore: fix search view styling gradient in light mode
* style: ShareView gradient styling
* refactor(Share): use select queries
* style: shared link table buttons
* localization and dark text styling
* style: fix clipboard button layout shift app-wide and add localization for copy code
* support assistants message content in shared links, add useCopyToClipboard, add copy buttons to Search Messages and Shared Link Messages
* add localizations
* comparisons
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
Co-authored-by: Fuegovic <32828263+fuegovic@users.noreply.github.com>
2024-05-17 18:13:32 -04:00
|
|
|
const { pageIndex, index } = findPageForConversation(data as ConversationData, {
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
conversationId: '2',
|
|
|
|
|
});
|
|
|
|
|
expect(pageIndex).toBe(0);
|
🚀 feat: Shared Links (#2772)
* ✨ feat(types): add necessary types for shared link feature
* ✨ feat: add shared links functions to data service
Added functions for retrieving, creating, updating, and deleting shared links and shared messages.
* ✨ feat: Add useGetSharedMessages hook to fetch shared messages by shareId
Adds a new hook `useGetSharedMessages` which fetches shared messages based on the provided shareId.
* ✨ feat: Add share schema and data access functions to API models
* ✨ feat: Add share endpoint to API
The GET /api/share/${shareId} is exposed to the public, so authentication is not required. Other paths require authentication.
* ♻️ refactor(utils): generalize react-query cache manipulation functions
Introduces generic functions for manipulating react-query cache entries, marking a refinement in how query cache data is managed. It aims to enhance the flexibility and reusability of the cache interaction patterns within our application.
- Replaced specific index names with more generic terms in queries.ts, enhancing consistency across data handling functions.
- Introduced new utility functions in collection.ts for adding, updating, and deleting data entries in an InfiniteData<TCollection>. These utility functions (`addData`, `updateData`, `deleteData`, `findPage`) are designed to be re-usable across different data types and collections.
- Adapted existing conversation utility functions in convos.ts to leverage these new generic utilities.
* ✨ feat(shared-link): add functions to manipulate shared link cache list
implemented new utility functions to handle additions, updates, and deletions in the shared link cache list.
* ✨ feat: Add mutations and queries for shared links
* ✨ feat(shared-link): add `Share` button to conversation list
- Added a share button in each conversation in the conversation list.
- Implemented functionality where clicking the share button triggers a POST request to the API.
- The API checks if a share link was already created for the conversation today; if so, it returns the existing link.
- If no link was created for today, the API will create a new share link and return it.
- Each click on the share button results in a new API request, following the specification similar to ChatGPT's share link feature.
* ♻️ refactor(hooks): generalize useNavScrolling for broader use
- Modified `useNavScrolling` to accept a generic type parameter `TData`, allowing it to be used with different data structures besides `ConversationListResponse`.
- Updated instances in `Nav.tsx` and `ArchivedChatsTable.tsx` to explicitly specify `ConversationListResponse` as the type argument when invoking `useNavScrolling`.
* ✨ feat(settings): add shared links listing table with delete functionality in settings
- Integrated a delete button for each shared link in the table, allowing users to remove links as needed.
* ♻️ refactor(components): separate `EndpointIcon` from `Icon` component for standalone use
* ♻️ refactor: update useGetSharedMessages to return TSharedLink
- Modified the useGetSharedMessages hook to return not only a list of TMessage but also the TSharedLink itself.
- This change was necessary to support displaying the title and date in the Shared Message UI, which requires data from TSharedLink.
* ✨ feat(shared link): add UI for displaying shared conversations without authentication
- Implemented a new UI component to display shared conversations, designed to be accessible without requiring authentication.
- Reused components from the authenticated Messages module where possible. Copied and adapted components that could not be directly reused to fit the non-authenticated context.
* 🔧 chore: Add translations
Translate labels only. Messages remain in English as they are possibly subject to change.
* ♻️ refactor: add icon and tooltip props to EditMenuButton component
* moved icon and popover to arguments so that EditMenuButton can be reused.
* modified so that when a ShareButton is closed, the parent DropdownMenu is also closed.
* ♻️irefactor: added DropdownMenu for Export and Share
* ♻️ refactor: renamed component names more intuitive
* More accurate naming of the dropdown menu.
* When the export button is closed, the parent dropdown menu is also closed.
* 🌍 chore: updated translations
* 🐞 Fix: OpenID Profile Image Download (#2757)
* Add fetch requirement
Fixes - error: [openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": TypeError: response.buffer is not a function
* Update openidStrategy.js
---------
Co-authored-by: Danny Avila <danacordially@gmail.com>
* 🚑 fix(export): Issue exporting Conversation with Assistants (#2769)
* 🚑 fix(export): use content as text if content is present in the message
If the endpoint is assistants, the text of the message goes into content, not message.text.
* refactor(ExportModel): TypeScript, remove unused code
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
* 📤style: export button icon (#2752)
* refactor(ShareDialog): logic and styling
* refactor(ExportAndShareMenu): imports order and icon update
* chore: imports
* chore: imports/render logic
* feat: message branching
* refactor: add optional config to useGetStartupConfig
* refactor: disable endpoints query
* chore: fix search view styling gradient in light mode
* style: ShareView gradient styling
* refactor(Share): use select queries
* style: shared link table buttons
* localization and dark text styling
* style: fix clipboard button layout shift app-wide and add localization for copy code
* support assistants message content in shared links, add useCopyToClipboard, add copy buttons to Search Messages and Shared Link Messages
* add localizations
* comparisons
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
Co-authored-by: Fuegovic <32828263+fuegovic@users.noreply.github.com>
2024-05-17 18:13:32 -04:00
|
|
|
expect(index).toBe(1);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Conversation Utilities with Fake Data', () => {
|
|
|
|
|
describe('groupConversationsByDate', () => {
|
|
|
|
|
it('correctly groups conversations from fake data by date', () => {
|
|
|
|
|
const { pages } = convoData;
|
|
|
|
|
const allConversations = pages.flatMap((p) => p.conversations);
|
|
|
|
|
const grouped = groupConversationsByDate(allConversations);
|
|
|
|
|
|
2024-02-11 08:46:14 -05:00
|
|
|
expect(grouped).toHaveLength(1);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
expect(grouped[0][1]).toBeInstanceOf(Array);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('addConversation', () => {
|
|
|
|
|
it('adds a new conversation to the existing fake data', () => {
|
|
|
|
|
const newConversation = {
|
2024-09-21 10:20:30 -04:00
|
|
|
conversationId: Constants.NEW_CONVO,
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
updatedAt: new Date().toISOString(),
|
|
|
|
|
} as TConversation;
|
|
|
|
|
const initialLength = convoData.pages[0].conversations.length;
|
|
|
|
|
const newData = addConversation(convoData, newConversation);
|
|
|
|
|
expect(newData.pages[0].conversations.length).toBe(initialLength + 1);
|
2024-09-21 10:20:30 -04:00
|
|
|
expect(newData.pages[0].conversations[0].conversationId).toBe(Constants.NEW_CONVO);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('updateConversation', () => {
|
|
|
|
|
it('updates an existing conversation within fake data', () => {
|
|
|
|
|
const updatedConversation = {
|
|
|
|
|
...convoData.pages[0].conversations[0],
|
|
|
|
|
title: 'Updated Title',
|
|
|
|
|
};
|
|
|
|
|
const newData = updateConversation(convoData, updatedConversation);
|
|
|
|
|
expect(newData.pages[0].conversations[0].title).toBe('Updated Title');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('updateConvoFields', () => {
|
|
|
|
|
it('updates specific fields of a conversation in fake data', () => {
|
|
|
|
|
const updatedFields = {
|
|
|
|
|
conversationId: convoData.pages[0].conversations[0].conversationId,
|
|
|
|
|
title: 'Partially Updated Title',
|
|
|
|
|
};
|
|
|
|
|
const newData = updateConvoFields(convoData, updatedFields as TConversation);
|
|
|
|
|
const updatedConversation = newData.pages[0].conversations.find(
|
|
|
|
|
(c) => c.conversationId === updatedFields.conversationId,
|
|
|
|
|
);
|
|
|
|
|
expect(updatedConversation?.title).toBe('Partially Updated Title');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('deleteConversation', () => {
|
|
|
|
|
it('removes a conversation by id from fake data', () => {
|
|
|
|
|
const conversationIdToDelete = convoData.pages[0].conversations[0].conversationId as string;
|
|
|
|
|
const newData = deleteConversation(convoData, conversationIdToDelete);
|
|
|
|
|
const deletedConvoExists = newData.pages[0].conversations.some(
|
|
|
|
|
(c) => c.conversationId === conversationIdToDelete,
|
|
|
|
|
);
|
|
|
|
|
expect(deletedConvoExists).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('findPageForConversation', () => {
|
|
|
|
|
it('finds the correct page and index for a given conversation in fake data', () => {
|
|
|
|
|
const targetConversation = convoData.pages[0].conversations[0];
|
🚀 feat: Shared Links (#2772)
* ✨ feat(types): add necessary types for shared link feature
* ✨ feat: add shared links functions to data service
Added functions for retrieving, creating, updating, and deleting shared links and shared messages.
* ✨ feat: Add useGetSharedMessages hook to fetch shared messages by shareId
Adds a new hook `useGetSharedMessages` which fetches shared messages based on the provided shareId.
* ✨ feat: Add share schema and data access functions to API models
* ✨ feat: Add share endpoint to API
The GET /api/share/${shareId} is exposed to the public, so authentication is not required. Other paths require authentication.
* ♻️ refactor(utils): generalize react-query cache manipulation functions
Introduces generic functions for manipulating react-query cache entries, marking a refinement in how query cache data is managed. It aims to enhance the flexibility and reusability of the cache interaction patterns within our application.
- Replaced specific index names with more generic terms in queries.ts, enhancing consistency across data handling functions.
- Introduced new utility functions in collection.ts for adding, updating, and deleting data entries in an InfiniteData<TCollection>. These utility functions (`addData`, `updateData`, `deleteData`, `findPage`) are designed to be re-usable across different data types and collections.
- Adapted existing conversation utility functions in convos.ts to leverage these new generic utilities.
* ✨ feat(shared-link): add functions to manipulate shared link cache list
implemented new utility functions to handle additions, updates, and deletions in the shared link cache list.
* ✨ feat: Add mutations and queries for shared links
* ✨ feat(shared-link): add `Share` button to conversation list
- Added a share button in each conversation in the conversation list.
- Implemented functionality where clicking the share button triggers a POST request to the API.
- The API checks if a share link was already created for the conversation today; if so, it returns the existing link.
- If no link was created for today, the API will create a new share link and return it.
- Each click on the share button results in a new API request, following the specification similar to ChatGPT's share link feature.
* ♻️ refactor(hooks): generalize useNavScrolling for broader use
- Modified `useNavScrolling` to accept a generic type parameter `TData`, allowing it to be used with different data structures besides `ConversationListResponse`.
- Updated instances in `Nav.tsx` and `ArchivedChatsTable.tsx` to explicitly specify `ConversationListResponse` as the type argument when invoking `useNavScrolling`.
* ✨ feat(settings): add shared links listing table with delete functionality in settings
- Integrated a delete button for each shared link in the table, allowing users to remove links as needed.
* ♻️ refactor(components): separate `EndpointIcon` from `Icon` component for standalone use
* ♻️ refactor: update useGetSharedMessages to return TSharedLink
- Modified the useGetSharedMessages hook to return not only a list of TMessage but also the TSharedLink itself.
- This change was necessary to support displaying the title and date in the Shared Message UI, which requires data from TSharedLink.
* ✨ feat(shared link): add UI for displaying shared conversations without authentication
- Implemented a new UI component to display shared conversations, designed to be accessible without requiring authentication.
- Reused components from the authenticated Messages module where possible. Copied and adapted components that could not be directly reused to fit the non-authenticated context.
* 🔧 chore: Add translations
Translate labels only. Messages remain in English as they are possibly subject to change.
* ♻️ refactor: add icon and tooltip props to EditMenuButton component
* moved icon and popover to arguments so that EditMenuButton can be reused.
* modified so that when a ShareButton is closed, the parent DropdownMenu is also closed.
* ♻️irefactor: added DropdownMenu for Export and Share
* ♻️ refactor: renamed component names more intuitive
* More accurate naming of the dropdown menu.
* When the export button is closed, the parent dropdown menu is also closed.
* 🌍 chore: updated translations
* 🐞 Fix: OpenID Profile Image Download (#2757)
* Add fetch requirement
Fixes - error: [openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": TypeError: response.buffer is not a function
* Update openidStrategy.js
---------
Co-authored-by: Danny Avila <danacordially@gmail.com>
* 🚑 fix(export): Issue exporting Conversation with Assistants (#2769)
* 🚑 fix(export): use content as text if content is present in the message
If the endpoint is assistants, the text of the message goes into content, not message.text.
* refactor(ExportModel): TypeScript, remove unused code
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
* 📤style: export button icon (#2752)
* refactor(ShareDialog): logic and styling
* refactor(ExportAndShareMenu): imports order and icon update
* chore: imports
* chore: imports/render logic
* feat: message branching
* refactor: add optional config to useGetStartupConfig
* refactor: disable endpoints query
* chore: fix search view styling gradient in light mode
* style: ShareView gradient styling
* refactor(Share): use select queries
* style: shared link table buttons
* localization and dark text styling
* style: fix clipboard button layout shift app-wide and add localization for copy code
* support assistants message content in shared links, add useCopyToClipboard, add copy buttons to Search Messages and Shared Link Messages
* add localizations
* comparisons
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
Co-authored-by: Fuegovic <32828263+fuegovic@users.noreply.github.com>
2024-05-17 18:13:32 -04:00
|
|
|
const { pageIndex, index } = findPageForConversation(convoData, {
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
conversationId: targetConversation.conversationId as string,
|
|
|
|
|
});
|
|
|
|
|
expect(pageIndex).toBeGreaterThanOrEqual(0);
|
🚀 feat: Shared Links (#2772)
* ✨ feat(types): add necessary types for shared link feature
* ✨ feat: add shared links functions to data service
Added functions for retrieving, creating, updating, and deleting shared links and shared messages.
* ✨ feat: Add useGetSharedMessages hook to fetch shared messages by shareId
Adds a new hook `useGetSharedMessages` which fetches shared messages based on the provided shareId.
* ✨ feat: Add share schema and data access functions to API models
* ✨ feat: Add share endpoint to API
The GET /api/share/${shareId} is exposed to the public, so authentication is not required. Other paths require authentication.
* ♻️ refactor(utils): generalize react-query cache manipulation functions
Introduces generic functions for manipulating react-query cache entries, marking a refinement in how query cache data is managed. It aims to enhance the flexibility and reusability of the cache interaction patterns within our application.
- Replaced specific index names with more generic terms in queries.ts, enhancing consistency across data handling functions.
- Introduced new utility functions in collection.ts for adding, updating, and deleting data entries in an InfiniteData<TCollection>. These utility functions (`addData`, `updateData`, `deleteData`, `findPage`) are designed to be re-usable across different data types and collections.
- Adapted existing conversation utility functions in convos.ts to leverage these new generic utilities.
* ✨ feat(shared-link): add functions to manipulate shared link cache list
implemented new utility functions to handle additions, updates, and deletions in the shared link cache list.
* ✨ feat: Add mutations and queries for shared links
* ✨ feat(shared-link): add `Share` button to conversation list
- Added a share button in each conversation in the conversation list.
- Implemented functionality where clicking the share button triggers a POST request to the API.
- The API checks if a share link was already created for the conversation today; if so, it returns the existing link.
- If no link was created for today, the API will create a new share link and return it.
- Each click on the share button results in a new API request, following the specification similar to ChatGPT's share link feature.
* ♻️ refactor(hooks): generalize useNavScrolling for broader use
- Modified `useNavScrolling` to accept a generic type parameter `TData`, allowing it to be used with different data structures besides `ConversationListResponse`.
- Updated instances in `Nav.tsx` and `ArchivedChatsTable.tsx` to explicitly specify `ConversationListResponse` as the type argument when invoking `useNavScrolling`.
* ✨ feat(settings): add shared links listing table with delete functionality in settings
- Integrated a delete button for each shared link in the table, allowing users to remove links as needed.
* ♻️ refactor(components): separate `EndpointIcon` from `Icon` component for standalone use
* ♻️ refactor: update useGetSharedMessages to return TSharedLink
- Modified the useGetSharedMessages hook to return not only a list of TMessage but also the TSharedLink itself.
- This change was necessary to support displaying the title and date in the Shared Message UI, which requires data from TSharedLink.
* ✨ feat(shared link): add UI for displaying shared conversations without authentication
- Implemented a new UI component to display shared conversations, designed to be accessible without requiring authentication.
- Reused components from the authenticated Messages module where possible. Copied and adapted components that could not be directly reused to fit the non-authenticated context.
* 🔧 chore: Add translations
Translate labels only. Messages remain in English as they are possibly subject to change.
* ♻️ refactor: add icon and tooltip props to EditMenuButton component
* moved icon and popover to arguments so that EditMenuButton can be reused.
* modified so that when a ShareButton is closed, the parent DropdownMenu is also closed.
* ♻️irefactor: added DropdownMenu for Export and Share
* ♻️ refactor: renamed component names more intuitive
* More accurate naming of the dropdown menu.
* When the export button is closed, the parent dropdown menu is also closed.
* 🌍 chore: updated translations
* 🐞 Fix: OpenID Profile Image Download (#2757)
* Add fetch requirement
Fixes - error: [openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": TypeError: response.buffer is not a function
* Update openidStrategy.js
---------
Co-authored-by: Danny Avila <danacordially@gmail.com>
* 🚑 fix(export): Issue exporting Conversation with Assistants (#2769)
* 🚑 fix(export): use content as text if content is present in the message
If the endpoint is assistants, the text of the message goes into content, not message.text.
* refactor(ExportModel): TypeScript, remove unused code
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
* 📤style: export button icon (#2752)
* refactor(ShareDialog): logic and styling
* refactor(ExportAndShareMenu): imports order and icon update
* chore: imports
* chore: imports/render logic
* feat: message branching
* refactor: add optional config to useGetStartupConfig
* refactor: disable endpoints query
* chore: fix search view styling gradient in light mode
* style: ShareView gradient styling
* refactor(Share): use select queries
* style: shared link table buttons
* localization and dark text styling
* style: fix clipboard button layout shift app-wide and add localization for copy code
* support assistants message content in shared links, add useCopyToClipboard, add copy buttons to Search Messages and Shared Link Messages
* add localizations
* comparisons
---------
Co-authored-by: Yuichi Ohneda <ohneda@gmail.com>
Co-authored-by: bsu3338 <bsu3338@users.noreply.github.com>
Co-authored-by: Fuegovic <32828263+fuegovic@users.noreply.github.com>
2024-05-17 18:13:32 -04:00
|
|
|
expect(index).toBeGreaterThanOrEqual(0);
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|
|
|
|
|
});
|
2024-05-24 09:38:38 -07:00
|
|
|
|
|
|
|
|
describe('normalizeConversationData', () => {
|
|
|
|
|
it('normalizes the number of items on each page after data removal', () => {
|
|
|
|
|
// Create test data:
|
|
|
|
|
// Generates 15 conversation items, each with a unique conversationId and an updatedAt timestamp set to a different day.
|
|
|
|
|
// { conversationId: '1', updatedAt: new Date(Date.now() - 86400000 * i).toISOString() }
|
|
|
|
|
const conversations = Array.from({ length: 15 }, (_, i) => ({
|
|
|
|
|
conversationId: (i + 1).toString(),
|
|
|
|
|
updatedAt: new Date(Date.now() - 86400000 * i).toISOString(),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Paginate Data:
|
|
|
|
|
// Divides the 15 conversation items into pages, with each page containing up to 5 items (pageSize is set to 5). This results in 3 pages.
|
|
|
|
|
const pageSize = 5;
|
|
|
|
|
const totalPageNumber = Math.ceil(conversations.length / pageSize);
|
|
|
|
|
|
|
|
|
|
const paginatedData = Array.from({ length: totalPageNumber }, (_, index) => ({
|
|
|
|
|
conversations: conversations.slice(index * pageSize, (index + 1) * pageSize),
|
|
|
|
|
pages: totalPageNumber,
|
|
|
|
|
pageNumber: index + 1,
|
|
|
|
|
pageSize,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const testData = { pages: paginatedData, pageParams: [null, 2, 3] };
|
|
|
|
|
|
|
|
|
|
// Removes one item from the first page, resulting in the first page having 4 items, while the second and third pages still have 5 items each.
|
|
|
|
|
testData.pages[0].conversations.splice(1, 1);
|
|
|
|
|
expect(testData.pages[0].conversations).toHaveLength(4);
|
|
|
|
|
expect(testData.pages[1].conversations).toHaveLength(5);
|
|
|
|
|
expect(testData.pages[2].conversations).toHaveLength(5);
|
|
|
|
|
|
|
|
|
|
// Normalize Data:
|
|
|
|
|
// Calls the normalizeData function to ensure that each page contains exactly 5 items, redistributing the items across the pages as needed.
|
|
|
|
|
const normalizedData = normalizeData(testData, 'conversations', pageSize);
|
|
|
|
|
|
|
|
|
|
// Verify Results:
|
|
|
|
|
// Asserts that the number of conversation data is 5 except for the last page,
|
|
|
|
|
// that the number of conversation data is 4 only for the last page,
|
|
|
|
|
// and that the conversation ids are in the expected order.
|
|
|
|
|
expect(normalizedData.pages[0].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pages[0].conversations[0].conversationId).toBe('1');
|
|
|
|
|
expect(normalizedData.pages[0].conversations[4].conversationId).toBe('6');
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[1].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pages[1].conversations[0].conversationId).toBe('7');
|
|
|
|
|
expect(normalizedData.pages[1].conversations[4].conversationId).toBe('11');
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[2].conversations).toHaveLength(4);
|
|
|
|
|
expect(normalizedData.pages[2].conversations[0].conversationId).toBe('12');
|
|
|
|
|
expect(normalizedData.pages[2].conversations[3].conversationId).toBe('15');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('normalizes the number of items on each page after data addition', () => {
|
|
|
|
|
// Create test data:
|
|
|
|
|
// Generates 15 conversation items, each with a unique conversationId and an updatedAt timestamp set to a different day.
|
|
|
|
|
// { conversationId: '1', updatedAt: new Date(Date.now() - 86400000 * i).toISOString() }
|
|
|
|
|
const conversations = Array.from({ length: 15 }, (_, i) => ({
|
|
|
|
|
conversationId: (i + 1).toString(),
|
|
|
|
|
updatedAt: new Date(Date.now() - 86400000 * i).toISOString(),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Paginate Data:
|
|
|
|
|
// Divides the 15 conversation items into pages,
|
|
|
|
|
// with each page containing up to 5 items (pageSize is set to 5). This results in 3 pages.
|
|
|
|
|
const pageSize = 5;
|
|
|
|
|
const totalPageNumber = Math.ceil(conversations.length / pageSize);
|
|
|
|
|
|
|
|
|
|
const paginatedData = Array.from({ length: totalPageNumber }, (_, index) => ({
|
|
|
|
|
conversations: conversations.slice(index * pageSize, (index + 1) * pageSize),
|
|
|
|
|
pages: totalPageNumber,
|
|
|
|
|
pageNumber: index + 1,
|
|
|
|
|
pageSize,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const testData = { pages: paginatedData, pageParams: [null, 2, 3] };
|
|
|
|
|
|
|
|
|
|
// Inserts a new conversation item at the beginning of the first page,
|
|
|
|
|
testData.pages[0].conversations.unshift({
|
|
|
|
|
conversationId: '16',
|
|
|
|
|
updatedAt: new Date().toISOString(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// resulting in the first page having 6 items,
|
|
|
|
|
// while the second and third pages still have 5 items each.
|
|
|
|
|
expect(testData.pages[0].conversations).toHaveLength(6);
|
|
|
|
|
expect(testData.pages[1].conversations).toHaveLength(5);
|
|
|
|
|
expect(testData.pages[2].conversations).toHaveLength(5);
|
|
|
|
|
expect(testData.pages[2].conversations[4].conversationId).toBe('15');
|
|
|
|
|
expect(testData.pages).toHaveLength(3);
|
|
|
|
|
|
|
|
|
|
const normalizedData = normalizeData(testData, 'conversations', pageSize);
|
|
|
|
|
|
|
|
|
|
// Verify Results:
|
|
|
|
|
// Asserts that after normalization, each page contains the correct number of items (5 items per page).
|
|
|
|
|
expect(normalizedData.pages[0].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pages[1].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pages[2].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pages).toHaveLength(3);
|
|
|
|
|
|
|
|
|
|
// Checks that the items are in the expected order, ensuring that the conversationId values are correctly distributed across the pages.
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[0].conversations[0].conversationId).toBe('16');
|
|
|
|
|
expect(normalizedData.pages[0].conversations[4].conversationId).toBe('4');
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[1].conversations[0].conversationId).toBe('5');
|
|
|
|
|
expect(normalizedData.pages[1].conversations[4].conversationId).toBe('9');
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[2].conversations[0].conversationId).toBe('10');
|
|
|
|
|
expect(normalizedData.pages[2].conversations[4].conversationId).toBe('14');
|
|
|
|
|
expect(normalizedData.pageParams).toHaveLength(3);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('returns empty data when there is no data', () => {
|
|
|
|
|
const normalizedData = normalizeData(
|
|
|
|
|
{ pages: [{ conversations: [], pageNumber: 1, pageSize: 5, pages: 1 }], pageParams: [] },
|
|
|
|
|
'conversations',
|
|
|
|
|
5,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.log(normalizedData);
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[0].conversations).toHaveLength(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('does not normalize data when not needed', () => {
|
|
|
|
|
const normalizedData = normalizeData(
|
|
|
|
|
{ pages: [{ conversations: ['1'], pageNumber: 1, pageSize: 5, pages: 1 }], pageParams: [] },
|
|
|
|
|
'conversations',
|
|
|
|
|
5,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(normalizedData.pages[0].conversations).toHaveLength(1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('deletes pages that have no data as a result of normalization', () => {
|
|
|
|
|
const conversations = Array.from({ length: 15 }, (_, i) => ({
|
|
|
|
|
conversationId: (i + 1).toString(),
|
|
|
|
|
updatedAt: new Date(Date.now() - 86400000 * i).toISOString(),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const pageSize = 5;
|
|
|
|
|
const totalPageNumber = Math.ceil(conversations.length / pageSize);
|
|
|
|
|
|
|
|
|
|
const paginatedData = Array.from({ length: totalPageNumber }, (_, index) => ({
|
|
|
|
|
conversations: conversations.slice(index * pageSize, (index + 1) * pageSize),
|
|
|
|
|
pages: totalPageNumber,
|
|
|
|
|
pageNumber: index + 1,
|
|
|
|
|
pageSize,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const testData = { pages: paginatedData, pageParams: [null, 2, 3] };
|
|
|
|
|
|
|
|
|
|
// Removes all data from the last page, resulting in the last page having 0 items.
|
|
|
|
|
testData.pages[2].conversations = [];
|
|
|
|
|
expect(testData.pages[0].conversations).toHaveLength(5);
|
|
|
|
|
expect(testData.pages[1].conversations).toHaveLength(5);
|
|
|
|
|
expect(testData.pages[2].conversations).toHaveLength(0);
|
|
|
|
|
expect(testData.pageParams).toHaveLength(3);
|
|
|
|
|
|
|
|
|
|
const normalizedData = normalizeData(testData, 'conversations', pageSize);
|
|
|
|
|
|
|
|
|
|
// Verify Results:
|
|
|
|
|
// Asserts that the last page is removed after normalization, leaving only the first and second pages.
|
|
|
|
|
expect(normalizedData.pages).toHaveLength(2);
|
|
|
|
|
expect(normalizedData.pages[0].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pages[1].conversations).toHaveLength(5);
|
|
|
|
|
expect(normalizedData.pageParams).toHaveLength(2);
|
|
|
|
|
});
|
|
|
|
|
});
|
♾️ style: Infinite Scroll Nav and Sort Convos by Date/Usage (#1708)
* Style: Infinite Scroll and Group convos by date
* Style: Infinite Scroll and Group convos by date- Redesign NavBar
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Clean code
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Style: Infinite Scroll and Group convos by date- Redesign NavBar - Redesign NewChat Component
* Including OpenRouter and Mistral icon
* refactor(Conversations): cleanup use of utility functions and typing
* refactor(Nav/NewChat): use localStorage `lastConversationSetup` to determine the endpoint to use, as well as icons -> JSX components, remove use of `endpointSelected`
* refactor: remove use of `isFirstToday`
* refactor(Nav): remove use of `endpointSelected`, consolidate scrolling logic to its own hook `useNavScrolling`, remove use of recoil `conversation`
* refactor: Add spinner to bottom of list, throttle fetching, move query hooks to client workspace
* chore: sort by `updatedAt` field
* refactor: optimize conversation infinite query, use optimistic updates, add conversation helpers for managing pagination, remove unnecessary operations
* feat: gen_title route for generating the title for the conversation
* style(Convo): change hover bg-color
* refactor: memoize groupedConversations and return as array of tuples, correctly update convos pre/post message stream, only call genTitle if conversation is new, make `addConversation` dynamically either add/update depending if convo exists in pages already, reorganize type definitions
* style: rename Header NewChat Button -> HeaderNewChat, add NewChatIcon, closely match main Nav New Chat button to ChatGPT
* style(NewChat): add hover bg color
* style: cleanup comments, match ChatGPT nav styling, redesign search bar, make part of new chat sticky header, move Nav under same parent as outlet/mobilenav, remove legacy code, search only if searchQuery is not empty
* feat: add tests for conversation helpers and ensure no duplicate conversations are ever grouped
* style: hover bg-color
* feat: alt-click on convo item to open conversation in new tab
* chore: send error message when `gen_title` fails
---------
Co-authored-by: Walber Cardoso <walbercardoso@gmail.com>
2024-02-03 20:25:35 -05:00
|
|
|
});
|