Skip to content

Thread options#135

Merged
BiancaWentzel merged 8 commits intomainfrom
thread-options
Jan 28, 2026
Merged

Thread options#135
BiancaWentzel merged 8 commits intomainfrom
thread-options

Conversation

@BiancaWentzel
Copy link
Copy Markdown
Contributor

Added option menu to threads history.
Now each thread can be renamed or deleted.

I didn't really managed to find a clean/general solution to multiple options without touching the whole list implementation. Maybe I have to have a deeper look into it in the future.

Expected behavior:

  • on hovering a thread in the thread history a menu icon appears
  • when clicking on icon a popover appears presenting two options: "Rename" and "Delete"
  • on clicking one oft the options, the popover closes and a modal appears presenting a message (either deleting or editing the topic)
  • on accepting via the modal a request to the backend is made (renaming or deleting the thread)
  • on successful request the thread will be renamed or removed from the thread history shown
  • a message toast appears stating the success or fail of the action

Note: On deletion of a thread react complains rightfully about a state update on an unmounted component (due to deleting thread from list). @Karinon do you have an idea how I could prevent this?

@BiancaWentzel BiancaWentzel requested a review from Karinon January 8, 2026 15:16
Base automatically changed from python-gpt to main January 13, 2026 10:01
Copy link
Copy Markdown
Contributor

@tropicrainforest tropicrainforest left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While reviewing this PR, I noticed three related issues. Only the first one is directly related to the current PR; the other two are observations/suggestions for follow-up.

  1. When the user is viewing a thread and deletes that same thread, the UI currently stays on a page that no longer exists. Ideally, the user should be redirected to a safe location (for example, the “new chat” page as OpenAI is doing the same) instead of remaining on the deleted thread. The proposed solution and implementation details are explained in the review comments.

  2. When opening the History side panel, the main chatbit page content shifts slightly to the left. This appears to be caused by scroll locking on the body. Enabling scrolling on the Offcanvas component seems to prevent this shift:

    <Offcanvas show={showThreadHistory} onHide={setShowThreadHistory} scroll>

    https://github.com/freva-org/freva-web/blob/thread-options/assets/js/Containers/FrevaGPT/components/SidePanel/SidePanel.js#L76

  3. If a thread is deleted or the user manually enters an invalid thread_id in the URL, the page currently renders empty with no feedback. This can be confusing.

    A better UX would be either:

    • Redirecting the user to the new chat page along with a red toast, or
    • Showing a clear warning that the thread does not exist (or both).

    For example, a simple inline warning could be rendered like this:

    const rearrangedConversation = useMemo(() => {
      return rearrangeCodeElements(conversation);
    }, [conversation]);
    const threadId = new URLSearchParams(window.location.search).get("thread_id");
    if (threadId && !rearrangedConversation.length) {
      return (
        <div className="text-center text-muted mt-5">
          <h5>This chat does not exist</h5>
          <p>It may have been deleted or you don’t have access.</p>
        </div>
      );
    }

    https://github.com/freva-org/freva-web/blob/thread-options/assets/js/Containers/FrevaGPT/components/ChatBlock.js#L58-L60

    Alternatively, this could be implemented as a toast notification (e.g. a red warning toast) followed by navigation to the new chat page.

Also there is another issue that when you are on an non-existing thread you would get TypeError: Invalid attempt to iterate non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method. on console. it seems via evaluating the conversation on the rearrangedConversation here you can get rid of this.

const rearrangedConversation = useMemo(() => {
  if (!Array.isArray(conversation)) {
    return [];
  }
  return rearrangeCodeElements(conversation);
}, [conversation]);

if (response.ok) {
toastColor.current = "success";
toastMessage.current = "Deleted chat.";
updateThreadList(mode, element);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here, when we remove one thread, it still shows the content of the removed thread and stays on the removed thread. To keep it clear, how about to force to go to the new message page as soon as it's removed. as same as what OpenAI does.

Suggested change
updateThreadList(mode, element);
updateThreadList(mode, element);
window.location.assign("/chatbot/");

@BiancaWentzel
Copy link
Copy Markdown
Contributor Author

Hi @mo-dkrz
Regarding point 3. The frontend is handling an invalid thread_id (see https://github.com/freva-org/freva-web/blob/main/assets/js/Containers/FrevaGPT/index.js#L102).
Currently the backend responds with a 200 which then surpasses the test. I requested a change.

Copy link
Copy Markdown
Contributor

@tropicrainforest tropicrainforest left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor not directly relevant comment and then LGTM!

when i create a new message and then press on history, I don't get the current thread on the history side panel. It seems, we can fetch the backend each time on panel open to have an updated history.

here https://github.com/freva-org/freva-web/blob/thread-options/assets/js/Containers/FrevaGPT/customHooks/useGeneralThreads.js if we first Pass showThreadHistory prop to the hook from useGeneralThreads in SidePanel and then add this useEffect, it should fetch:

export default function useGeneralThreads(showThreadHistory) {

useEffect(() => {
  if (showThreadHistory) {
    setPageNumber(0);
    handleThreadsRequest(0, undefined, setThreadsLoading, setThreads, setHasMore);
  }
}, [showThreadHistory]);

@BiancaWentzel
Copy link
Copy Markdown
Contributor Author

One minor not directly relevant comment and then LGTM!

when i create a new message and then press on history, I don't get the current thread on the history side panel. It seems, we can fetch the backend each time on panel open to have an updated history.

here https://github.com/freva-org/freva-web/blob/thread-options/assets/js/Containers/FrevaGPT/customHooks/useGeneralThreads.js if we first Pass showThreadHistory prop to the hook from useGeneralThreads in SidePanel and then add this useEffect, it should fetch:

export default function useGeneralThreads(showThreadHistory) {

useEffect(() => {
  if (showThreadHistory) {
    setPageNumber(0);
    handleThreadsRequest(0, undefined, setThreadsLoading, setThreads, setHasMore);
  }
}, [showThreadHistory]);

I would put this into a new issue since this isn't a trivial task. I have to think about how to handle a filtered thread list as well as multi-page lists.
See issue: #140

@BiancaWentzel BiancaWentzel merged commit 5e68ee6 into main Jan 28, 2026
7 of 8 checks passed
@BiancaWentzel BiancaWentzel deleted the thread-options branch January 28, 2026 09:27
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.

2 participants