So that admins and drivers can coordinate with one another without needing a separate app
Discussion
Currently, the drivers use a group chat to coordinate their activities.
Moving that group chat into the app is a good way to provide a way for coordination to happen while the program is relatively small. As the program grows, more of the features can be automated (e.g. assigning drivers to rides).
Also, if the group chat is in the app, we can add things like "mentioning rides", "mentioning drivers" or "mentioning riders" with @ or # notation to make links to the rows in the database tables (similar to how the @ and # symbols work in Github discussions.)
Initially, the chat may be only for drivers and admins. At a later stage, we can check in with the program participants to see whether it makes sense to add riders into the chat as well.
Feature Summary
The aim is to have a chat page in the app so that admins and drivers can send messages between each other.
Discussion
This is a big feature, so it should be broken up into multiple issues; the list below is one suggestion.
Remember "minimum viable product"; the first iteration of this would be a single chat room for all drivers/admins without DM features; just a global chat where everyone sees everything.
So DM's are not part of MVP. However, I do suggest including these fields in the entity, since it can be disruptive to add new fields to the database once that app is launched. It will be easier to add DMs later if these fields already exist.
private boolean dm;private Long toUserId
The dm field would initially always be false, and the toUserId field would be null; we'll use those fields later when/if we implement DMs (but that will be a separate Epic.)
Implementation Todos
Here is one way to break this up. Note that each of the headings below could be a single issue/PR or it could be broken down further into multiple issues/PRs; smaller issues/PRs are easier to code review / merge and tend to earn more points!
CRUD backend for messages MVP
[ ] There is an entity/repository for a ChatMessage. A ChatMessage should have an id, userId, and a message payload. You can use the @CreationTimestamp technique to automatically get a timestamp on the message.
[ ] Include these fields for future use: private boolean dm;,private Long toUserId
[ ] There is a backend POST endpoint /api/chat/post where any admin or driver can create a message. If user is not admin or driver, that should be a 403 error. The endpoint should take just one parameter: content. The userId should be determined automatically from the currentUser service on the backend, and should not be passed as a parameter. The dm field should always be set to false right now, and the toUserId set to null.
[ ] There is a chatMessageFixtures.js that matches the output of the /api/chat/get endpoint. If that endpoint already exists, use actual data from Swagger; if not, make a best effort guess as to what it will look like, and communicate with the person working on the backend implementation of CRUD operations for chat messages.
[ ] There is a chat window component ChatDisplay that displays chat messages retrieved from the backend endpoint; that is its only job.
[ ] The chat messages displayed should include the date/time of the message, the user id (probably as the full name of the user and the numeric userid in parens, e.g. Phill Conrad (17) or Phillip Conrad (23)) and the message content. There is no need to display the id field from the message table. You may find it useful to create a separate ChatMessageDisplay component that displays a single message using a React Bootstrap Card; the main panel of the ChatDisplay would then be a Stack of ChatMessageDisplay components. Or you could use OurTable; this is an implementer decision.
[ ] For this issue, we don't necessarily need a frontend component to create the messages yet; that can come later. Build this with the assumption that while you are building it, you can test it by entering messages manually in the swagger POST endpoint. However, assume that a ChatMessageCreate component will go stacked on top of, or immediately underneath, this component.
[ ] The chat window component either takes a list of messages as a prop (this is easier for testing if the backend isn't ready yet), or it might directly query the backend endpoint for the messages (like the PagedJobsTable does). This is an implementation decision. It could also be that a first version take messages though a prop, and a later version integrates directly with the backend.
[ ] Messages in the chat window are displayed with the least recent message on top, and the most recent message on bottom.
[ ] By default, only the most recent n messages are loaded, where n is at least 5, but could be 10 or 20; whatever it is, it should be defined as a constant somewhere in the component, e.g. const initialMessagePageSize = 10 and then that value should be used everywhere by the name initialMessagePageSize (i.e. it should be possible to change the initial message page size by changing just that one number.)
[ ] Messages have a scroll bar when the content of the most recent n messages is too big to fit in the window.
[ ] In a first PR, it's ok if this is only displayed in the Storybook. Integrating it into the page can come later when all of the separate parts are ready.
[ ] The chat message window should retrieve new messages with some frequency that is defined as a variable in the component (e.g. every 2000 ms).
Frontend Chat Display Component (not MVP; work on these ONLY after all front and backend MVP features are done!)
[ ] There is also a button at the top of the when there are more pages of messages "load more messages". Unlike the PagedJobsTable, instead of showing one page at a time, it works more like "infinite scroll"; each time you click "more messages", another page of messages from the past is loaded, until you reach the earliest message, at which point the "load more messages" button is disabled, and the label text changes to "No more messages".
Frontend ChatMessageCreate component (MVP)
[ ] There is a ChatMessageCreate component that can create a new chat message and post it to the /api/chat/post endpoint. The only information you need from the user is the message content, but you will need a <Form> for that. It should not be necessary to pass the userId, since the backend already knows the userId (from currentUserService).
[ ] The ChatMessageCreate component should be the same width as the ChatDisplay so that we can create a ChatPanel that consists of the ChatMessageCreate and ChatDisplay components stacked on top of each other. (See: https://react-bootstrap.netlify.app/docs/layout/stack/)
Frontend ChatPanel component (MVP)
[ ] There is a ChatPanel component that is composed of two children, ChatMessageCreate and ChatDisplay
[ ] The ChatPanel incorporates a vertical Stack of ChatMessageCreate and ChatDisplay
[ ] There is a storybook entry for ChatPanel
Frontend ChatPanel component incorporated into App
This depends on all of the MVP issues above being finished.
Your job here is to incorporate the working ChatPanel into a new ChatPage at the url /chat.
User Story
Discussion
Currently, the drivers use a group chat to coordinate their activities.
Moving that group chat into the app is a good way to provide a way for coordination to happen while the program is relatively small. As the program grows, more of the features can be automated (e.g. assigning drivers to rides).
Also, if the group chat is in the app, we can add things like "mentioning rides", "mentioning drivers" or "mentioning riders" with @ or # notation to make links to the rows in the database tables (similar to how the @ and # symbols work in Github discussions.)
Initially, the chat may be only for drivers and admins. At a later stage, we can check in with the program participants to see whether it makes sense to add riders into the chat as well.
Feature Summary
The aim is to have a chat page in the app so that admins and drivers can send messages between each other.
Discussion
This is a big feature, so it should be broken up into multiple issues; the list below is one suggestion.
Remember "minimum viable product"; the first iteration of this would be a single chat room for all drivers/admins without DM features; just a global chat where everyone sees everything.
So DM's are not part of MVP. However, I do suggest including these fields in the entity, since it can be disruptive to add new fields to the database once that app is launched. It will be easier to add DMs later if these fields already exist.
private boolean dm;
private Long toUserId
The
dm
field would initially always be false, and the toUserId field would benull
; we'll use those fields later when/if we implement DMs (but that will be a separate Epic.)Implementation Todos
Here is one way to break this up. Note that each of the headings below could be a single issue/PR or it could be broken down further into multiple issues/PRs; smaller issues/PRs are easier to code review / merge and tend to earn more points!
CRUD backend for messages MVP
@CreationTimestamp
technique to automatically get a timestamp on the message.private boolean dm;
,private Long toUserId
/api/chat/post
where any admin or driver can create a message. If user is not admin or driver, that should be a 403 error. The endpoint should take just one parameter:content
. The userId should be determined automatically from the currentUser service on the backend, and should not be passed as a parameter. Thedm
field should always be set tofalse
right now, and thetoUserId
set to null./api/chat/get
for retrieving chat messages that operates similar to the backend endpoint for jobs in theproj-happycows
repo, in that it is paged, and sorted. The endpoint should retrieve the most recent messages first. It should retrieve messages only if the user is an admin or driver, otherwise it should return a 403. See: https://github.com/ucsb-cs156/proj-happycows/blob/7f4a3c596920b786b60c167899fe6d8b4ed1b795/src/main/java/edu/ucsb/cs156/happiercows/controllers/JobsController.java#L74 for an example of how to create paged controller, and https://github.com/ucsb-cs156/proj-happycows/blob/main/frontend/src/main/components/Jobs/PagedJobsTable.js for an example of how to access a paged backend from the frontend.Frontend
ChatDisplay
Component (MVP)chatMessageFixtures.js
that matches the output of the/api/chat/get
endpoint. If that endpoint already exists, use actual data from Swagger; if not, make a best effort guess as to what it will look like, and communicate with the person working on the backend implementation of CRUD operations for chat messages.ChatDisplay
that displays chat messages retrieved from the backend endpoint; that is its only job.Phill Conrad (17)
orPhillip Conrad (23)
) and the message content. There is no need to display theid
field from the message table. You may find it useful to create a separateChatMessageDisplay
component that displays a single message using a React BootstrapCard
; the main panel of theChatDisplay
would then be aStack
ofChatMessageDisplay
components. Or you could useOurTable
; this is an implementer decision.ChatMessageCreate
component will go stacked on top of, or immediately underneath, this component.const initialMessagePageSize = 10
and then that value should be used everywhere by the nameinitialMessagePageSize
(i.e. it should be possible to change the initial message page size by changing just that one number.)Frontend Chat Display Component (not MVP; work on these ONLY after all front and backend MVP features are done!)
Frontend
ChatMessageCreate
component (MVP)ChatMessageCreate
component that can create a new chat message and post it to the/api/chat/post
endpoint. The only information you need from the user is the message content, but you will need a<Form>
for that. It should not be necessary to pass the userId, since the backend already knows the userId (from currentUserService).ChatMessageCreate
component should be the same width as theChatDisplay
so that we can create aChatPanel
that consists of theChatMessageCreate
andChatDisplay
components stacked on top of each other. (See: https://react-bootstrap.netlify.app/docs/layout/stack/)Frontend
ChatPanel
component (MVP)ChatPanel
component that is composed of two children,ChatMessageCreate
andChatDisplay
ChatPanel
incorporates a verticalStack
ofChatMessageCreate
andChatDisplay
ChatPanel
Frontend
ChatPanel
component incorporated into AppThis depends on all of the MVP issues above being finished.
Your job here is to incorporate the working ChatPanel into a new ChatPage at the url
/chat
.