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

Feature/413 chat room #419

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9ed8eeb
implemented a Dark Mode for Diveni
SponsoredByPuma Jul 24, 2023
114eb22
styled the navBar and also the session page a bit
Jul 24, 2023
989c00c
update the link color
SponsoredByPuma Jul 25, 2023
ca2584a
styled everything now, works as intended + added Pictures in Landing …
SponsoredByPuma Jul 26, 2023
b244688
redesign of the prepare page
Aug 1, 2023
9e488f9
prepare Page now changes pictures depending on theme
SponsoredByPuma Aug 2, 2023
d8f7f5e
changed colour of button hover
SponsoredByPuma Aug 2, 2023
a27dcfc
added the blurred background
SponsoredByPuma Aug 2, 2023
21a3547
Merge branch 'main' into 364-dark-mode
SponsoredByPuma Aug 2, 2023
e2cee4a
styled the join page according to wireframe
SponsoredByPuma Aug 3, 2023
04d4247
updated session page, Member Vote page, add some css variables
SponsoredByPuma Aug 3, 2023
941a789
fixed not responsive Background
SponsoredByPuma Aug 4, 2023
d106c4b
add shadow + rounded the pictures
SponsoredByPuma Aug 4, 2023
ec3caa3
styled Session Page
SponsoredByPuma Aug 4, 2023
6fe7bac
styled MemberVotePage, improved the Timer + Option Buttons on Session…
SponsoredByPuma Aug 4, 2023
73b20ee
Update App.vue
SponsoredByPuma Aug 7, 2023
90d90d8
website now looks fine on smaller devices
Aug 7, 2023
c4a661f
Merge branch '364-dark-mode' of https://github.com/Sybit-Education/Di…
Aug 7, 2023
795dbbd
add some button styling
Aug 7, 2023
449a83a
improved Code Quality
Aug 8, 2023
0653868
reverted animation
SponsoredByPuma Aug 9, 2023
67bd4a6
add focus to search bar
SponsoredByPuma Aug 9, 2023
e5d0156
removed some icons and replaced them with bootstrap icons. improved m…
SponsoredByPuma Aug 17, 2023
c87ed04
Merge branch 'main' into 364-dark-mode
SponsoredByPuma Aug 17, 2023
a90e79a
fixed overflow of buttontext
SponsoredByPuma Aug 17, 2023
ee081d5
Merge branch 'main' into 364-dark-mode
SponsoredByPuma Aug 23, 2023
07d4193
Merge branch 'main' into 364-dark-mode
SponsoredByPuma Aug 24, 2023
c14b0ce
made the font color inside the markdown editor also a var
SponsoredByPuma Sep 20, 2023
f92b9f8
styling for the session page is almost done
SponsoredByPuma Sep 22, 2023
a834f08
worked on the functionality of the chat
Sep 26, 2023
0056d59
chat works, some smaller issues remain
SponsoredByPuma Sep 26, 2023
f418bfd
fix: member subscribed multiple times to chat
SponsoredByPuma Sep 26, 2023
01be4fa
add new chat model, worked on styling
SponsoredByPuma Sep 27, 2023
78c4786
Merge branch 'main' into feature/413-chat-room
SponsoredByPuma Sep 27, 2023
509870c
Google Java Format
Sep 27, 2023
35739df
Backend Tests, Locales, improved time stamp, clean up fe components
SponsoredByPuma Sep 28, 2023
bf841f8
Google Java Format
Sep 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package io.diveni.backend.controller;

import java.security.Principal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

Expand Down Expand Up @@ -196,6 +198,31 @@ private boolean checkIfAllMembersVoted(List<Member> members) {
return members.stream().filter(m -> m.getCurrentEstimation() == null).count() == 0;
}

@MessageMapping("/chat-admin")
public synchronized void processChatMessageAdmin(
@Payload String message, AdminPrincipal principal) {
LOGGER.debug("--> processChatMessageAdmin()");
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
message = message + "\n - Host " + LocalDateTime.now().format(formatter);
val session =
ControllerUtils.getSessionOrThrowResponse(databaseService, principal.getSessionID());
webSocketService.sendMessage(session, message, principal.getAdminID());
LOGGER.debug("<-- processChatMessageAdmin()");
}

@MessageMapping("/chat-member")
public synchronized void processChatMessageMember(
@Payload String message, MemberPrincipal principal) {
LOGGER.debug("--> processChatMessageMember()");
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
message = message + " " + LocalDateTime.now().format(formatter);
val session =
ControllerUtils.getSessionByMemberIDOrThrowResponse(
databaseService, principal.getMemberID());
webSocketService.sendMessage(session, message, principal.getMemberID());
LOGGER.debug("<-- processChatMessageMember()");
}

@MessageMapping("/restart")
public synchronized void restartVote(AdminPrincipal principal) {
LOGGER.debug("--> restartVote()");
Expand Down
19 changes: 19 additions & 0 deletions backend/src/main/java/io/diveni/backend/model/ChatMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.diveni.backend.model;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class ChatMessage {

private String message;

private String author;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import io.diveni.backend.model.ChatMessage;
import io.diveni.backend.model.MemberUpdate;
import io.diveni.backend.model.Session;
import io.diveni.backend.model.notification.Notification;
Expand Down Expand Up @@ -43,6 +44,8 @@ public class WebSocketService {

public static String START_TIMER_DESTINATION = "/updates/startTimer";

public static String CHAT_MESSAGE_DESTINATION = "/updates/chatMessage";

public static String USER_STORY_SELECTED_DESTINATION = "/updates/userStorySelected";

@Autowired private SimpMessagingTemplate simpMessagingTemplate;
Expand Down Expand Up @@ -240,6 +243,30 @@ public void sendTimerStartMessageToUser(Session session, String timestamp, Strin
LOGGER.debug("<-- sendTimerStartMessageToUser()");
}

public void sendMessage(Session session, String message, String userID) {
LOGGER.debug("--> sendMessage(), sessionID={}", session.getSessionID());
val sessionPrincipals = getSessionPrincipals(session.getSessionID());
if (sessionPrincipals.adminPrincipal() != null) {
sendChatMessageToUser(
session, new ChatMessage(message, userID), sessionPrincipals.adminPrincipal().getName());
} // else the admin left the session

sessionPrincipals
.memberPrincipals()
.forEach(
member ->
sendChatMessageToUser(
session, new ChatMessage(message, userID), member.getMemberID()));
LOGGER.debug("<-- sendMessage()");
}

public void sendChatMessageToUser(Session session, ChatMessage message, String userID) {
LOGGER.debug(
"--> sendChatMessageToUser(), sessionID={}, userID={}", session.getSessionID(), userID);
simpMessagingTemplate.convertAndSendToUser(userID, CHAT_MESSAGE_DESTINATION, message);
LOGGER.debug("<-- sendChatMessageToUser()");
}

public void sendNotification(Session session, Notification notification) {
LOGGER.debug("--> sendNotification(), sessionID={}", session.getSessionID());
getSessionPrincipals(session.getSessionID())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@
import java.util.Set;

import io.diveni.backend.Utils;
import io.diveni.backend.model.Member;
import io.diveni.backend.model.MemberUpdate;
import io.diveni.backend.model.Session;
import io.diveni.backend.model.SessionConfig;
import io.diveni.backend.model.SessionState;
import io.diveni.backend.model.*;
import io.diveni.backend.model.notification.Notification;
import io.diveni.backend.model.notification.NotificationType;
import io.diveni.backend.principals.AdminPrincipal;
Expand Down Expand Up @@ -366,4 +362,48 @@ public void removeSession_isRemoved() throws Exception {

assertTrue(webSocketService.getSessionPrincipalList().isEmpty());
}

@Test
public void adminSendsMessage_sendsTheMessageToAllUser() throws Exception {
final String message = "Test - Host 12:12:12";
val memberPrincipal =
new MemberPrincipal(defaultAdminPrincipal.getSessionID(), Utils.generateRandomID());
setDefaultAdminPrincipal(Set.of(defaultMemberPrincipal, memberPrincipal));
val session =
new Session(
new ObjectId(),
defaultAdminPrincipal.getSessionID(),
defaultAdminPrincipal.getAdminID(),
new SessionConfig(List.of(), List.of(), null, "US_MANUALLY", "password"),
null,
List.of(
new Member(defaultMemberPrincipal.getMemberID(), null, null, null, null),
new Member(memberPrincipal.getMemberID(), null, null, null, null)),
new HashMap<>(),
new ArrayList<>(),
SessionState.WAITING_FOR_MEMBERS,
null,
null,
null);

webSocketService.sendMessage(session, message, defaultAdminPrincipal.getAdminID());

verify(simpMessagingTemplateMock, times(1))
.convertAndSendToUser(
defaultMemberPrincipal.getMemberID(),
WebSocketService.CHAT_MESSAGE_DESTINATION,
new ChatMessage(message, defaultAdminPrincipal.getAdminID()));

verify(simpMessagingTemplateMock, times(1))
.convertAndSendToUser(
memberPrincipal.getMemberID(),
WebSocketService.CHAT_MESSAGE_DESTINATION,
new ChatMessage(message, defaultAdminPrincipal.getAdminID()));

verify(simpMessagingTemplateMock, times(1))
.convertAndSendToUser(
defaultAdminPrincipal.getAdminID(),
WebSocketService.CHAT_MESSAGE_DESTINATION,
new ChatMessage(message, defaultAdminPrincipal.getAdminID()));
}
}
192 changes: 192 additions & 0 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,199 @@ export default Vue.extend({
});
</script>
<style>
@import "./assets/variables.css";
main {
min-height: calc(100vh - 10rem);
background:
/* Top */
radial-gradient(farthest-corner at 500px 500px, var(--blurredColour1) 0.1%, rgba(255, 255, 255, 0) 26%),
radial-gradient(farthest-corner at 500px 500px, var(--blurredColour1) 0.1%, rgba(255, 255, 255, 0) 26%),
radial-gradient(farthest-corner at 7% 7%, var(--blurredColour2) 0.1%, rgba(255, 255, 255, 0) 8%),
radial-gradient(farthest-corner at 17% 40px, var(--blurredColour3) 1%, rgba(255, 255, 255, 0) 16%),
radial-gradient(farthest-corner at 17% 40px, var(--blurredColour3) 1%, rgba(255, 255, 255, 0) 16%),
radial-gradient(farthest-corner at 36% 7%, var(--blurredColour4) 0.1%, rgba(255, 255, 255, 0) 18%),
radial-gradient(farthest-corner at 36% 7%, var(--blurredColour4) 0.1%, rgba(255, 255, 255, 0) 18%),

/* Bottom */
radial-gradient(farthest-corner at 95% 42%, var(--blurredColour5) 0.1%, rgba(255, 255, 255, 0) 26%),
radial-gradient(farthest-corner at 0% 58%, var(--blurredColour5) 0.1%, rgba(255, 255, 255, 0) 22%),
radial-gradient(circle farthest-corner at 65% 95%, var(--blurredColour3) 0.1%, rgba(255, 255, 255, 0) 13%),
radial-gradient( farthest-corner at 100% 87%, var(--blurredColour3) 0.1%, rgba(255, 255, 255, 0) 13%),
radial-gradient( farthest-corner at 84% 82%, var(--blurredColour4) 0.1%, rgba(255, 255, 255, 0) 13%),
radial-gradient(circle farthest-corner at 84% 82%, var(--blurredColour6) 0.1%, rgba(255, 255, 255, 0) 13%);
background-color: var(--background-color-primary);
backdrop-filter: blur(5px);
color: var(--text-primary-color) !important;
}

p {
color: var(--text-primary-color);
}

h1 {
color: var(--text-primary-color);
}

h4 {
color: var(--text-primary-color);
}
/* Landing Page */
.newSessionCard .landingPageCardButton{
background-color: var(--startButton);
border-radius: var(--buttonShape);
color: var(--text-primary-color);
}

.newSessionCard .landingPageCardButton:hover{
background-color: var(--startButtonHovered);
color: var(--text-primary-color);
}

.newSessionCard .landingPageCardButton:focus{
background-color: var(--startButtonHovered) !important;
}

.newSessionCard .card-footer {
background-color: #52173100; /* So the Footer does not overflow */
}

.joinSessionCard .landingPageCardButton{
background-color: var(--joinButton);
border-radius: var(--buttonShape);
color: var(--text-primary-color);
}

.joinSessionCard .landingPageCardButton:hover{
background-color: var(--joinButtonHovered);
color: var(--text-primary-color);
}

.joinSessionCard .card-footer {
background-color: #52173100; /* So the Footer does not overflow */
}

.reconnectSessionCard .landingPageCardButton {
background-color: var(--reconnectButton);
border-radius: var(--buttonShape);
color: var(--text-primary-color);
}

.reconnectSessionCard .landingPageCardButton:hover {
background-color: var(--reconnectButtonHovered);
color: var(--text-primary-color);
}

.reconnectSessionCard .landingPageCardButton:focus {
background-color: var(--reconnectButtonHovered) !important;
}

.reconnectSessionCard .card-footer {
background-color: #52173100; /* So the Footer does not overflow */
}
/* Prepare Page */
.selectedTab {
background-color: var(--preparePageMainColor) !important;
}

.selectedTextColor {
color: var(--text-primary-color) !important;
}

.notSelectedTab {
background-color: var(--preparePageInActiveTab) !important;
border-color: var(--preparePageBorderTab) !important;
}

.notSelectedTab:hover {
background-color: var(--preparePageInActiveTabHover) !important;
}

.notSelectedTextColor {
color: var(--text-primary-color) !important;
}

/*End of prepare Page */

.dropDownLink {
color: var(--text-primary-color) !important;
}
.containerClass {
background-color: var(--landingPageCardsBackground) !important;
color: var(--text-primary-color) !important;
}

.dropdown-item {
color: var(--text-primary-color) !important;
}

.dropdown-item:hover {
color: black !important;
}

.dropdown-item.active {
background-color: var(--startButton) !important;
}

a.btn.joinButton {
background-color: var(--joinButton);
border-radius: var(--buttonShape);
color: var(--text-primary-color);
}

a.btn.joinButton:hover {
background-color: var(--joinButtonHovered);
}

a.btn.startButton {
background-color: var(--startButton);
border-radius: var(--buttonShape);
color: var(--text-primary-color);
}

a.btn.startButton:hover {
background-color: var(--startButtonHovered);
}

a.btn.startButton:focus {
background-color: var(--startButtonHovered) !important;
}

.btn.dropdown-toggle { /* User Estimation Button */
color: var(--text-primary-color);
background-color: var(--joinButton);
}

.btn.dropdown-toggle:active { /* User Estimation Button hold */
background-color: var(--joinButtonHovered) !important;
color: var(--text-primary-color) !important;
}

.btn.dropdown-toggle:hover { /* User Estimation Button Hover */
background-color: var(--joinButtonHovered);
color: var(--text-primary-color);
}

.btn-secondary:not(:disabled):not(.disabled).active, .show > .btn-secondary.dropdown-toggle { /* User Estimation Button clicked */
background-color: var(--joinButton) !important;
color: var(--text-primary-color) !important;
}

.btn-secondary:focus{ /* User Estimation Button after click & add User Story Button on click hold*/
background-color: var(--joinButtonHovered) !important;
color: var(--text-primary-color) !important;
}

.a.dropdown-item {
color: var(--text-primary-color) !important;
}

.a.dropdown-item:hover {
color: black !important;
}

.dropdown-menu {
background-color: var(--topNavigationBarColor) !important;
border-color: var(--text-primary-color) !important;
}

</style>
Binary file added frontend/src/assets/ActiveUserStory.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/EstimateUserStories.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/InviteYourTeam.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/LeaveButton.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/LoadingCat.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/SetUpSession.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/Timer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed frontend/src/assets/magnifying glass.png
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/Hour-DarkMode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P1D.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P2D.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P3D.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/preparePage/P4D.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading