+
+
+
+ {isRenaming ? (
+ setRenameValue(e.target.value)}
+ onBlur={handleRename}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') handleRename();
+ if (e.key === 'Escape') setRenaming(null);
+ }}
+ className="text-sm font-medium w-full bg-transparent border-b border-blue-500 outline-none"
+ style={{ color: 'var(--color-text-primary)' }}
+ />
+ ) : (
+
+ {file.name}
+
+ )}
+
+
+ );
+ };
return (
- {/* Top Banner (Template Gallery placeholder) */}
+ {/* Top Banner */}
-
Start a new document
+
Start a new {type === 'docs' ? 'document' : 'presentation'}
- {/* Blank Document */}
) : (
- {recentFiles.map(file => (
-
-
-
-
-
- {file.name}
-
-
-
- ))}
+ {recentFiles.map(file => renderFileCard(file))}
)}
+
+ {/* All Documents */}
+
+
+
All {title.toLowerCase()}
+
+ {loadingAll ? (
+
Loading...
+ ) : allFiles.length === 0 ? (
+
No {title.toLowerCase()} found in your drive.
+ ) : (
+
+ {allFiles.map(file => renderFileCard(file))}
+
+ )}
+
+
+
+ {/* Context Menu */}
+ {contextMenu && (
+
e.stopPropagation()}
+ >
+
+
+
+ )}
);
}
diff --git a/frontend/src/components/OnlyOfficeEditor.tsx b/frontend/src/components/OnlyOfficeEditor.tsx
index 0493833..1bae143 100644
--- a/frontend/src/components/OnlyOfficeEditor.tsx
+++ b/frontend/src/components/OnlyOfficeEditor.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useRef } from 'react';
import { DocumentEditor } from '@onlyoffice/document-editor-react';
import api from '@/lib/api';
@@ -17,12 +17,37 @@ interface OnlyOfficeEditorProps {
file: FileItem;
type: 'word' | 'cell' | 'slide';
onClose: () => void;
+ onRename?: (oldPath: string, newName: string, newPath: string) => void;
}
-export default function OnlyOfficeEditor({ file, type, onClose }: OnlyOfficeEditorProps) {
+export default function OnlyOfficeEditor({ file, type, onClose, onRename }: OnlyOfficeEditorProps) {
const [downloadToken, setDownloadToken] = useState
(null);
const [loadError, setLoadError] = useState(null);
const [config, setConfig] = useState(null);
+ const [isRenaming, setIsRenaming] = useState(false);
+ const [renameValue, setRenameValue] = useState(file.name);
+ const renameInputRef = useRef(null);
+
+ const handleRename = async () => {
+ const trimmed = renameValue.trim();
+ if (!trimmed || trimmed === file.name) {
+ setRenameValue(file.name);
+ setIsRenaming(false);
+ return;
+ }
+ try {
+ const res = await api.rename(file.path, trimmed);
+ // Build new path from the response or derive it
+ const dir = file.path.includes('/') ? file.path.substring(0, file.path.lastIndexOf('/') + 1) : '';
+ const newPath = dir + trimmed;
+ onRename?.(file.path, trimmed, newPath);
+ setIsRenaming(false);
+ } catch (err) {
+ console.error('Failed to rename', err);
+ setRenameValue(file.name);
+ setIsRenaming(false);
+ }
+ };
useEffect(() => {
// We need a short-lived download token to pass to the Document Server
@@ -106,7 +131,38 @@ export default function OnlyOfficeEditor({ file, type, onClose }: OnlyOfficeEdit
return (