Add: support walk database with tags

This commit is contained in:
2021-12-13 13:24:25 +08:00
parent d4718ac120
commit a826e4bf29
4 changed files with 144 additions and 66 deletions

View File

@@ -8,6 +8,7 @@ import (
type WalkRequest struct {
Root string `json:"root"`
Pattern []string `json:"pattern"`
TagIDs []int64 `json:"tag_ids"`
}
type ResetRequest struct {
@@ -71,8 +72,15 @@ func (api *API) HandleWalk(w http.ResponseWriter, r *http.Request) {
return
}
// get userID
userID, err := api.GetUserID(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
// walk
err = api.Db.Walk(walkRequest.Root, walkRequest.Pattern)
err = api.Db.Walk(walkRequest.Root, walkRequest.Pattern, walkRequest.TagIDs, userID)
if err != nil {
api.HandleError(w, r, err)
return

View File

@@ -51,9 +51,7 @@ func (database *Database) GetRandomFilesWithTag(tagID, limit int64) ([]File, err
return nil, err
}
files = append(files, file)
log.Println("[db] GetRandomFilesWithTag", file.ID, file.Filename, file.Foldername, file.Filesize)
}
log.Println("[db] GetRandomFilesWithTag", files)
return files, nil
}
@@ -137,12 +135,22 @@ func (database *Database) ResetFolder() error {
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)
for _, v := range pattern {
patternDict[v] = true
}
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 {
if err != nil {
return err
@@ -159,10 +167,17 @@ func (database *Database) Walk(root string, pattern []string) error {
}
// insert file, folder will aut created
err = database.Insert(path, info.Size())
fileID, err := database.Insert(path, info.Size())
if err != nil {
return err
}
for _, tag := range tags {
err = database.PutTagOnFile(tag.ID, fileID, userID)
if err != nil {
return err
}
}
return nil
})
}
@@ -231,35 +246,39 @@ func (database *Database) InsertFolder(folder string) (int64, error) {
return lastInsertId, nil
}
func (database *Database) InsertFile(folderId int64, filename string, filesize int64) error {
_, err := database.stmt.insertFile.Exec(folderId, filename, filesize)
func (database *Database) InsertFile(folderId int64, filename string, filesize int64) (int64, error) {
result, err := database.stmt.insertFile.Exec(folderId, filename, filesize)
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)
folderId, err := database.FindFolder(folder)
if err != nil {
folderId, err = database.InsertFolder(folder)
if err != nil {
return err
return 0, err
}
}
// if file exists, skip it
_, err = database.FindFile(folderId, filename)
lastInsertId, err := database.FindFile(folderId, filename)
if err == nil {
return nil
return lastInsertId, nil
}
err = database.InsertFile(folderId, filename, filesize)
lastInsertId, err = database.InsertFile(folderId, filename, filesize)
if err != nil {
return err
return 0, err
}
return nil
return lastInsertId, nil
}
func (database *Database) UpdateFoldername(folderId int64, foldername string) error {

View 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;

View File

@@ -1,38 +1,9 @@
import { useState } from "react";
import { useNavigate } from "react-router";
import Database from "./Database";
function Manage(props) {
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 (
<div>
<h2>Manage</h2>
@@ -65,26 +36,7 @@ function Manage(props) {
)}
<hr />
<button onClick={() => navigate("/manage/tags")}>Tags</button>
<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)}
/>
<button
onClick={() => {
updateDatabase();
}}
>
Update Database
</button>
<Database />
</div>
);
}