Fix new file creation on Instructions tab silently failing
New files created via the "+" button were not appearing in the file tree because visibleFilePaths was derived solely from bundle API data. The selection reset effect would also immediately undo the file selection. Add pendingFiles state to track newly created files until they are saved to disk. Include pending files in visibleFilePaths, guard the selection reset effect, and clean up pending state after successful save. Fixes PAP-563 Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
e99fa66daf
commit
6000bb4ee2
1 changed files with 9 additions and 6 deletions
|
|
@ -897,8 +897,8 @@ export function AgentDetail() {
|
||||||
items={[
|
items={[
|
||||||
{ value: "dashboard", label: "Dashboard" },
|
{ value: "dashboard", label: "Dashboard" },
|
||||||
{ value: "instructions", label: "Instructions" },
|
{ value: "instructions", label: "Instructions" },
|
||||||
{ value: "configuration", label: "Configuration" },
|
|
||||||
{ value: "skills", label: "Skills" },
|
{ value: "skills", label: "Skills" },
|
||||||
|
{ value: "configuration", label: "Configuration" },
|
||||||
{ value: "runs", label: "Runs" },
|
{ value: "runs", label: "Runs" },
|
||||||
{ value: "budget", label: "Budget" },
|
{ value: "budget", label: "Budget" },
|
||||||
]}
|
]}
|
||||||
|
|
@ -1515,6 +1515,7 @@ function PromptsTab({
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [newFilePath, setNewFilePath] = useState("");
|
const [newFilePath, setNewFilePath] = useState("");
|
||||||
const [showNewFileInput, setShowNewFileInput] = useState(false);
|
const [showNewFileInput, setShowNewFileInput] = useState(false);
|
||||||
|
const [pendingFiles, setPendingFiles] = useState<string[]>([]);
|
||||||
const [expandedDirs, setExpandedDirs] = useState<Set<string>>(new Set());
|
const [expandedDirs, setExpandedDirs] = useState<Set<string>>(new Set());
|
||||||
const [filePanelWidth, setFilePanelWidth] = useState(260);
|
const [filePanelWidth, setFilePanelWidth] = useState(260);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
@ -1559,9 +1560,9 @@ function PromptsTab({
|
||||||
);
|
);
|
||||||
const visibleFilePaths = useMemo(
|
const visibleFilePaths = useMemo(
|
||||||
() => bundleMatchesDraft
|
() => bundleMatchesDraft
|
||||||
? [...new Set([currentEntryFile, ...fileOptions])]
|
? [...new Set([currentEntryFile, ...fileOptions, ...pendingFiles])]
|
||||||
: [currentEntryFile],
|
: [currentEntryFile, ...pendingFiles],
|
||||||
[bundleMatchesDraft, currentEntryFile, fileOptions],
|
[bundleMatchesDraft, currentEntryFile, fileOptions, pendingFiles],
|
||||||
);
|
);
|
||||||
const fileTree = useMemo(
|
const fileTree = useMemo(
|
||||||
() => buildFileTree(Object.fromEntries(visibleFilePaths.map((filePath) => [filePath, ""]))),
|
() => buildFileTree(Object.fromEntries(visibleFilePaths.map((filePath) => [filePath, ""]))),
|
||||||
|
|
@ -1598,6 +1599,7 @@ function PromptsTab({
|
||||||
agentsApi.saveInstructionsFile(agent.id, data, companyId),
|
agentsApi.saveInstructionsFile(agent.id, data, companyId),
|
||||||
onMutate: () => setAwaitingRefresh(true),
|
onMutate: () => setAwaitingRefresh(true),
|
||||||
onSuccess: (_, variables) => {
|
onSuccess: (_, variables) => {
|
||||||
|
setPendingFiles((prev) => prev.filter((f) => f !== variables.path));
|
||||||
queryClient.invalidateQueries({ queryKey: queryKeys.agents.instructionsBundle(agent.id) });
|
queryClient.invalidateQueries({ queryKey: queryKeys.agents.instructionsBundle(agent.id) });
|
||||||
queryClient.invalidateQueries({ queryKey: queryKeys.agents.instructionsFile(agent.id, variables.path) });
|
queryClient.invalidateQueries({ queryKey: queryKeys.agents.instructionsFile(agent.id, variables.path) });
|
||||||
queryClient.invalidateQueries({ queryKey: queryKeys.agents.detail(agent.id) });
|
queryClient.invalidateQueries({ queryKey: queryKeys.agents.detail(agent.id) });
|
||||||
|
|
@ -1636,10 +1638,10 @@ function PromptsTab({
|
||||||
if (selectedFile !== bundle.entryFile) setSelectedFile(bundle.entryFile);
|
if (selectedFile !== bundle.entryFile) setSelectedFile(bundle.entryFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!availablePaths.includes(selectedFile) && selectedFile !== currentEntryFile) {
|
if (!availablePaths.includes(selectedFile) && selectedFile !== currentEntryFile && !pendingFiles.includes(selectedFile)) {
|
||||||
setSelectedFile(availablePaths.includes(bundle.entryFile) ? bundle.entryFile : availablePaths[0]!);
|
setSelectedFile(availablePaths.includes(bundle.entryFile) ? bundle.entryFile : availablePaths[0]!);
|
||||||
}
|
}
|
||||||
}, [bundle, bundleMatchesDraft, currentEntryFile, selectedFile]);
|
}, [bundle, bundleMatchesDraft, currentEntryFile, pendingFiles, selectedFile]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const nextExpanded = new Set<string>();
|
const nextExpanded = new Set<string>();
|
||||||
|
|
@ -1998,6 +2000,7 @@ function PromptsTab({
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const candidate = newFilePath.trim();
|
const candidate = newFilePath.trim();
|
||||||
if (!candidate || candidate.includes("..")) return;
|
if (!candidate || candidate.includes("..")) return;
|
||||||
|
setPendingFiles((prev) => prev.includes(candidate) ? prev : [...prev, candidate]);
|
||||||
setSelectedFile(candidate);
|
setSelectedFile(candidate);
|
||||||
setDraft("");
|
setDraft("");
|
||||||
setNewFilePath("");
|
setNewFilePath("");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue