Fixed issues:
AdminAutomationEventsPage.tsx — removed the unused _event variable entirely (it was never referenced). AutomationTemplatesPage.tsx — removed FaCopy from the import (no longer used after switching to type: 'copy'). AutomationsPage.tsx — same, removed the now-unused FaCopy import.
This commit is contained in:
parent
573a77be0b
commit
d2a2cfbd10
4 changed files with 64 additions and 15 deletions
|
|
@ -5,7 +5,7 @@ import { useFileContext } from '../../contexts/FileContext';
|
||||||
import { MessageDocument } from '../../components/UiComponents/Messages/MessagesTypes';
|
import { MessageDocument } from '../../components/UiComponents/Messages/MessagesTypes';
|
||||||
import { usePrompts } from '../usePrompts';
|
import { usePrompts } from '../usePrompts';
|
||||||
import { usePermissions } from '../usePermissions';
|
import { usePermissions } from '../usePermissions';
|
||||||
import { deleteFileFromMessageApi } from '../../api/workflowApi';
|
import { deleteFileFromMessageApi, deleteMessageApi } from '../../api/workflowApi';
|
||||||
import type { Workflow, WorkflowMessage } from '../../api/workflowApi';
|
import type { Workflow, WorkflowMessage } from '../../api/workflowApi';
|
||||||
import { useWorkflowLifecycle } from './useWorkflowLifecycle';
|
import { useWorkflowLifecycle } from './useWorkflowLifecycle';
|
||||||
import { useWorkflows } from './useWorkflows';
|
import { useWorkflows } from './useWorkflows';
|
||||||
|
|
@ -31,6 +31,9 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
const [selectedPromptId, setSelectedPromptId] = useState<string | null>(null);
|
const [selectedPromptId, setSelectedPromptId] = useState<string | null>(null);
|
||||||
const [workflowMode, setWorkflowMode] = useState<'Dynamic' | 'Automation' | null>(null);
|
const [workflowMode, setWorkflowMode] = useState<'Dynamic' | 'Automation' | null>(null);
|
||||||
const [selectedProviders, setSelectedProviders] = useState<string[]>([]); // AI provider selection (multiselect)
|
const [selectedProviders, setSelectedProviders] = useState<string[]>([]); // AI provider selection (multiselect)
|
||||||
|
const [deletedDocumentFileIds, setDeletedDocumentFileIds] = useState<Set<string>>(new Set());
|
||||||
|
const [deletedMessageIds, setDeletedMessageIds] = useState<Set<string>>(new Set());
|
||||||
|
const [deletingMessages, setDeletingMessages] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
const { checkPermission } = usePermissions();
|
const { checkPermission } = usePermissions();
|
||||||
const [playgroundUIPermission, setPlaygroundUIPermission] = useState<boolean>(true);
|
const [playgroundUIPermission, setPlaygroundUIPermission] = useState<boolean>(true);
|
||||||
|
|
@ -294,19 +297,28 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
}, [messages, optimisticMessage]);
|
}, [messages, optimisticMessage]);
|
||||||
|
|
||||||
const displayMessages = useMemo(() => {
|
const displayMessages = useMemo(() => {
|
||||||
const processedMessages = (messages || []).map((message: WorkflowMessage) => {
|
const processedMessages = (messages || [])
|
||||||
const files = (message as any).files as any[] | undefined;
|
// Filter out locally deleted messages
|
||||||
const documents = (message as any).documents as MessageDocument[] | undefined;
|
.filter((message: WorkflowMessage) => !deletedMessageIds.has(message.id))
|
||||||
|
.map((message: WorkflowMessage) => {
|
||||||
|
const files = (message as any).files as any[] | undefined;
|
||||||
|
const documents = (message as any).documents as MessageDocument[] | undefined;
|
||||||
|
|
||||||
|
let processedDocs = documents;
|
||||||
|
if (files && Array.isArray(files) && (!documents || documents.length === 0)) {
|
||||||
|
processedDocs = convertFilesToDocuments(files, message.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out locally deleted documents
|
||||||
|
if (processedDocs && deletedDocumentFileIds.size > 0) {
|
||||||
|
processedDocs = processedDocs.filter(doc => !deletedDocumentFileIds.has(doc.fileId));
|
||||||
|
}
|
||||||
|
|
||||||
if (files && Array.isArray(files) && (!documents || documents.length === 0)) {
|
|
||||||
return {
|
return {
|
||||||
...message,
|
...message,
|
||||||
documents: convertFilesToDocuments(files, message.id)
|
documents: processedDocs
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
|
|
||||||
return message;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If optimistic message is still active (backend "first" message not yet polled),
|
// If optimistic message is still active (backend "first" message not yet polled),
|
||||||
// show the optimistic message instead of any backend user messages to avoid duplicates.
|
// show the optimistic message instead of any backend user messages to avoid duplicates.
|
||||||
|
|
@ -324,7 +336,7 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return allMessages.sort(sortMessages);
|
return allMessages.sort(sortMessages);
|
||||||
}, [messages, optimisticMessage, workflowId]);
|
}, [messages, optimisticMessage, workflowId, deletedDocumentFileIds, deletedMessageIds]);
|
||||||
|
|
||||||
const handleFileUpload = useCallback(async (file: File): Promise<{ success: boolean; data: any }> => {
|
const handleFileUpload = useCallback(async (file: File): Promise<{ success: boolean; data: any }> => {
|
||||||
const result = await fileContext.handleFileUpload(file, workflowId || undefined);
|
const result = await fileContext.handleFileUpload(file, workflowId || undefined);
|
||||||
|
|
@ -414,6 +426,9 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
const handleFileDelete = useCallback(async (file: WorkflowFile) => {
|
const handleFileDelete = useCallback(async (file: WorkflowFile) => {
|
||||||
if (!file.fileId) return;
|
if (!file.fileId) return;
|
||||||
|
|
||||||
|
// Immediately remove document from UI for instant feedback
|
||||||
|
setDeletedDocumentFileIds(prev => new Set([...prev, file.fileId]));
|
||||||
|
|
||||||
const success = await fileContext.handleFileDelete(file.fileId, () => {
|
const success = await fileContext.handleFileDelete(file.fileId, () => {
|
||||||
setPendingFiles(prev => prev.filter(f => f.fileId !== file.fileId));
|
setPendingFiles(prev => prev.filter(f => f.fileId !== file.fileId));
|
||||||
});
|
});
|
||||||
|
|
@ -434,6 +449,13 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Restore document in UI on failure
|
||||||
|
setDeletedDocumentFileIds(prev => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
next.delete(file.fileId);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [workflowId, messages, fileContext, request]);
|
}, [workflowId, messages, fileContext, request]);
|
||||||
|
|
||||||
|
|
@ -448,6 +470,32 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
await fileContext.handleFileDownload(file.fileId, file.fileName);
|
await fileContext.handleFileDownload(file.fileId, file.fileName);
|
||||||
}, [fileContext]);
|
}, [fileContext]);
|
||||||
|
|
||||||
|
const handleMessageDelete = useCallback(async (messageId: string) => {
|
||||||
|
if (!workflowId || !messageId) return;
|
||||||
|
|
||||||
|
// Immediately remove message from UI for instant feedback
|
||||||
|
setDeletedMessageIds(prev => new Set([...prev, messageId]));
|
||||||
|
setDeletingMessages(prev => new Set([...prev, messageId]));
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteMessageApi(request, workflowId, messageId);
|
||||||
|
} catch (error: any) {
|
||||||
|
// Restore message in UI on failure
|
||||||
|
setDeletedMessageIds(prev => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
next.delete(messageId);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
console.error('Failed to delete message:', error);
|
||||||
|
} finally {
|
||||||
|
setDeletingMessages(prev => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
next.delete(messageId);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [workflowId, request]);
|
||||||
|
|
||||||
const onInputChange = useCallback((value: string) => {
|
const onInputChange = useCallback((value: string) => {
|
||||||
setInputValue(value);
|
setInputValue(value);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -780,6 +828,8 @@ export function useDashboardInputForm(instanceId: string) {
|
||||||
previewingFiles: fileContext.previewingFiles,
|
previewingFiles: fileContext.previewingFiles,
|
||||||
downloadingFiles: fileContext.downloadingFiles,
|
downloadingFiles: fileContext.downloadingFiles,
|
||||||
handleFileDownload,
|
handleFileDownload,
|
||||||
|
handleMessageDelete,
|
||||||
|
deletingMessages,
|
||||||
isFileAttachmentPopupOpen,
|
isFileAttachmentPopupOpen,
|
||||||
setIsFileAttachmentPopupOpen,
|
setIsFileAttachmentPopupOpen,
|
||||||
allUserFiles: fileContext.files || [],
|
allUserFiles: fileContext.files || [],
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ export const AdminAutomationEventsPage: React.FC = () => {
|
||||||
const _handleDelete = useCallback(async (eventId: string) => {
|
const _handleDelete = useCallback(async (eventId: string) => {
|
||||||
try {
|
try {
|
||||||
setError(null);
|
setError(null);
|
||||||
const _event = events.find(e => e.eventId === eventId);
|
|
||||||
const encodedId = encodeURIComponent(eventId);
|
const encodedId = encodeURIComponent(eventId);
|
||||||
await api.post(`/api/admin/automation-events/${encodedId}/remove`);
|
await api.post(`/api/admin/automation-events/${encodedId}/remove`);
|
||||||
setEvents(prev => prev.filter(e => e.eventId !== eventId));
|
setEvents(prev => prev.filter(e => e.eventId !== eventId));
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import React, { useState, useMemo, useEffect } from 'react';
|
||||||
import { useAutomationTemplates, type AutomationTemplate } from '../../hooks/useAutomations';
|
import { useAutomationTemplates, type AutomationTemplate } from '../../hooks/useAutomations';
|
||||||
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
||||||
import { AutomationEditor } from '../../components/AutomationEditor';
|
import { AutomationEditor } from '../../components/AutomationEditor';
|
||||||
import { FaSync, FaPlus, FaFileAlt, FaCopy, FaLock } from 'react-icons/fa';
|
import { FaSync, FaPlus, FaFileAlt, FaLock } from 'react-icons/fa';
|
||||||
import { useToast } from '../../contexts/ToastContext';
|
import { useToast } from '../../contexts/ToastContext';
|
||||||
import { useCurrentUser } from '../../hooks/useUsers';
|
import { useCurrentUser } from '../../hooks/useUsers';
|
||||||
import styles from '../admin/Admin.module.css';
|
import styles from '../admin/Admin.module.css';
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import React, { useState, useMemo, useEffect, useCallback, useRef } from 'react'
|
||||||
import { useAutomations, useAutomationOperations, AutomationTemplate, Automation } from '../../hooks/useAutomations';
|
import { useAutomations, useAutomationOperations, AutomationTemplate, Automation } from '../../hooks/useAutomations';
|
||||||
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
||||||
import { AutomationEditor } from '../../components/AutomationEditor';
|
import { AutomationEditor } from '../../components/AutomationEditor';
|
||||||
import { FaSync, FaRobot, FaRocket, FaPlus, FaFileAlt, FaStop, FaList, FaTimes, FaCheck, FaExclamationCircle, FaSpinner, FaCopy } from 'react-icons/fa';
|
import { FaSync, FaRobot, FaRocket, FaPlus, FaFileAlt, FaStop, FaList, FaTimes, FaCheck, FaExclamationCircle, FaSpinner } from 'react-icons/fa';
|
||||||
import { useToast } from '../../contexts/ToastContext';
|
import { useToast } from '../../contexts/ToastContext';
|
||||||
import { useApiRequest } from '../../hooks/useApi';
|
import { useApiRequest } from '../../hooks/useApi';
|
||||||
import { useFeatureStore } from '../../stores/featureStore';
|
import { useFeatureStore } from '../../stores/featureStore';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue