[Aichat] Fetch student chat history and display in workspace - #60322
#60322[Aichat] Fetch student chat history and display in workspace#60322fisher-alice merged 19 commits intostagingcode-dot-org/code-dot-org:stagingfrom alice/frontend-student-chat-historycode-dot-org/code-dot-org:alice/frontend-student-chat-historyCopy head branch name to clipboard
Conversation
| ChatMessage, | ||
| ChatEvent, | ||
| ChatMessage, | ||
| LogChatEventApiResponse, |
| assert_response :forbidden | ||
| end | ||
|
|
||
| test 'student_chat_history successfully returns list of student aichat_events' do |
thomasoniii
left a comment
There was a problem hiding this comment.
couple of tiny structural suggestions, but overall lgtm 🚀
sanchitmalhotra126
left a comment
There was a problem hiding this comment.
So cool to see the history coming back from the server!
A few minor comments and refactor suggestion but the approach looks right to me.
| events: ChatEvent[]; | ||
| } | ||
|
|
||
| const StudentChatHistoryView: React.FunctionComponent< |
There was a problem hiding this comment.
Alright, another refactoring suggestion 😅 this is coming out of a couple things I noticed:
StudentChatHistoryViewandChatWithModelare almost identical (other than addingisTeacherViewto the events in the former)- Relatedly, it seems like we need
isTeacherViewto override the check forhideForParticipantsinChatEventView - Looking at this again, I'm also wondering if the student's chat history even needs to be in Redux if it's only going to be used and updated in one place (whichever component renders the history).
So, here's a potential suggestion to hopefully make things easier to follow:
- Remove the check for
hideForParticipantsinChatEventView.ChatEventViewsimply renders the givenChatEvent. - Create a component like
<ChatWithModel>that simply renders a list ofChatEvents in a container. This can just replaceChatWithModelor even replaceChatEventView(i.e. turnChatEventViewinto someChatEventsListthat renders a list ofChatEvents in adivcontainer). We can also move autoscroll logic to this container so the student chat history gets it for free. - We can then have a separate component for Student Chat History that 1) fetches and stores (in state) the list of chat event history from the server on mount or whenever dependencies change (level ID, channel ID, user ID, etc) and 2) uses the above component to render the list of returned
ChatEvent. No need to add a separateisTeacherViewflag sinceChatItemViewwill just render whatever is handed to it - To display the current user's chat with the model, get the list of user events from redux and filter out anything with
hideForParticipants: true. Use the above<ChatEventsList>component to render this filtered list of events.
My thinking is that this would result in less conditional logic, more reused components, and a bit of separation between the actual items in the student chat history and the items in the current chat with the model.
There was a problem hiding this comment.
Thanks Sanchit!
I made the following updates based on your suggestions above:
- Removed the internal
StudentChatHistoryViewandChatWithModelcomponents. - Added
ChatEventsListcomponent that is used to display the teacher view of student chat history and the visible chat events. - Removed
isTeacherViewfor now - see [Aichat] Fetch student chat history and display in workspace #60322 (comment) - Changed name of selector
selectAllMessagestoselectAllVisibleMessagesand then removed condition to check forhideForParticipants - Kept
studentChatHistorystored in redux because of some of the complex logic (checking if sublevel) and the async call, and already checking student list for selected student name in Teacher panel. (discussed this offline).
| delete: deleteRequest, | ||
| fetchJson, | ||
| post, | ||
| put, |
sanchitmalhotra126
left a comment
There was a problem hiding this comment.
LGTM!
One question on the screen recordings - it looks like the notification events in the history view have a close button. Does this mean they're dismissible?
|
|
||
| interface ChatEventsListProps { | ||
| events: ChatEvent[]; | ||
| showWaitingAnimation: () => React.ReactNode; |
There was a problem hiding this comment.
Not your change, but passing a function instead of a boolean here reads a little weird to me (maybe because previously it was an internal function?). Not necessary for this PR, but maybe we could change this to a showWaitingAnimation: boolean and have this component render the appropriate waiting image if true?
There was a problem hiding this comment.
Oh yeah - I agree a boolean would be expected here. I'll update in follow-up!
Great question! Interestingly, they're not dismissible. Looking into why they're not able to be dismissed, when the user clicks on the 'x' button, Do you have any ideas on why FYI - in the follow-up, I'll remove the 'x' close buttons. |
| } | ||
| return null; | ||
| }, [viewAsUserId, students]); | ||
| }, [viewAsUserId, students, dispatch, currentLevelId]); |
There was a problem hiding this comment.
FYI - added currentLevelId so that student chat history is updated when level changes (after pr approval) cc: @sanchitmalhotra126
| end | ||
|
|
||
| aichat_events = AichatEvent.where(user_id: student_user_id, level_id: level_id, script_id: script_id).order(created_at: :desc).pluck(:aichat_event) | ||
| aichat_events = AichatEvent.where(user_id: student_user_id, level_id: level_id, script_id: script_id).order(:created_at).pluck(:aichat_event).map do |event| |
There was a problem hiding this comment.
Want the oldest event to be first, not last since student chat history lists events from oldest to most recent.
This PR adds the frontend api call to fetch student chat history and follows up #60256 which added the backend controller action. It also displays the teacher view of student chat history in the aichat workspace.
Note that UI improvements/updates (auto-scroll to last message, ability to show/hide profane user messages, ...) will be taken care of in a follow-up PR.
Reminder that the teacher view of the student chat is hidden behind an experiment flag:
'?enableExperiments=view_chat_history'.
After update
Screencast video of teacher view of section with 3 students at '/s/allthethings/lessons/47/levels/1':
Screen.Recording.2024-08-12.at.9.07.56.AM.mov
Screencast video of teacher view of section with 3 students on a sublevel at '/s/allthethings/lessons/52/levels/8/sublevel/1':
Screen.Recording.2024-08-12.at.9.09.15.AM.mov
Note that for
chatEvents that have propertyhideForParticipantsset totrue(e.g., 'The user clears the chat workspace'), these events are NOT visible in the workspace. However, when a teacher is viewing the student chat history, the propertyisTeacherViewis set totrueso that thesechatEvents are visible in the workspace.Teacher view of student chat history:
Screencast video of user as participant - chat events are not shown if
hideForParticipantsis set totrue(e.g., 'The user clears the chat workspace.', 'The user loads the aichat level.').Screen.Recording.2024-08-12.at.9.13.44.AM.mov
Links
jira
Testing story
Added a dashboard unit test for checking that expected chat events returned by the
student_chat_historyendpoint.Tested locally on aichat levels in /allthethings including the aichat sublevel at '/s/allthethings/lessons/52/levels/8/sublevel/1'
Deployment strategy
Follow-up work
UI updates to teacher view of student chat history jira.
Privacy
Security
Caching
PR Checklist: