Erweiterungen
This commit is contained in:
@@ -29,6 +29,7 @@ import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.router.RouteParameters;
|
||||
import com.vaadin.flow.shared.Registration;
|
||||
import de.assecutor.votianlt.model.AppUser;
|
||||
import de.assecutor.votianlt.model.Job;
|
||||
import de.assecutor.votianlt.model.Message;
|
||||
import de.assecutor.votianlt.model.MessageContentType;
|
||||
import de.assecutor.votianlt.model.MessageOrigin;
|
||||
@@ -154,6 +155,8 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
|
||||
this.jobNumberContext = filteredMessages.stream().map(Message::getJobNumber)
|
||||
.filter(value -> value != null && !value.isBlank()).findFirst().orElse(null);
|
||||
|
||||
ensureJobContextForConversation(filteredMessages);
|
||||
|
||||
String conversationTitle = resolveConversationTitle(filteredMessages, conversationId);
|
||||
|
||||
HorizontalLayout headerLayout = createHeaderLayout(clientName, conversationTitle);
|
||||
@@ -763,6 +766,8 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
|
||||
String sender = Optional.ofNullable(securityService.getCurrentUsername()).filter(name -> !name.isBlank())
|
||||
.orElse("System");
|
||||
|
||||
ensureJobContextForConversation(currentMessages);
|
||||
|
||||
try {
|
||||
Message saved;
|
||||
if (jobConversation) {
|
||||
@@ -843,6 +848,60 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
|
||||
return value.replaceAll("[^a-zA-Z0-9_-]", "_").toLowerCase();
|
||||
}
|
||||
|
||||
private void ensureJobContextForConversation(List<Message> messages) {
|
||||
if (!jobConversation) {
|
||||
jobIdContext = null;
|
||||
jobNumberContext = null;
|
||||
return;
|
||||
}
|
||||
|
||||
String token = extractJobConversationToken();
|
||||
if (token == null || token.isBlank()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jobIdContext == null && ObjectId.isValid(token)) {
|
||||
try {
|
||||
jobIdContext = new ObjectId(token);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
log.debug("Conversation token {} could not be converted to ObjectId", token, ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (messages != null && (jobNumberContext == null || jobNumberContext.isBlank())) {
|
||||
jobNumberContext = messages.stream()
|
||||
.map(Message::getJobNumber)
|
||||
.filter(value -> value != null && !value.isBlank())
|
||||
.findFirst()
|
||||
.orElse(jobNumberContext);
|
||||
}
|
||||
|
||||
if (jobIdContext == null || jobNumberContext == null || jobNumberContext.isBlank()) {
|
||||
Optional<Job> jobOptional = messageService.findJobByIdentifier(token);
|
||||
if (jobOptional.isEmpty() && jobNumberContext != null && !jobNumberContext.isBlank()) {
|
||||
jobOptional = messageService.findJobByIdentifier(jobNumberContext);
|
||||
}
|
||||
if (jobOptional.isPresent()) {
|
||||
Job job = jobOptional.get();
|
||||
jobIdContext = Optional.ofNullable(job.getId()).orElse(jobIdContext);
|
||||
jobNumberContext = Optional.ofNullable(job.getJobNumber())
|
||||
.filter(value -> !value.isBlank())
|
||||
.orElse(jobNumberContext);
|
||||
}
|
||||
}
|
||||
|
||||
if (jobNumberContext == null || jobNumberContext.isBlank()) {
|
||||
jobNumberContext = token;
|
||||
}
|
||||
}
|
||||
|
||||
private String extractJobConversationToken() {
|
||||
if (!jobConversation || conversationId == null || !conversationId.startsWith("job-")) {
|
||||
return null;
|
||||
}
|
||||
return conversationId.length() > 4 ? conversationId.substring(4) : "";
|
||||
}
|
||||
|
||||
private String resolveConversationTitle(List<Message> messages, String conversationId) {
|
||||
if (conversationId == null) {
|
||||
return "Konversation";
|
||||
@@ -947,6 +1006,8 @@ public class MessageDetailsView extends Main implements BeforeEnterObserver {
|
||||
// Add new message to the list
|
||||
currentMessages.add(message);
|
||||
|
||||
ensureJobContextForConversation(currentMessages);
|
||||
|
||||
// Re-render all messages with the new message included
|
||||
renderMessages();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.assecutor.votianlt.service;
|
||||
|
||||
import de.assecutor.votianlt.model.Job;
|
||||
import de.assecutor.votianlt.model.Message;
|
||||
import de.assecutor.votianlt.model.MessageContentType;
|
||||
import de.assecutor.votianlt.model.MessageOrigin;
|
||||
@@ -8,6 +9,7 @@ import de.assecutor.votianlt.dto.ChatMessageInboundPayload;
|
||||
import de.assecutor.votianlt.dto.ChatMessageOutboundPayload;
|
||||
import de.assecutor.votianlt.event.MessageReceivedEvent;
|
||||
import de.assecutor.votianlt.mqtt.MqttPublisher;
|
||||
import de.assecutor.votianlt.repository.JobRepository;
|
||||
import de.assecutor.votianlt.repository.MessageRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bson.types.ObjectId;
|
||||
@@ -23,12 +25,14 @@ import java.util.Optional;
|
||||
public class MessageService {
|
||||
|
||||
private final MessageRepository messageRepository;
|
||||
private final JobRepository jobRepository;
|
||||
private final MqttPublisher mqttPublisher;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public MessageService(MessageRepository messageRepository, MqttPublisher mqttPublisher,
|
||||
ApplicationEventPublisher eventPublisher) {
|
||||
public MessageService(MessageRepository messageRepository, JobRepository jobRepository,
|
||||
MqttPublisher mqttPublisher, ApplicationEventPublisher eventPublisher) {
|
||||
this.messageRepository = messageRepository;
|
||||
this.jobRepository = jobRepository;
|
||||
this.mqttPublisher = mqttPublisher;
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
@@ -66,7 +70,9 @@ public class MessageService {
|
||||
|
||||
public Message sendJobMessageToClient(String content, String sender, String receiver,
|
||||
MessageContentType contentType, ObjectId jobId, String jobNumber) {
|
||||
Message message = new Message(content, sender, receiver, MessageOrigin.SERVER, contentType, jobId, jobNumber);
|
||||
JobContext context = resolveJobContext(jobId, jobNumber);
|
||||
Message message = new Message(content, sender, receiver, MessageOrigin.SERVER, contentType,
|
||||
context.jobId(), context.jobNumber());
|
||||
message = saveMessage(message);
|
||||
publishMessageToMqtt(message, receiver);
|
||||
return message;
|
||||
@@ -79,8 +85,9 @@ public class MessageService {
|
||||
Message message;
|
||||
MessageContentType contentType = payload.contentType();
|
||||
if (payload.hasJobContext()) {
|
||||
JobContext context = resolveJobContext(payload.jobId(), payload.jobNumber());
|
||||
message = new Message(payload.content(), payload.sender(), payload.receiver(),
|
||||
MessageOrigin.CLIENT, contentType, payload.jobId(), payload.jobNumber());
|
||||
MessageOrigin.CLIENT, contentType, context.jobId(), context.jobNumber());
|
||||
} else {
|
||||
message = new Message(payload.content(), payload.sender(), payload.receiver(),
|
||||
MessageOrigin.CLIENT, contentType);
|
||||
@@ -222,4 +229,102 @@ public class MessageService {
|
||||
messageRepository.deleteById(messageId);
|
||||
log.info("Deleted message {}", messageId);
|
||||
}
|
||||
|
||||
public Optional<Job> findJobByIdentifier(String identifier) {
|
||||
if (identifier == null || identifier.isBlank()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<Job> jobOptional = Optional.empty();
|
||||
if (ObjectId.isValid(identifier)) {
|
||||
try {
|
||||
jobOptional = jobRepository.findById(new ObjectId(identifier));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
log.debug("Identifier {} could not be parsed as ObjectId: {}", identifier, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (jobOptional.isPresent()) {
|
||||
return jobOptional;
|
||||
}
|
||||
|
||||
return lookupJobByNumber(identifier);
|
||||
}
|
||||
|
||||
private JobContext resolveJobContext(ObjectId jobId, String jobNumber) {
|
||||
ObjectId resolvedJobId = jobId;
|
||||
String resolvedJobNumber = jobNumber;
|
||||
|
||||
Optional<Job> jobOptional = lookupJob(jobId, jobNumber);
|
||||
if (jobOptional.isPresent()) {
|
||||
Job job = jobOptional.get();
|
||||
resolvedJobId = job.getId();
|
||||
resolvedJobNumber = Optional.ofNullable(job.getJobNumber()).orElse(resolvedJobNumber);
|
||||
}
|
||||
|
||||
return new JobContext(resolvedJobId, resolvedJobNumber);
|
||||
}
|
||||
|
||||
private Optional<Job> lookupJob(ObjectId jobId, String jobNumber) {
|
||||
Optional<Job> jobOptional = Optional.empty();
|
||||
|
||||
if (jobId != null) {
|
||||
jobOptional = jobRepository.findById(jobId);
|
||||
if (jobOptional.isPresent()) {
|
||||
return jobOptional;
|
||||
}
|
||||
}
|
||||
|
||||
if (jobNumber == null || jobNumber.isBlank()) {
|
||||
return jobOptional;
|
||||
}
|
||||
|
||||
jobOptional = jobRepository.findByJobNumber(jobNumber);
|
||||
if (jobOptional.isPresent()) {
|
||||
return jobOptional;
|
||||
}
|
||||
|
||||
return lookupJobByNumber(jobNumber);
|
||||
}
|
||||
|
||||
private Optional<Job> lookupJobByNumber(String candidate) {
|
||||
if (candidate == null || candidate.isBlank()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String normalizedCandidate = normalizeJobToken(candidate);
|
||||
|
||||
Optional<Job> jobOptional = jobRepository.findByJobNumber(candidate);
|
||||
if (jobOptional.isPresent()) {
|
||||
return jobOptional;
|
||||
}
|
||||
|
||||
String relaxedCandidate = candidate.replace('_', ' ');
|
||||
if (!relaxedCandidate.equals(candidate)) {
|
||||
jobOptional = jobRepository.findByJobNumber(relaxedCandidate);
|
||||
if (jobOptional.isPresent()) {
|
||||
return jobOptional;
|
||||
}
|
||||
}
|
||||
|
||||
List<Job> fuzzyMatches = jobRepository.findByJobNumberContainingIgnoreCase(relaxedCandidate);
|
||||
if (fuzzyMatches.isEmpty() && !relaxedCandidate.equals(candidate)) {
|
||||
fuzzyMatches = jobRepository.findByJobNumberContainingIgnoreCase(candidate);
|
||||
}
|
||||
if (fuzzyMatches.isEmpty()) {
|
||||
fuzzyMatches = jobRepository.findAll();
|
||||
}
|
||||
|
||||
return fuzzyMatches.stream()
|
||||
.filter(job -> normalizeJobToken(job.getJobNumber()).equalsIgnoreCase(normalizedCandidate))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private String normalizeJobToken(String value) {
|
||||
return value == null ? "" : value.replaceAll("[^a-zA-Z0-9_-]", "_");
|
||||
}
|
||||
|
||||
private record JobContext(ObjectId jobId, String jobNumber) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user