mirror of
https://github.com/lordmathis/lemma.git
synced 2025-12-22 17:44:25 +00:00
Add FolderSelector component and integrate with CreateFileModal
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Modal, TextInput, Button, Group, Box } from '@mantine/core';
|
||||
import { Modal, TextInput, Button, Group, Box, Popover, ActionIcon, Text } from '@mantine/core';
|
||||
import { IconFolderOpen } from '@tabler/icons-react';
|
||||
import { useModalContext } from '../../../contexts/ModalContext';
|
||||
import { useFileList } from '../../../hooks/useFileList';
|
||||
import { FolderSelector } from '../../files/FolderSelector';
|
||||
|
||||
interface CreateFileModalProps {
|
||||
onCreateFile: (fileName: string) => Promise<void>;
|
||||
@@ -8,16 +11,49 @@ interface CreateFileModalProps {
|
||||
|
||||
const CreateFileModal: React.FC<CreateFileModalProps> = ({ onCreateFile }) => {
|
||||
const [fileName, setFileName] = useState<string>('');
|
||||
const [selectedFolder, setSelectedFolder] = useState<string>('');
|
||||
const [popoverOpened, setPopoverOpened] = useState<boolean>(false);
|
||||
const { newFileModalVisible, setNewFileModalVisible } = useModalContext();
|
||||
const { files, loadFileList } = useFileList();
|
||||
|
||||
const handleSubmit = async (): Promise<void> => {
|
||||
if (fileName) {
|
||||
await onCreateFile(fileName.trim());
|
||||
const fullPath = selectedFolder
|
||||
? `${selectedFolder}/${fileName.trim()}`
|
||||
: fileName.trim();
|
||||
await onCreateFile(fullPath);
|
||||
setFileName('');
|
||||
setSelectedFolder('');
|
||||
setNewFileModalVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setFileName('');
|
||||
setSelectedFolder('');
|
||||
setNewFileModalVisible(false);
|
||||
};
|
||||
|
||||
const handleFolderSelect = (path: string) => {
|
||||
setSelectedFolder(path);
|
||||
// Keep popover open so users can continue browsing
|
||||
};
|
||||
|
||||
// Load files when modal opens
|
||||
React.useEffect(() => {
|
||||
if (newFileModalVisible) {
|
||||
void loadFileList();
|
||||
}
|
||||
}, [newFileModalVisible, loadFileList]);
|
||||
|
||||
// Generate full path preview
|
||||
const fullPathPreview = selectedFolder
|
||||
? `${selectedFolder}/${fileName || 'filename'}`
|
||||
: fileName || 'filename';
|
||||
|
||||
// Display text for location input
|
||||
const locationDisplay = selectedFolder || '/ (root)';
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent): void => {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
@@ -28,27 +64,82 @@ const CreateFileModal: React.FC<CreateFileModalProps> = ({ onCreateFile }) => {
|
||||
return (
|
||||
<Modal
|
||||
opened={newFileModalVisible}
|
||||
onClose={() => setNewFileModalVisible(false)}
|
||||
onClose={handleClose}
|
||||
title="Create New File"
|
||||
centered
|
||||
size="sm"
|
||||
>
|
||||
<Box maw={400} mx="auto">
|
||||
{/* Location input with folder picker */}
|
||||
<Popover
|
||||
opened={popoverOpened}
|
||||
onChange={setPopoverOpened}
|
||||
position="bottom-start"
|
||||
width="target"
|
||||
>
|
||||
<Popover.Target>
|
||||
<TextInput
|
||||
label="Location"
|
||||
type="text"
|
||||
placeholder="Select folder"
|
||||
data-testid="location-input"
|
||||
value={locationDisplay}
|
||||
readOnly
|
||||
mb="md"
|
||||
w="100%"
|
||||
rightSection={
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
onClick={() => setPopoverOpened((o) => !o)}
|
||||
data-testid="folder-picker-button"
|
||||
>
|
||||
<IconFolderOpen size={18} />
|
||||
</ActionIcon>
|
||||
}
|
||||
styles={{
|
||||
input: {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
}}
|
||||
onClick={() => setPopoverOpened(true)}
|
||||
/>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown>
|
||||
<FolderSelector
|
||||
files={files}
|
||||
selectedPath={selectedFolder}
|
||||
onSelect={handleFolderSelect}
|
||||
/>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
|
||||
{/* File name input */}
|
||||
<TextInput
|
||||
label="File Name"
|
||||
type="text"
|
||||
placeholder="Enter file name"
|
||||
placeholder="example.md"
|
||||
data-testid="file-name-input"
|
||||
value={fileName}
|
||||
onChange={(event) => setFileName(event.currentTarget.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
mb="md"
|
||||
mb="xs"
|
||||
w="100%"
|
||||
/>
|
||||
|
||||
{/* Hint text */}
|
||||
<Text size="xs" c="dimmed" mb="xs">
|
||||
Tip: Use / to create nested folders (e.g., folder/subfolder/file.md)
|
||||
</Text>
|
||||
|
||||
{/* Full path preview */}
|
||||
<Text size="sm" c="dimmed" mb="md">
|
||||
Full path: {fullPathPreview}
|
||||
</Text>
|
||||
|
||||
<Group justify="flex-end" mt="md">
|
||||
<Button
|
||||
variant="default"
|
||||
onClick={() => setNewFileModalVisible(false)}
|
||||
onClick={handleClose}
|
||||
data-testid="cancel-create-file-button"
|
||||
>
|
||||
Cancel
|
||||
|
||||
Reference in New Issue
Block a user