feat: list file contents
This commit is contained in:
38
api/main.go
38
api/main.go
@@ -1,11 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
// "fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"encoding/base64"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ func main() {
|
|||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
router.SetTrustedProxies([]string{"127.0.0.1"}) // TODO: fix All origins allowed by default
|
router.SetTrustedProxies([]string{"127.0.0.1"}) // TODO: fix All origins allowed by default
|
||||||
router.Use(cors.Default())
|
router.Use(cors.Default())
|
||||||
list := listFiles("/Users/madundead/Syncthing/Obsidian/Personal")
|
list := listFiles("/home/madundead/Syncthing/Obsidian/Personal")
|
||||||
|
|
||||||
router.GET("/api/v1/files", func(c *gin.Context) {
|
router.GET("/api/v1/files", func(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
@@ -26,6 +27,21 @@ func main() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.GET("/api/v1/files/:id", func(c *gin.Context) {
|
||||||
|
id := c.Params.ByName("id")
|
||||||
|
// value, ok := db[user]
|
||||||
|
// if ok {
|
||||||
|
path, _ := base64.StdEncoding.DecodeString(id)
|
||||||
|
|
||||||
|
data, _ := os.ReadFile(string(path))
|
||||||
|
// fmt.Print(string(dat))
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{"data": string(data)})
|
||||||
|
// } else {
|
||||||
|
// c.JSON(http.StatusOK, gin.H{"user": user, "status": "no value"})
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
|
||||||
if err := router.Run(); err != nil {
|
if err := router.Run(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -46,12 +62,12 @@ func listFiles(dir string) []string {
|
|||||||
}
|
}
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
//
|
||||||
func readFile(string filePath) []string {
|
// func readFile(string filePath) []string {
|
||||||
content, err := os.ReadFile(filePath)
|
// content, err := os.ReadFile(filePath)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println("Error reading file:", err)
|
// fmt.Println("Error reading file:", err)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
return content
|
// return content
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
// import { FilesList } from "./components/FilesList";
|
// import { FilesList } from "./components/FilesList";
|
||||||
// import { FileContent } from "./components/FileContent";
|
// import { FileContent } from "./components/FileContent";
|
||||||
import { Root } from "./components/Root";
|
import { Obi } from "./components/Obi";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
return (<Root/ >);
|
return (<Obi />);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function FileContent({ filePath }) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("http://localhost:8912/api/v1/files"); // Replace with your API endpoint
|
const response = await fetch("http://localhost:8912/api/v1/files/" + filePath); // Replace with your API endpoint
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -22,14 +22,14 @@ export function FileContent({ filePath }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
}, []); // Empty dependency array ensures this effect runs only once on mount
|
}, [filePath]); // Empty dependency array ensures this effect runs only once on mount
|
||||||
|
|
||||||
if (loading) return <p>Loading data...</p>;
|
if (loading) return <p>Loading data...</p>;
|
||||||
if (error) return <p>Error: {error.message}</p>;
|
// if (error) return <p>Error: {error.message}</p>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<pre>{filePath}</pre>
|
<pre>{data?.data}</pre>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
export function FilesList({ handleFileClick }) {
|
export function FilesList({ handleFileClick }) {
|
||||||
const [data, setData] = useState(null);
|
const [data, setData] = useState(null);
|
||||||
@@ -27,15 +27,11 @@ export function FilesList({ handleFileClick }) {
|
|||||||
if (loading) return <p>Loading data...</p>;
|
if (loading) return <p>Loading data...</p>;
|
||||||
if (error) return <p>Error: {error.message}</p>;
|
if (error) return <p>Error: {error.message}</p>;
|
||||||
|
|
||||||
const onClick = (event) => {
|
|
||||||
handleFileClick(event.target.value); // Call the parent's callback with the new value
|
|
||||||
};
|
|
||||||
|
|
||||||
const listFiles = data.map(filePath => <li onClick={onClick} className="cursor-pointer">{filePath}</li>);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{listFiles}
|
{data.map(filePath => (
|
||||||
|
<li key={filePath} onClick={() => handleFileClick(filePath)} className="cursor-pointer">{filePath}</li>)
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
24
frontend/src/components/Obi.tsx
Normal file
24
frontend/src/components/Obi.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { FilesList } from "./FilesList";
|
||||||
|
import { FileContent } from "./FileContent";
|
||||||
|
import { bytesToBase64 } from "../util/codecs.ts";
|
||||||
|
|
||||||
|
export function Obi() {
|
||||||
|
const [filePath, setFilePath] = useState('');
|
||||||
|
|
||||||
|
const handleFileClick = (value) => {
|
||||||
|
console.log(`Encoded string: [${bytesToBase64(value)}]`);
|
||||||
|
setFilePath(bytesToBase64(value));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid text-black grid-cols-1 md:grid-cols-2 h-screen">
|
||||||
|
<div className="bg-gray-100 p-4 overflow-y-auto">
|
||||||
|
<FilesList handleFileClick={handleFileClick} />
|
||||||
|
</div>
|
||||||
|
<div className="bg-white p-4 overflow-y-auto">
|
||||||
|
<FileContent filePath={filePath} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
|
|
||||||
import { FilesList } from "./FilesList";
|
|
||||||
import { FileContent } from "./FileContent";
|
|
||||||
|
|
||||||
export function Root() {
|
|
||||||
const [filePath, setFilePath] = useState(''); // State to be shared
|
|
||||||
|
|
||||||
const handleFileClick = () => {
|
|
||||||
setFilePath('1000')
|
|
||||||
alert("Button clicked!");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex">
|
|
||||||
<div className="flex-1">
|
|
||||||
<FilesList onClick={handleFileClick} />
|
|
||||||
</div>
|
|
||||||
<div className="flex-2">
|
|
||||||
<FileContent filePath={filePath} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
12
frontend/src/util/codecs.ts
Normal file
12
frontend/src/util/codecs.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem.
|
||||||
|
export function base64ToBytes(base64) {
|
||||||
|
const binString = atob(base64);
|
||||||
|
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem.
|
||||||
|
export function bytesToBase64(string: String) {
|
||||||
|
const bytes = new TextEncoder().encode(string)
|
||||||
|
const binString = String.fromCodePoint(...bytes);
|
||||||
|
return btoa(binString);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user