히스토리 패널 작업 완료.

This commit is contained in:
sheetEasy AI Team
2025-06-27 14:47:47 +09:00
parent e5ee01553a
commit b09a417291
4 changed files with 164 additions and 18 deletions

View File

@@ -8,7 +8,6 @@ import {
} from "@univerjs/presets"; } from "@univerjs/presets";
import { UniverSheetsCorePreset } from "@univerjs/presets/preset-sheets-core"; import { UniverSheetsCorePreset } from "@univerjs/presets/preset-sheets-core";
import UniverPresetSheetsCoreEnUS from "@univerjs/presets/preset-sheets-core/locales/en-US"; import UniverPresetSheetsCoreEnUS from "@univerjs/presets/preset-sheets-core/locales/en-US";
import { UniverInstanceType } from "@univerjs/core";
// Presets CSS import // Presets CSS import
import "@univerjs/presets/lib/styles/preset-sheets-core.css"; import "@univerjs/presets/lib/styles/preset-sheets-core.css";
@@ -327,7 +326,7 @@ const TestSheetViewer: React.FC = () => {
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
const mountedRef = useRef<boolean>(false); const mountedRef = useRef<boolean>(false);
const [isInitialized, setIsInitialized] = useState<boolean>(false); const [, setIsInitialized] = useState<boolean>(false);
const [showUploadOverlay, setShowUploadOverlay] = useState(true); const [showUploadOverlay, setShowUploadOverlay] = useState(true);
const [isDragOver, setIsDragOver] = useState(false); const [isDragOver, setIsDragOver] = useState(false);
const [isProcessing, setIsProcessing] = useState(false); const [isProcessing, setIsProcessing] = useState(false);
@@ -355,12 +354,73 @@ const TestSheetViewer: React.FC = () => {
} }
}; };
const handleHistoryReapply = (entry: HistoryEntry) => { const handleHistoryReapply = useCallback(async (entry: HistoryEntry) => {
// 히스토리 항목 재적용 로직 console.log("🔄 히스토리 재적용 시작:", entry);
// 1. 프롬프트 입력창에 기존 프롬프트 설정
setPrompt(entry.prompt); setPrompt(entry.prompt);
console.log("🔄 히스토리 재적용:", entry);
// TODO: 실제 액션 재실행 로직 구현 // 2. 확인 대화상자
}; const confirmReapply = window.confirm(
`다음 프롬프트를 다시 실행하시겠습니까?\n\n"${entry.prompt}"\n\n범위: ${entry.range} | 시트: ${entry.sheetName}`,
);
if (!confirmReapply) {
return;
}
// 3. 재적용 히스토리 항목 생성
const reapplyHistoryId = addHistoryEntry(
`[재적용] ${entry.prompt}`,
entry.range,
entry.sheetName,
[],
"pending",
);
try {
// 4. AI 프로세서 실행
const result = await aiProcessor.processPrompt(entry.prompt, true);
// 5. 결과에 따라 히스토리 업데이트
if (result.success) {
updateHistoryEntry(reapplyHistoryId, {
status: "success",
actions:
result.appliedCells?.map((cell) => ({
type: "formula" as const,
range: cell,
formula: `=재적용 수식`, // TODO: 실제 수식 정보 저장
})) || [],
});
// 성공 시 팝업 제거 (히스토리 패널에서 확인 가능)
console.log(`✅ 재적용 성공: ${result.message}`);
} else {
updateHistoryEntry(reapplyHistoryId, {
status: "error",
error: result.message,
actions: [],
});
// 실패 알림
alert(`❌ 재적용 실패: ${result.message}`);
}
} catch (error) {
// 6. 예외 처리
const errorMessage =
error instanceof Error
? error.message
: "알 수 없는 오류가 발생했습니다.";
updateHistoryEntry(reapplyHistoryId, {
status: "error",
error: errorMessage,
actions: [],
});
alert(`❌ 재적용 중 오류: ${errorMessage}`);
}
}, []);
// 새 히스토리 항목 추가 함수 // 새 히스토리 항목 추가 함수
const addHistoryEntry = ( const addHistoryEntry = (
@@ -383,8 +443,87 @@ const TestSheetViewer: React.FC = () => {
}; };
setHistory((prev) => [newEntry, ...prev]); // 최신 항목을 맨 위에 setHistory((prev) => [newEntry, ...prev]); // 최신 항목을 맨 위에
return newEntry.id; // 히스토리 ID 반환하여 나중에 업데이트 가능
}; };
// 기존 히스토리 항목 업데이트 함수
const updateHistoryEntry = (
id: string,
updates: Partial<Omit<HistoryEntry, "id" | "timestamp">>,
) => {
setHistory((prev) =>
prev.map((entry) => (entry.id === id ? { ...entry, ...updates } : entry)),
);
};
// AI 프롬프트 실행 핸들러 (히스토리 연동)
const handlePromptExecute = useCallback(async () => {
if (!prompt.trim()) {
alert("프롬프트를 입력해주세요.");
return;
}
const currentRange = appStore.selectedRange
? rangeToAddress(appStore.selectedRange.range)
: "A1";
const currentSheetName = "Sheet1"; // TODO: 실제 시트명 가져오기
// 1. 히스토리에 pending 상태로 추가
const historyId = addHistoryEntry(
prompt.trim(),
currentRange,
currentSheetName,
[],
"pending",
);
try {
// 2. AI 프로세서 실행
const result = await aiProcessor.processPrompt(prompt.trim(), true);
// 3. 결과에 따라 히스토리 업데이트
if (result.success) {
updateHistoryEntry(historyId, {
status: "success",
actions:
result.appliedCells?.map((cell) => ({
type: "formula" as const,
range: cell,
formula: `=수식`, // TODO: 실제 수식 정보 저장
})) || [],
});
// 성공 시 팝업 제거 (히스토리 패널에서 확인 가능)
console.log(`${result.message}`);
} else {
updateHistoryEntry(historyId, {
status: "error",
error: result.message,
actions: [],
});
// 실패 알림
alert(`${result.message}`);
}
} catch (error) {
// 4. 예외 처리
const errorMessage =
error instanceof Error
? error.message
: "알 수 없는 오류가 발생했습니다.";
updateHistoryEntry(historyId, {
status: "error",
error: errorMessage,
actions: [],
});
alert(`❌ 처리 중 오류: ${errorMessage}`);
}
// 5. 프롬프트 입력창 초기화
setPrompt("");
}, [prompt, appStore.selectedRange]);
// Univer 초기화 함수 (Presets 기반) // Univer 초기화 함수 (Presets 기반)
const initializeUniver = useCallback( const initializeUniver = useCallback(
async (workbookData?: any) => { async (workbookData?: any) => {
@@ -769,8 +908,10 @@ const TestSheetViewer: React.FC = () => {
<PromptInput <PromptInput
value={prompt} value={prompt}
onChange={(e) => setPrompt(e.target.value)} onChange={(e) => setPrompt(e.target.value)}
onExecute={handlePromptExecute}
onHistoryToggle={handleHistoryToggle} onHistoryToggle={handleHistoryToggle}
historyCount={history.length} historyCount={history.length}
disabled={isProcessing}
/> />
{/* 히스토리 패널 - 파일이 업로드된 후에만 표시 */} {/* 히스토리 패널 - 파일이 업로드된 후에만 표시 */}

View File

@@ -24,18 +24,16 @@ const PromptInput: React.FC<PromptInputProps> = ({
value, value,
onChange, onChange,
onExecute, onExecute,
disabled = true, disabled: _disabled = true,
maxLength = 500, maxLength = 500,
onHistoryToggle, onHistoryToggle,
historyCount, historyCount,
}) => { }) => {
const textareaRef = useRef<HTMLTextAreaElement>(null); const textareaRef = useRef<HTMLTextAreaElement>(null);
const [showCellInsertFeedback, setShowCellInsertFeedback] = useState(false); const [, setShowCellInsertFeedback] = useState(false);
const [lastInsertedCell, setLastInsertedCell] = useState<string | null>(null); const [, setLastInsertedCell] = useState<string | null>(null);
const [currentSelectedCell, setCurrentSelectedCell] = useState<string | null>( const [, setCurrentSelectedCell] = useState<string | null>(null);
null, const [, setProcessingMessage] = useState<string>("");
);
const [processingMessage, setProcessingMessage] = useState<string>("");
const cellAddressToInsert = useAppStore((state) => state.cellAddressToInsert); const cellAddressToInsert = useAppStore((state) => state.cellAddressToInsert);
const setCellAddressToInsert = useAppStore( const setCellAddressToInsert = useAppStore(
@@ -53,7 +51,7 @@ const PromptInput: React.FC<PromptInputProps> = ({
}, [cellAddressToInsert]); }, [cellAddressToInsert]);
/** /**
* 전송하기 버튼 클릭 핸들러 * 전송하기 버튼 클릭 핸들러 - 상위 컴포넌트 onExecute 사용 또는 기본 로직
*/ */
const handleExecute = async () => { const handleExecute = async () => {
if (!value.trim()) { if (!value.trim()) {
@@ -66,6 +64,14 @@ const PromptInput: React.FC<PromptInputProps> = ({
return; return;
} }
// 상위 컴포넌트에서 onExecute를 전달받은 경우 해당 함수 사용
if (onExecute) {
console.log("🚀 상위 컴포넌트 onExecute 함수 호출");
await onExecute();
return;
}
// 폴백: 기본 AI 프로세서 직접 호출
setProcessingMessage("AI가 요청을 처리하고 있습니다..."); setProcessingMessage("AI가 요청을 처리하고 있습니다...");
try { try {

View File

@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { Card, CardContent, CardHeader, CardTitle } from "./card"; import { Card, CardContent, CardHeader } from "./card";
import { Button } from "./button"; import { Button } from "./button";
import type { HistoryPanelProps, HistoryEntry } from "../../types/ai"; import type { HistoryPanelProps, HistoryEntry } from "../../types/ai";
import { cn } from "../../lib/utils"; import { cn } from "../../lib/utils";

View File

@@ -41,7 +41,6 @@ export default defineConfig({
"@univerjs/sheets-formula-ui", "@univerjs/sheets-formula-ui",
"@univerjs/sheets-numfmt", "@univerjs/sheets-numfmt",
"@univerjs/sheets-numfmt-ui", "@univerjs/sheets-numfmt-ui",
"@univerjs/facade",
], ],
}, },
@@ -69,7 +68,7 @@ export default defineConfig({
"@univerjs/sheets-numfmt-ui", "@univerjs/sheets-numfmt-ui",
], ],
"univer-docs": ["@univerjs/docs", "@univerjs/docs-ui"], "univer-docs": ["@univerjs/docs", "@univerjs/docs-ui"],
"univer-ui": ["@univerjs/ui", "@univerjs/facade"], "univer-ui": ["@univerjs/ui"],
}, },
}, },
}, },