fixed 3 issues
This commit is contained in:
parent
def3ba06de
commit
a83aa31df7
5 changed files with 179 additions and 11 deletions
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { FaExclamationTriangle } from 'react-icons/fa';
|
||||
import { IoIosTrash, IoIosCheckmark, IoIosClose } from 'react-icons/io';
|
||||
import { Message } from '../MessagesTypes';
|
||||
import { formatTimestamp } from '../MessageUtils';
|
||||
import { DocumentItem, ActionInfo } from '../MessageParts';
|
||||
|
|
@ -21,6 +22,8 @@ export interface ChatMessageProps {
|
|||
removingFiles?: Set<string>;
|
||||
downloadingFiles?: Set<string>;
|
||||
workflowId?: string;
|
||||
onMessageDelete?: (messageId: string) => Promise<void>;
|
||||
deletingMessages?: Set<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,12 +41,36 @@ export const ChatMessage: React.FC<ChatMessageProps> = ({
|
|||
previewingFiles,
|
||||
removingFiles,
|
||||
downloadingFiles,
|
||||
workflowId
|
||||
workflowId,
|
||||
onMessageDelete,
|
||||
deletingMessages
|
||||
}) => {
|
||||
const isUser = message.role?.toLowerCase() === 'user';
|
||||
const isError = message.actionProgress === 'fail' || message.actionProgress === 'error';
|
||||
const messageClass = isUser ? styles.messageUser : styles.messageAssistant;
|
||||
const errorClass = isError ? styles.messageError : '';
|
||||
const isDeleting = deletingMessages?.has(message.id) || false;
|
||||
|
||||
// Message delete 2-click confirmation state
|
||||
const [isConfirmingDelete, setIsConfirmingDelete] = useState(false);
|
||||
|
||||
const handleDeleteClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setIsConfirmingDelete(true);
|
||||
};
|
||||
|
||||
const handleConfirmDelete = async (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setIsConfirmingDelete(false);
|
||||
if (onMessageDelete && message.id) {
|
||||
await onMessageDelete(message.id);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancelDelete = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setIsConfirmingDelete(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${styles.message} ${messageClass} ${errorClass}`}>
|
||||
|
|
@ -158,12 +185,47 @@ export const ChatMessage: React.FC<ChatMessageProps> = ({
|
|||
{/* Action information (shown only for assistant messages) */}
|
||||
{!isUser && <ActionInfo message={message} />}
|
||||
|
||||
{/* Timestamp */}
|
||||
{message.publishedAt && (
|
||||
<div className={styles.messageTimestamp}>
|
||||
{formatTimestamp(message.publishedAt)}
|
||||
</div>
|
||||
)}
|
||||
{/* Timestamp and message actions */}
|
||||
<div className={styles.messageFooter}>
|
||||
{message.publishedAt && (
|
||||
<div className={styles.messageTimestamp}>
|
||||
{formatTimestamp(message.publishedAt)}
|
||||
</div>
|
||||
)}
|
||||
{onMessageDelete && message.id && (
|
||||
<div className={styles.messageActions}>
|
||||
{isConfirmingDelete ? (
|
||||
<div className={styles.messageDeleteConfirm}>
|
||||
<button
|
||||
onClick={handleConfirmDelete}
|
||||
className={styles.messageDeleteConfirmBtn}
|
||||
title="Löschen bestätigen"
|
||||
disabled={isDeleting}
|
||||
>
|
||||
<IoIosCheckmark />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCancelDelete}
|
||||
className={styles.messageDeleteCancelBtn}
|
||||
title="Abbrechen"
|
||||
disabled={isDeleting}
|
||||
>
|
||||
<IoIosClose />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
onClick={handleDeleteClick}
|
||||
className={styles.messageDeleteBtn}
|
||||
title="Nachricht löschen"
|
||||
disabled={isDeleting}
|
||||
>
|
||||
<IoIosTrash />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -512,11 +512,17 @@
|
|||
border-top-color: var(--color-gray-disabled);
|
||||
}
|
||||
|
||||
.messageFooter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 4px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.messageTimestamp {
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
margin-top: 4px;
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.messageUser .messageTimestamp {
|
||||
|
|
@ -527,6 +533,92 @@
|
|||
color: var(--color-gray);
|
||||
}
|
||||
|
||||
/* Message action buttons (delete) */
|
||||
.messageActions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
|
||||
.message:hover .messageActions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.messageDeleteBtn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
color: var(--color-gray);
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.messageDeleteBtn:hover {
|
||||
color: var(--color-danger, #dc3545);
|
||||
background: rgba(220, 53, 69, 0.1);
|
||||
}
|
||||
|
||||
.messageDeleteBtn:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.messageUser .messageDeleteBtn {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.messageUser .messageDeleteBtn:hover {
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/* Message delete confirmation */
|
||||
.messageDeleteConfirm {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
background: var(--color-secondary);
|
||||
border-radius: 12px;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.messageDeleteConfirmBtn,
|
||||
.messageDeleteCancelBtn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
border-radius: 50%;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
min-width: 22px;
|
||||
min-height: 22px;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.messageDeleteConfirmBtn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.messageDeleteCancelBtn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.messageDeleteConfirmBtn:disabled,
|
||||
.messageDeleteCancelBtn:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.messageSummary {
|
||||
padding: 8px 12px;
|
||||
border-radius: var(--object-radius-small);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ const Messages: React.FC<MessagesProps> = ({
|
|||
previewingFiles,
|
||||
removingFiles,
|
||||
downloadingFiles,
|
||||
workflowId
|
||||
workflowId,
|
||||
onMessageDelete,
|
||||
deletingMessages
|
||||
}) => {
|
||||
if (!messages || messages.length === 0) {
|
||||
return (
|
||||
|
|
@ -89,6 +91,8 @@ const Messages: React.FC<MessagesProps> = ({
|
|||
removingFiles={removingFiles}
|
||||
downloadingFiles={downloadingFiles}
|
||||
workflowId={workflowId}
|
||||
onMessageDelete={onMessageDelete}
|
||||
deletingMessages={deletingMessages}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -116,5 +116,11 @@ export interface MessagesProps {
|
|||
removingFiles?: Set<string>;
|
||||
downloadingFiles?: Set<string>;
|
||||
workflowId?: string;
|
||||
|
||||
/**
|
||||
* Message delete handler
|
||||
*/
|
||||
onMessageDelete?: (messageId: string) => Promise<void>;
|
||||
deletingMessages?: Set<string>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ export const PlaygroundPage: React.FC = () => {
|
|||
deletingFiles,
|
||||
previewingFiles,
|
||||
downloadingFiles,
|
||||
handleMessageDelete,
|
||||
deletingMessages,
|
||||
selectedProviders,
|
||||
onProvidersChange,
|
||||
} = hookData;
|
||||
|
|
@ -349,6 +351,8 @@ export const PlaygroundPage: React.FC = () => {
|
|||
previewingFiles={previewingFiles}
|
||||
downloadingFiles={downloadingFiles}
|
||||
workflowId={workflowId}
|
||||
onMessageDelete={handleMessageDelete}
|
||||
deletingMessages={deletingMessages}
|
||||
emptyMessage="Keine Nachrichten"
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue