Save file on FE

This commit is contained in:
2024-09-26 15:43:28 +02:00
parent 9faa212043
commit fcbf4a689f
3 changed files with 50 additions and 7 deletions

View File

@@ -1,8 +1,8 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import { GeistProvider, CssBaseline } from '@geist-ui/core'; import { GeistProvider, CssBaseline, useToasts } from '@geist-ui/core';
import Editor from './components/Editor'; import Editor from './components/Editor';
import FileTree from './components/FileTree'; import FileTree from './components/FileTree';
import { fetchFileList, fetchFileContent } from './services/api'; import { fetchFileList, fetchFileContent, saveFileContent } from './services/api';
import './App.scss'; import './App.scss';
function App() { function App() {
@@ -10,6 +10,7 @@ function App() {
const [files, setFiles] = useState([]); const [files, setFiles] = useState([]);
const [selectedFile, setSelectedFile] = useState(null); const [selectedFile, setSelectedFile] = useState(null);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const { setToast } = useToasts();
useEffect(() => { useEffect(() => {
const loadFileList = async () => { const loadFileList = async () => {
@@ -34,12 +35,23 @@ function App() {
const fileContent = await fetchFileContent(filePath); const fileContent = await fetchFileContent(filePath);
setContent(fileContent); setContent(fileContent);
setSelectedFile(filePath); setSelectedFile(filePath);
setError(null);
} catch (error) { } catch (error) {
console.error('Failed to load file content:', error); console.error('Failed to load file content:', error);
setError('Failed to load file content. Please try again.'); setError('Failed to load file content. Please try again.');
} }
}; };
const handleSave = useCallback(async (filePath, fileContent) => {
try {
await saveFileContent(filePath, fileContent);
setToast({ text: 'File saved successfully', type: 'success' });
} catch (error) {
console.error('Error saving file:', error);
setToast({ text: 'Failed to save file. Please try again.', type: 'error' });
}
}, [setToast]);
return ( return (
<GeistProvider> <GeistProvider>
<CssBaseline /> <CssBaseline />
@@ -57,7 +69,12 @@ function App() {
</div> </div>
<div className="main-content"> <div className="main-content">
<h1>NovaMD</h1> <h1>NovaMD</h1>
<Editor content={content} onChange={setContent} /> <Editor
content={content}
onChange={setContent}
onSave={handleSave}
filePath={selectedFile}
/>
</div> </div>
</div> </div>
</GeistProvider> </GeistProvider>

View File

@@ -5,17 +5,27 @@ import { EditorView, keymap } from "@codemirror/view";
import { markdown } from "@codemirror/lang-markdown"; import { markdown } from "@codemirror/lang-markdown";
import { defaultKeymap } from "@codemirror/commands"; import { defaultKeymap } from "@codemirror/commands";
const Editor = ({ content, onChange }) => { const Editor = ({ content, onChange, onSave, filePath }) => {
const editorRef = useRef(); const editorRef = useRef();
const viewRef = useRef(); const viewRef = useRef();
useEffect(() => { useEffect(() => {
const handleSave = (view) => {
onSave(filePath, view.state.doc.toString());
return true;
};
const state = EditorState.create({ const state = EditorState.create({
doc: content, doc: content,
extensions: [ extensions: [
basicSetup, basicSetup,
markdown(), markdown(),
keymap.of(defaultKeymap), keymap.of(defaultKeymap),
keymap.of([{
key: "Ctrl-s",
run: handleSave,
preventDefault: true
}]),
EditorView.updateListener.of((update) => { EditorView.updateListener.of((update) => {
if (update.docChanged) { if (update.docChanged) {
onChange(update.state.doc.toString()); onChange(update.state.doc.toString());
@@ -34,7 +44,7 @@ const Editor = ({ content, onChange }) => {
return () => { return () => {
view.destroy(); view.destroy();
}; };
}, []); }, [filePath]);
useEffect(() => { useEffect(() => {
if (viewRef.current && content !== viewRef.current.state.doc.toString()) { if (viewRef.current && content !== viewRef.current.state.doc.toString()) {

View File

@@ -24,4 +24,20 @@ export const fetchFileContent = async (filePath) => {
console.error('Error fetching file content:', error); console.error('Error fetching file content:', error);
throw error; throw error;
} }
}; };
export const saveFileContent = async (filePath, content) => {
const response = await fetch(`/api/v1/files/${filePath}`, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
body: content,
});
if (!response.ok) {
throw new Error('Failed to save file');
}
return await response.text();
};