Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀feat: Archive conversations #2590

Merged
merged 23 commits into from May 7, 2024

Conversation

ohneda
Copy link
Contributor

@ohneda ohneda commented May 1, 2024

Summary

This Pull Request introduces an archiving feature for conversations, similar to the ChatGPT's archiving functionality.

SCR-20240430-rrej

Changes made:

  • Changed the "Rename" and "Delete" buttons to be in a dropdown menu.
  • Added an "Archive" button.
  • Added a new section, "Archived Chats," under Settings -> General, where users can manage archived conversations.
  • Archived conversations can be restored.
  • Did not include the “Archive all” feature available in ChatGPT. I may consider adding it based on feedback after this PR is merged.

Key modifications include:

  • Introduced a new query key archivedConversations for archived conversations management.
  • Originally planned to reuse useUpdateConversationMutation, but due to different post-request handling, I opted to create useArchiveConversationMutation.
  • Addressed a tooltip display issue:
    • Fixed a bug where tooltips were not displayed on Dialog du to the z-index of DialogPrimitive.Portal being set to 999. Adjusted the tooltip’s z-index to 1000 to solve this issue. Please revert if the adjustment creates any discrepancies.
  • Internationalization:
    • Added the necessary keys and values for new features in multiple languages, mostly translated automatically by Copilot. I performed partial verifications using Google Translate but further validation might be needed.

Known Issue:

  • Including archived conversations in search results
    • The implementation details around excluding archived conversations from search results have not been examined yet, but it should be feasible to adjust this upon request.

Change Type

Please delete any irrelevant options.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Translation update
  • Documentation update

Testing

While I have not written unit tests for these changes, I have verified the following functionalities manually:

  • An "Archive" button has been added to the conversation list in the navigation.
  • Clicking the "Archive" button archives the conversation and removes it from the conversation list.
  • The "Rename" and "Delete" buttons, now in a dropdown, function correctly.
  • Added a section titled "Archived Chats" under Settings -> General.
  • Clicking the "Manage" button under "Archived Chats" displays a list of archived conversations.
  • If there are no archived conversations, the message "You have no archived conversations." is displayed.
  • Initially displays the first 25 archived conversations.
  • More conversations are paginated in increments of 25 upon scrolling.
  • Each archived conversation in the list has an "Unarchive" and a "Delete" button on the right, with tooltips displayed on mouseover.
  • Clicking the "Unarchive" button removes the conversation from the archived list and adds it back to the conversation list.
  • Clicking the "Delete" button prompts a confirmation dialog before deletion.
  • Archiving a conversation adds an isArchived: true property to the conversation document in mongodb.
  • If the isArchived property is absent, it defaults to isArchived: false (ensuring backward compatibility).

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • I have made pertinent documentation changes
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes
  • Any changes dependent on mine have been merged and published in downstream modules.
  • New documents have been locally validated with mkdocs

This commit adds a new mutation function `useArchiveConversationMutation()` for archiving conversations. This function takes the ID string of the conversation to be archived and returns a mutation result object. Upon successful archiving, it removes and refreshes the conversation from the query data cache.
While ChatGPT PATCHes the archived status by sending `{is_archived: true}` to the URL `/backend-api/conversation/$conversation_id`, this implementation uses the `dataService.updateConversation(payload)` with a POST method, aligning with the existing code conventions.
…getConvosByPage method

This commit adds a new field `is_archived` with a default value of false to the Conversation schema. It also modifies the `getConvosByPage` method within the Conversation API to adjust the query to only target conversations where `is_archived` is set to false or where the `is_archived` field does not exist. The function `getConvosQueried`, which returns conversations for a specified Conversation ID, was determined not to require consideration of whether `is_archived` is true or false, and thus was not modified.
To enhance the versatility of the DotsIcon component, this commit introduces the ability to specify a className prop, allowing for greater customization.
…lete buttons

Added a new Edit Button to the conversations, similar to the ChatGPT UI, which groups options for editing the conversation title and deleting conversations. This grouping is accessible through a dialogue that appears when the three-dot icon is clicked.
…options

Enhanced the Delete Button component to accept a `className` for customization and an optional `appendLabel`. The DeleteButton component is used by both `Convo.tsx` and `Conversation.tsx`, but currently only `Convo.tsx` is active and `Conversation.tsx `is apparently not used; removing `Conversation.tsx` may eliminate the need for the `appendLabel` property in the future.
Added the ability to optionally display labels; the Rename Button component is used by both `Convo.tsx` and `Conversation.tsx`, but currently only `Convo.tsx` is active and `Conversation.tsx `is apparently not used; removing `Conversation.tsx` may eliminate the need for the `appendLabel` property in the future.
* Refactor the is_archived property of conversation to camelCase (isArchived) to adhere to the existing code conventions
* Modify the function that retrieves conversations to accept the isArchived parameter
I thought I could divert dataService.updateConversation, but added a new archiveConversation because the request types are different. It might be better to make them common, but to avoid side effects, I added a new function this time.
Added process to deleteConversationMutation to delete archived conversations
…mponent

The Cancel button is not needed when displaying the archive list, so I made the Cancel button optional.
…component

This commit modifies the Nav component to add the ability to filter out archived conversations when fetching data. This is done by adding `isArchived: false` to the query parameters for both the `useConversationsInfiniteQuery()` and `useSearchInfiniteQuery()` hooks, effectively excluding any archived conversations from the results returned.
* Add Tooltip to DeleteButton component
* Display Tooltip when DeleteButton only shows an Icon without text
To be compatible with the ChatGPT UI, no confirmation dialog is displayed when ArchiveButton is clicked. The basic behavior conforms to DeleteButton and RenameButton.
Modify the Nav of the conversation list to include a dropdown that contains the Rename and Delete options, similar to the ChatGPT UI. Additionally, an Archive button has been added adjacent to the dropdown menu.
Adds the `ArchivedChatsTable` component, which displays a table of archived chats. It has been implemented to be as compatible with the ChatGPT UI as possible.
Resolve an issue where tooltips were not visible when displayed over a Dialog. The z-index of `DialogPrimitive.Portal` in `Dialog.tsx` is set to 999. Since the rationale for this value is unclear, the z-index of the tooltip has been increased to 1000 to guarantee its visibility above the Dialog component.
@danny-avila
Copy link
Owner

Thanks so much for this, awesome job! Looks very clean and thank you for using existing infinite query and adding all the localizations. Played around with it a bit, I think this is a good way to introduce the feature, and then later improve it

@danny-avila
Copy link
Owner

@ohneda When I get a chance, I will see if I can easily add time-to-live (TTL) expiry to the archived documents, while also allowing removing that expiry if unarchived, before merging or shortly after merging this. It would be helpful if you can look into this as well!

See how I do this for files here:
Adding:

/**
* Creates a new file with a TTL of 1 hour.
* @param {MongoFile} data - The file data to be created, must contain file_id.
* @param {boolean} disableTTL - Whether to disable the TTL.
* @returns {Promise<MongoFile>} A promise that resolves to the created file document.
*/
const createFile = async (data, disableTTL) => {
const fileData = {
...data,
expiresAt: new Date(Date.now() + 3600 * 1000),
};
if (disableTTL) {
delete fileData.expiresAt;
}
return await File.findOneAndUpdate({ file_id: data.file_id }, fileData, {
new: true,
upsert: true,
}).lean();
};

Removing:

/**
* Updates a file identified by file_id with new data and removes the TTL.
* @param {MongoFile} data - The data to update, must contain file_id.
* @returns {Promise<MongoFile>} A promise that resolves to the updated file document.
*/
const updateFile = async (data) => {
const { file_id, ...update } = data;
const updateOperation = {
$set: update,
$unset: { expiresAt: '' }, // Remove the expiresAt field to prevent TTL
};
return await File.findOneAndUpdate({ file_id }, updateOperation, { new: true }).lean();
};

@ohneda
Copy link
Contributor Author

ohneda commented May 6, 2024

@danny-avila Yes, I think that's possible. Just to confirm, are you suggesting that archived conversations have a set expiration date, after which they cannot be accessed anymore? For example, if the expiration is set to one month, any conversation archived for one month would automatically be removed from the archive list, correct?

@danny-avila
Copy link
Owner

@danny-avila Yes, I think that's possible. Just to confirm, are you suggesting that archived conversations have a set expiration date, after which they cannot be accessed anymore? For example, if the expiration is set to one month, any conversation archived for one month would automatically be removed from the archive list, correct?

Yup, they would be deleted but on second thought, maybe this isn't what's desired via archiving, after re-reading how it works for ChatGPT: https://help.openai.com/en/articles/8809935-how-chat-retention-works-in-chatgpt

Scratch that thought, I just thought it would be a good way to introduce some simple retention.

Don't worry about my earlier comment, I'll merge this after the conflicts are resolved, thanks for your work on this!

@danny-avila danny-avila merged commit 89b1e33 into danny-avila:main May 7, 2024
2 checks passed
@ohneda ohneda deleted the feature/archive-conversations branch May 17, 2024 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants