Erweiterungen

This commit is contained in:
2025-10-09 10:56:27 +02:00
parent b4e55cee82
commit 9b9a2feb6d
9 changed files with 49 additions and 43 deletions

View File

@@ -1,7 +1,7 @@
package de.assecutor.votianlt.controller; package de.assecutor.votianlt.controller;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.service.MessageService; import de.assecutor.votianlt.service.MessageService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
@@ -173,20 +173,20 @@ public class MessageApiController {
} }
/** /**
* Get messages by direction (incoming/outgoing) * Get messages by origin (incoming/outgoing/server)
* GET /api/messages/direction/{direction} * GET /api/messages/origin/{origin}
*/ */
@GetMapping("/direction/{direction}") @GetMapping("/origin/{origin}")
public ResponseEntity<List<Message>> getMessagesByDirection(@PathVariable String direction) { public ResponseEntity<List<Message>> getMessagesByOrigin(@PathVariable String origin) {
try { try {
MessageDirection messageDirection = MessageDirection.valueOf(direction.toUpperCase()); MessageOrigin messageOrigin = MessageOrigin.valueOf(origin.toUpperCase());
List<Message> messages = messageService.getMessagesByDirection(messageDirection); List<Message> messages = messageService.getMessagesByOrigin(messageOrigin);
return ResponseEntity.ok(messages); return ResponseEntity.ok(messages);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
log.error("Invalid direction: {}", direction); log.error("Invalid origin: {}", origin);
return ResponseEntity.badRequest().build(); return ResponseEntity.badRequest().build();
} catch (Exception e) { } catch (Exception e) {
log.error("Error retrieving messages by direction {}: {}", direction, e.getMessage(), e); log.error("Error retrieving messages by origin {}: {}", origin, e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
} }
} }

View File

@@ -1,7 +1,7 @@
package de.assecutor.votianlt.dto; package de.assecutor.votianlt.dto;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.model.MessageType; import de.assecutor.votianlt.model.MessageType;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -13,7 +13,7 @@ public record ChatMessageOutboundPayload(
String sender, String sender,
String receiver, String receiver,
String content, String content,
MessageDirection direction, MessageOrigin origin,
MessageType messageType, MessageType messageType,
LocalDateTime createdAt, LocalDateTime createdAt,
String jobId, String jobId,
@@ -27,7 +27,7 @@ public record ChatMessageOutboundPayload(
message.getSender(), message.getSender(),
message.getReceiver(), message.getReceiver(),
message.getContent(), message.getContent(),
message.getDirection(), message.getOrigin(),
message.getMessageType(), message.getMessageType(),
message.getCreatedAt(), message.getCreatedAt(),
message.getJobIdAsString(), message.getJobIdAsString(),

View File

@@ -49,10 +49,10 @@ public class Message {
private LocalDateTime createdAt; private LocalDateTime createdAt;
/** /**
* Direction of the message: INCOMING (from client) or OUTGOING (to client) * Origin of the message: INCOMING (from client), OUTGOING (to client), or SERVER (from server)
*/ */
@Field("direction") @Field("origin")
private MessageDirection direction; private MessageOrigin origin;
/** /**
* Type of message: JOB_RELATED or GENERAL * Type of message: JOB_RELATED or GENERAL
@@ -87,11 +87,11 @@ public class Message {
/** /**
* Constructor for general messages * Constructor for general messages
*/ */
public Message(String content, String sender, String receiver, MessageDirection direction) { public Message(String content, String sender, String receiver, MessageOrigin origin) {
this.content = content; this.content = content;
this.sender = sender; this.sender = sender;
this.receiver = receiver; this.receiver = receiver;
this.direction = direction; this.origin = origin;
this.messageType = MessageType.GENERAL; this.messageType = MessageType.GENERAL;
this.createdAt = LocalDateTime.now(); this.createdAt = LocalDateTime.now();
this.isRead = false; this.isRead = false;
@@ -100,12 +100,12 @@ public class Message {
/** /**
* Constructor for job-related messages * Constructor for job-related messages
*/ */
public Message(String content, String sender, String receiver, MessageDirection direction, public Message(String content, String sender, String receiver, MessageOrigin origin,
ObjectId jobId, String jobNumber) { ObjectId jobId, String jobNumber) {
this.content = content; this.content = content;
this.sender = sender; this.sender = sender;
this.receiver = receiver; this.receiver = receiver;
this.direction = direction; this.origin = origin;
this.messageType = MessageType.JOB_RELATED; this.messageType = MessageType.JOB_RELATED;
this.jobId = jobId; this.jobId = jobId;
this.jobNumber = jobNumber; this.jobNumber = jobNumber;

View File

@@ -1,9 +1,9 @@
package de.assecutor.votianlt.model; package de.assecutor.votianlt.model;
/** /**
* Enum representing the direction of a message * Enum representing the origin of a message
*/ */
public enum MessageDirection { public enum MessageOrigin {
/** /**
* Message received from a client (app user) * Message received from a client (app user)
*/ */
@@ -12,5 +12,10 @@ public enum MessageDirection {
/** /**
* Message sent to a client (app user) * Message sent to a client (app user)
*/ */
OUTGOING OUTGOING,
/**
* Message sent from the server
*/
SERVER
} }

View File

@@ -20,7 +20,7 @@ import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouteParameters; import com.vaadin.flow.router.RouteParameters;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.model.MessageType; import de.assecutor.votianlt.model.MessageType;
import de.assecutor.votianlt.pages.service.AppUserService; import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.service.MessageService; import de.assecutor.votianlt.service.MessageService;
@@ -148,6 +148,7 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
messagesScroller.setScrollDirection(Scroller.ScrollDirection.VERTICAL); messagesScroller.setScrollDirection(Scroller.ScrollDirection.VERTICAL);
messagesScroller.setHeightFull(); messagesScroller.setHeightFull();
messagesScroller.getStyle().set("flex", "1 1 auto"); messagesScroller.getStyle().set("flex", "1 1 auto");
messagesScroller.getStyle().set("background-color", "#f0f0f0");
contentLayout.add(messagesScroller); contentLayout.add(messagesScroller);
contentLayout.setFlexGrow(1, messagesScroller); contentLayout.setFlexGrow(1, messagesScroller);
@@ -188,7 +189,7 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
separator.getStyle().set("margin", "20px 0"); separator.getStyle().set("margin", "20px 0");
Span dateSpan = new Span(date.format(DATE_FORMATTER)); Span dateSpan = new Span(date.format(DATE_FORMATTER));
dateSpan.getStyle().set("background-color", "#e0e0e0"); dateSpan.getStyle().set("background-color", "#f0f0f0");
dateSpan.getStyle().set("padding", "5px 15px"); dateSpan.getStyle().set("padding", "5px 15px");
dateSpan.getStyle().set("border-radius", "15px"); dateSpan.getStyle().set("border-radius", "15px");
dateSpan.getStyle().set("font-size", "12px"); dateSpan.getStyle().set("font-size", "12px");
@@ -405,7 +406,7 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
} }
String content = Optional.ofNullable(message.getContent()).orElse("(kein Inhalt)"); String content = Optional.ofNullable(message.getContent()).orElse("(kein Inhalt)");
if (message.getDirection() == MessageDirection.INCOMING) { if (message.getOrigin() == MessageOrigin.INCOMING) {
messagesContainer.add(createIncomingMessage(content, timestamp)); messagesContainer.add(createIncomingMessage(content, timestamp));
} else { } else {
messagesContainer.add(createOutgoingMessage(content, timestamp)); messagesContainer.add(createOutgoingMessage(content, timestamp));
@@ -425,7 +426,7 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
if (scrollAnchor == null) { if (scrollAnchor == null) {
scrollAnchor = new Div(); scrollAnchor = new Div();
scrollAnchor.setId("scroll-anchor"); scrollAnchor.setId("scroll-anchor");
scrollAnchor.getStyle().set("height", "1px"); scrollAnchor.getStyle().set("height", "5px");
} }
if (scrollAnchor.getParent().isEmpty()) { if (scrollAnchor.getParent().isEmpty()) {
messagesContainer.add(scrollAnchor); messagesContainer.add(scrollAnchor);

View File

@@ -18,7 +18,7 @@ import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.dto.ClientMessageSummary; import de.assecutor.votianlt.dto.ClientMessageSummary;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.pages.service.AppUserService; import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.service.MessageService; import de.assecutor.votianlt.service.MessageService;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
@@ -210,7 +210,7 @@ public class MessagesView extends Main {
String preview = Optional.ofNullable(latest.getContent()).filter(s -> !s.isBlank()).orElse("(kein Inhalt)"); String preview = Optional.ofNullable(latest.getContent()).filter(s -> !s.isBlank()).orElse("(kein Inhalt)");
int totalMessages = conversation.size(); int totalMessages = conversation.size();
int unreadCount = (int) conversation.stream() int unreadCount = (int) conversation.stream()
.filter(msg -> msg.getDirection() == MessageDirection.INCOMING && !msg.isRead()) .filter(msg -> msg.getOrigin() == MessageOrigin.INCOMING && !msg.isRead())
.count(); .count();
summary.setTotalMessages(summary.getTotalMessages() + totalMessages); summary.setTotalMessages(summary.getTotalMessages() + totalMessages);
@@ -243,7 +243,7 @@ public class MessagesView extends Main {
if (message == null) { if (message == null) {
return null; return null;
} }
if (message.getDirection() == MessageDirection.INCOMING) { if (message.getOrigin() == MessageOrigin.INCOMING) {
return message.getSender(); return message.getSender();
} }
return message.getReceiver(); return message.getReceiver();

View File

@@ -17,7 +17,7 @@ import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.AppUser; import de.assecutor.votianlt.model.AppUser;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.model.MessageType; import de.assecutor.votianlt.model.MessageType;
import de.assecutor.votianlt.pages.service.AppUserService; import de.assecutor.votianlt.pages.service.AppUserService;
import de.assecutor.votianlt.service.MessageService; import de.assecutor.votianlt.service.MessageService;
@@ -131,7 +131,7 @@ public class UserMessagesView extends Main implements HasUrlParameter<String> {
Message latest = sortedMessages.isEmpty() ? null : sortedMessages.get(sortedMessages.size() - 1); Message latest = sortedMessages.isEmpty() ? null : sortedMessages.get(sortedMessages.size() - 1);
int unreadCount = (int) sortedMessages.stream() int unreadCount = (int) sortedMessages.stream()
.filter(message -> message.getDirection() == MessageDirection.INCOMING && !message.isRead()) .filter(message -> message.getOrigin() == MessageOrigin.INCOMING && !message.isRead())
.count(); .count();
int messageCount = sortedMessages.size(); int messageCount = sortedMessages.size();
LocalDateTime lastMessageTime = latest != null ? latest.getCreatedAt() : null; LocalDateTime lastMessageTime = latest != null ? latest.getCreatedAt() : null;
@@ -173,7 +173,7 @@ public class UserMessagesView extends Main implements HasUrlParameter<String> {
messages.sort(Comparator.comparing(Message::getCreatedAt, Comparator.nullsLast(LocalDateTime::compareTo))); messages.sort(Comparator.comparing(Message::getCreatedAt, Comparator.nullsLast(LocalDateTime::compareTo)));
Message latest = messages.get(messages.size() - 1); Message latest = messages.get(messages.size() - 1);
int unreadCount = (int) messages.stream() int unreadCount = (int) messages.stream()
.filter(message -> message.getDirection() == MessageDirection.INCOMING && !message.isRead()) .filter(message -> message.getOrigin() == MessageOrigin.INCOMING && !message.isRead())
.count(); .count();
String conversationTitle = "Auftrag " + jobKey; String conversationTitle = "Auftrag " + jobKey;

View File

@@ -1,7 +1,7 @@
package de.assecutor.votianlt.repository; package de.assecutor.votianlt.repository;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.model.MessageType; import de.assecutor.votianlt.model.MessageType;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.MongoRepository;
@@ -38,9 +38,9 @@ public interface MessageRepository extends MongoRepository<Message, ObjectId> {
List<Message> findByReceiverAndMessageTypeOrderByCreatedAtDesc(String receiver, MessageType messageType); List<Message> findByReceiverAndMessageTypeOrderByCreatedAtDesc(String receiver, MessageType messageType);
/** /**
* Find all messages by direction (incoming/outgoing) * Find all messages by origin (incoming/outgoing/server)
*/ */
List<Message> findByDirectionOrderByCreatedAtDesc(MessageDirection direction); List<Message> findByOriginOrderByCreatedAtDesc(MessageOrigin origin);
/** /**
* Find all messages between two users (in both directions) * Find all messages between two users (in both directions)

View File

@@ -1,7 +1,7 @@
package de.assecutor.votianlt.service; package de.assecutor.votianlt.service;
import de.assecutor.votianlt.model.Message; import de.assecutor.votianlt.model.Message;
import de.assecutor.votianlt.model.MessageDirection; import de.assecutor.votianlt.model.MessageOrigin;
import de.assecutor.votianlt.model.MessageType; import de.assecutor.votianlt.model.MessageType;
import de.assecutor.votianlt.dto.ChatMessageInboundPayload; import de.assecutor.votianlt.dto.ChatMessageInboundPayload;
import de.assecutor.votianlt.dto.ChatMessageOutboundPayload; import de.assecutor.votianlt.dto.ChatMessageOutboundPayload;
@@ -38,7 +38,7 @@ public class MessageService {
* Send a general message to a client via MQTT * Send a general message to a client via MQTT
*/ */
public Message sendGeneralMessageToClient(String content, String sender, String receiver) { public Message sendGeneralMessageToClient(String content, String sender, String receiver) {
Message message = new Message(content, sender, receiver, MessageDirection.OUTGOING); Message message = new Message(content, sender, receiver, MessageOrigin.SERVER);
message = saveMessage(message); message = saveMessage(message);
publishMessageToMqtt(message, receiver); publishMessageToMqtt(message, receiver);
return message; return message;
@@ -49,7 +49,7 @@ public class MessageService {
*/ */
public Message sendJobMessageToClient(String content, String sender, String receiver, public Message sendJobMessageToClient(String content, String sender, String receiver,
ObjectId jobId, String jobNumber) { ObjectId jobId, String jobNumber) {
Message message = new Message(content, sender, receiver, MessageDirection.OUTGOING, jobId, jobNumber); Message message = new Message(content, sender, receiver, MessageOrigin.SERVER, jobId, jobNumber);
message = saveMessage(message); message = saveMessage(message);
publishMessageToMqtt(message, receiver); publishMessageToMqtt(message, receiver);
return message; return message;
@@ -62,10 +62,10 @@ public class MessageService {
Message message; Message message;
if (payload.hasJobContext()) { if (payload.hasJobContext()) {
message = new Message(payload.content(), payload.sender(), payload.receiver(), message = new Message(payload.content(), payload.sender(), payload.receiver(),
MessageDirection.INCOMING, payload.jobId(), payload.jobNumber()); MessageOrigin.INCOMING, payload.jobId(), payload.jobNumber());
} else { } else {
message = new Message(payload.content(), payload.sender(), payload.receiver(), message = new Message(payload.content(), payload.sender(), payload.receiver(),
MessageDirection.INCOMING); MessageOrigin.INCOMING);
} }
return saveMessage(message); return saveMessage(message);
} }
@@ -156,10 +156,10 @@ public class MessageService {
} }
/** /**
* Get messages by direction * Get messages by origin
*/ */
public List<Message> getMessagesByDirection(MessageDirection direction) { public List<Message> getMessagesByOrigin(MessageOrigin origin) {
return messageRepository.findByDirectionOrderByCreatedAtDesc(direction); return messageRepository.findByOriginOrderByCreatedAtDesc(origin);
} }
/** /**