Add: support walk database with tags
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
type WalkRequest struct {
|
type WalkRequest struct {
|
||||||
Root string `json:"root"`
|
Root string `json:"root"`
|
||||||
Pattern []string `json:"pattern"`
|
Pattern []string `json:"pattern"`
|
||||||
|
TagIDs []int64 `json:"tag_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResetRequest struct {
|
type ResetRequest struct {
|
||||||
@@ -71,8 +72,15 @@ func (api *API) HandleWalk(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get userID
|
||||||
|
userID, err := api.GetUserID(w, r)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// walk
|
// walk
|
||||||
err = api.Db.Walk(walkRequest.Root, walkRequest.Pattern)
|
err = api.Db.Walk(walkRequest.Root, walkRequest.Pattern, walkRequest.TagIDs, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -51,9 +51,7 @@ func (database *Database) GetRandomFilesWithTag(tagID, limit int64) ([]File, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
log.Println("[db] GetRandomFilesWithTag", file.ID, file.Filename, file.Foldername, file.Filesize)
|
|
||||||
}
|
}
|
||||||
log.Println("[db] GetRandomFilesWithTag", files)
|
|
||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,12 +135,22 @@ func (database *Database) ResetFolder() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (database *Database) Walk(root string, pattern []string) error {
|
func (database *Database) Walk(root string, pattern []string, tagIDs []int64, userID int64) error {
|
||||||
patternDict := make(map[string]bool)
|
patternDict := make(map[string]bool)
|
||||||
for _, v := range pattern {
|
for _, v := range pattern {
|
||||||
patternDict[v] = true
|
patternDict[v] = true
|
||||||
}
|
}
|
||||||
log.Println("[db] Walk", root, patternDict)
|
log.Println("[db] Walk", root, patternDict)
|
||||||
|
|
||||||
|
tags := make([]*Tag, 0)
|
||||||
|
for _, tagID := range tagIDs {
|
||||||
|
tag, err := database.GetTag(tagID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tags = append(tags, tag)
|
||||||
|
}
|
||||||
|
|
||||||
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -159,10 +167,17 @@ func (database *Database) Walk(root string, pattern []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert file, folder will aut created
|
// insert file, folder will aut created
|
||||||
err = database.Insert(path, info.Size())
|
fileID, err := database.Insert(path, info.Size())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
err = database.PutTagOnFile(tag.ID, fileID, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -231,35 +246,39 @@ func (database *Database) InsertFolder(folder string) (int64, error) {
|
|||||||
return lastInsertId, nil
|
return lastInsertId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (database *Database) InsertFile(folderId int64, filename string, filesize int64) error {
|
func (database *Database) InsertFile(folderId int64, filename string, filesize int64) (int64, error) {
|
||||||
_, err := database.stmt.insertFile.Exec(folderId, filename, filesize)
|
result, err := database.stmt.insertFile.Exec(folderId, filename, filesize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
return nil
|
lastInsertId, err := result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return lastInsertId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (database *Database) Insert(path string, filesize int64) error {
|
func (database *Database) Insert(path string, filesize int64) (int64, error) {
|
||||||
folder, filename := filepath.Split(path)
|
folder, filename := filepath.Split(path)
|
||||||
folderId, err := database.FindFolder(folder)
|
folderId, err := database.FindFolder(folder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
folderId, err = database.InsertFolder(folder)
|
folderId, err = database.InsertFolder(folder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if file exists, skip it
|
// if file exists, skip it
|
||||||
_, err = database.FindFile(folderId, filename)
|
lastInsertId, err := database.FindFile(folderId, filename)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return lastInsertId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = database.InsertFile(folderId, filename, filesize)
|
lastInsertId, err = database.InsertFile(folderId, filename, filesize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
return nil
|
return lastInsertId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (database *Database) UpdateFoldername(folderId int64, foldername string) error {
|
func (database *Database) UpdateFoldername(folderId int64, foldername string) error {
|
||||||
|
|||||||
99
web/src/component/Database.js
Normal file
99
web/src/component/Database.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
function Database() {
|
||||||
|
const [walkPath, setWalkPath] = useState("");
|
||||||
|
const [patternString, setPatternString] = useState("");
|
||||||
|
const [tags, setTags] = useState([]);
|
||||||
|
const [selectedTags, setSelectedTags] = useState([]);
|
||||||
|
|
||||||
|
function getTags() {
|
||||||
|
fetch("/api/v1/get_tags")
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
if (data.error) {
|
||||||
|
alert(data.error);
|
||||||
|
} else {
|
||||||
|
setTags(data.tags);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getTags();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function updateDatabase() {
|
||||||
|
// split pattern string into array
|
||||||
|
let patternArray = patternString.split(" ");
|
||||||
|
// remove whitespace from array
|
||||||
|
patternArray = patternArray.map((item) => item.trim());
|
||||||
|
// remove empty strings from array
|
||||||
|
patternArray = patternArray.filter((item) => item !== "");
|
||||||
|
// add dot before item array
|
||||||
|
patternArray = patternArray.map((item) => "." + item);
|
||||||
|
|
||||||
|
fetch("/api/v1/walk", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
root: walkPath,
|
||||||
|
pattern: patternArray,
|
||||||
|
tag_ids: selectedTags,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>Update Database</h3>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={walkPath}
|
||||||
|
placeholder="walk path"
|
||||||
|
onChange={(e) => setWalkPath(e.target.value)}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={patternString}
|
||||||
|
placeholder="pattern wav flac mp3"
|
||||||
|
onChange={(e) => setPatternString(e.target.value)}
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<h4>Tags</h4>
|
||||||
|
{tags.map((tag) => (
|
||||||
|
<div key={tag.id}>
|
||||||
|
<input
|
||||||
|
id={tag.id}
|
||||||
|
type="checkbox"
|
||||||
|
value={tag.id}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
setSelectedTags([...selectedTags, tag.id]);
|
||||||
|
} else {
|
||||||
|
setSelectedTags(
|
||||||
|
selectedTags.filter((item) => item !== tag.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor={tag.id}>{tag.name}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
updateDatabase();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update Database
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Database;
|
||||||
@@ -1,38 +1,9 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
|
import Database from "./Database";
|
||||||
|
|
||||||
function Manage(props) {
|
function Manage(props) {
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
|
||||||
const [walkPath, setWalkPath] = useState("");
|
|
||||||
const [patternString, setPatternString] = useState("");
|
|
||||||
|
|
||||||
function updateDatabase() {
|
|
||||||
// split pattern string into array
|
|
||||||
let patternArray = patternString.split(" ");
|
|
||||||
// remove whitespace from array
|
|
||||||
patternArray = patternArray.map((item) => item.trim());
|
|
||||||
// remove empty strings from array
|
|
||||||
patternArray = patternArray.filter((item) => item !== "");
|
|
||||||
// add dot before item array
|
|
||||||
patternArray = patternArray.map((item) => "." + item);
|
|
||||||
|
|
||||||
fetch("/api/v1/walk", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
root: walkPath,
|
|
||||||
pattern: patternArray,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>Manage</h2>
|
<h2>Manage</h2>
|
||||||
@@ -65,26 +36,7 @@ function Manage(props) {
|
|||||||
)}
|
)}
|
||||||
<hr />
|
<hr />
|
||||||
<button onClick={() => navigate("/manage/tags")}>Tags</button>
|
<button onClick={() => navigate("/manage/tags")}>Tags</button>
|
||||||
<h3>Update Database</h3>
|
<Database />
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={walkPath}
|
|
||||||
placeholder="walk path"
|
|
||||||
onChange={(e) => setWalkPath(e.target.value)}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={patternString}
|
|
||||||
placeholder="pattern wav flac mp3"
|
|
||||||
onChange={(e) => setPatternString(e.target.value)}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
updateDatabase();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Update Database
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user