fi.evolver.ai.vaadin.component.ChatHistoryAvatarItem Maven / Gradle / Ivy
package fi.evolver.ai.vaadin.component;
import java.io.Serial;
import java.util.List;
import java.util.Map;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.avatar.Avatar;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.QueryParameters;
import com.vaadin.flow.theme.lumo.LumoUtility;
import fi.evolver.ai.vaadin.ChatHistoryConfiguration;
import fi.evolver.ai.vaadin.component.form.StarRatingComponent;
import fi.evolver.ai.vaadin.entity.Chat;
import fi.evolver.ai.vaadin.entity.ChatMessage;
import fi.evolver.ai.vaadin.entity.ChatMessage.ChatMessageRole;
import fi.evolver.ai.vaadin.view.ChatHistoryAction;
import fi.evolver.utils.DateUtils;
public class ChatHistoryAvatarItem extends Composite implements HasSize {
@Serial
private static final long serialVersionUID = 1L;
private final Chat chat;
private final ChatHistoryAction historyAction;
private final ChatHistoryConfiguration config;
public ChatHistoryAvatarItem(Chat chat, ChatHistoryConfiguration config, ChatHistoryAction historyAction) {
this.chat = chat;
this.historyAction = historyAction;
this.config = config;
generateContent();
}
private void generateContent() {
HorizontalLayout containerLayout = new HorizontalLayout();
getContent().setAlignItems(FlexComponent.Alignment.CENTER);
Span headingDate = new Span(chat.getStartTime().format(DateUtils.FORMAT_DATE_TIME_FI));
Span headingSummary = new Span(chat.getSummary());
Span description = new Span(getDescription(chat.getChatMessages()));
description.getStyle()
.set("color", "var(--lumo-secondary-text-color)")
.set("font-size", "var(--lumo-font-size-s)");
headingDate.addClassName(LumoUtility.FontWeight.BOLD);
VerticalLayout chatLayout = new VerticalLayout(headingDate, headingSummary, description);
chatLayout.setPadding(false);
chatLayout.setSpacing(false);
chatLayout.setWidth("500px");
chatLayout.addClickListener(e -> handleOnClickEvent());
containerLayout.setWidth("600px");
containerLayout.setAlignItems(FlexComponent.Alignment.CENTER);
containerLayout.add(
chatLayout,
createFavoriteIcon(),
createEditChatSummaryIcon(),
createRemoveChatIcon(),
createChatRatingButton());
getContent().add(containerLayout);
getContent().getStyle().set("line-height", "var(--lumo-line-height-m)");
getContent().getStyle().setCursor("pointer");
setAvatar(new Avatar());
}
private Icon createRemoveChatIcon() {
Icon icon = VaadinIcon.TRASH.create();
icon.setTooltipText(getTranslation("component.chatHistoryAvatarItem.removeChat"));
icon.addClickListener(e -> historyAction.showRemovalDialog(chat));
return icon;
}
private Icon createEditChatSummaryIcon() {
Icon icon = VaadinIcon.EDIT.create();
icon.setTooltipText(getTranslation("component.chatHistoryAvatarItem.renameChat"));
icon.addClickListener(e -> historyAction.showEditDialog(chat));
return icon;
}
private Icon createFavoriteIcon() {
Icon icon = chat.isFavorite() ? VaadinIcon.STAR.create() : VaadinIcon.STAR_O.create();
icon.setTooltipText(chat.isFavorite() ?
getTranslation("component.chatHistoryAvatarItem.removeFromFavorites") :
getTranslation("component.chatHistoryAvatarItem.saveToFavorites"));
icon.addClickListener(e -> historyAction.toggleFavorite(chat));
return icon;
}
private StarRatingComponent createChatRatingButton() {
StarRatingComponent rating = new StarRatingComponent(chat.getChatRating(), this::getTranslation);
rating.addValueChangeListener(val -> historyAction.setChatRating(chat, val));
rating.addClassName(LumoUtility.Padding.Left.SMALL);
return rating;
}
private void handleOnClickEvent() {
UI.getCurrent().navigate(config.route(), new QueryParameters(Map.of("chatId", List.of(chat.getChatId()))));
}
public void setAvatar(Avatar avatar) {
if (getContent().getComponentAt(0) instanceof Avatar existing)
existing.removeFromParent();
getContent().addComponentAsFirst(avatar);
}
private static String getDescription(List messages) {
ChatMessage message = messages.stream()
.filter(m -> m.getRole() == ChatMessageRole.USER)
.findFirst()
.orElse(messages.get(0));
if (message == null || message.getMessage() == null)
return "";
return message.getMessage().length() > 150 ?
"%s...".formatted(message.getMessage().substring(0, 150)) :
message.getMessage();
}
}