diff --git a/pkg/api/api.go b/pkg/api/api.go
index abe1c62..929a259 100644
--- a/pkg/api/api.go
+++ b/pkg/api/api.go
@@ -82,6 +82,10 @@ func NewAPI(config Config) (*API, error) {
apiMux.HandleFunc("/login", api.HandleLogin)
apiMux.HandleFunc("/register", api.HandleRegister)
apiMux.HandleFunc("/logout", api.LoginAsAnonymous)
+ // tag
+ apiMux.HandleFunc("/get_tags", api.HandleGetTags)
+ apiMux.HandleFunc("/get_tag_info", api.HandleGetTagInfo)
+ apiMux.HandleFunc("/insert_tag", api.HandleInsertTag)
// below needs token
apiMux.HandleFunc("/walk", api.HandleWalk)
apiMux.HandleFunc("/reset", api.HandleReset)
diff --git a/pkg/api/handle_tag.go b/pkg/api/handle_tag.go
new file mode 100644
index 0000000..2988386
--- /dev/null
+++ b/pkg/api/handle_tag.go
@@ -0,0 +1,93 @@
+package api
+
+import (
+ "encoding/json"
+ "log"
+ "msw-open-music/pkg/database"
+ "net/http"
+)
+
+type getTagsResponse struct {
+ Tags []database.Tag `json:"tags"`
+}
+
+func (api *API) HandleGetTags(w http.ResponseWriter, r *http.Request) {
+ tags, err := api.Db.GetTags()
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+
+ log.Println("Successfully got tags")
+
+ resp := &getTagsResponse{Tags: tags}
+
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+}
+
+type InsertTagRequest struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+}
+
+type InsertTagResponse struct {
+ Tag *database.Tag `json:"tag"`
+}
+
+func (api *API) HandleInsertTag(w http.ResponseWriter, r *http.Request) {
+ var req InsertTagRequest
+ err := json.NewDecoder(r.Body).Decode(&req)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+
+ tag, err := api.Db.InsertTag(req.Name, req.Description)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+
+ resp := &InsertTagResponse{Tag: tag}
+
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+}
+
+type GetTagInfoRequest struct {
+ ID int64 `json:"id"`
+}
+
+type GetTagInfoResponse struct {
+ Tag *database.Tag `json:"tag"`
+}
+
+func (api *API) HandleGetTagInfo(w http.ResponseWriter, r *http.Request) {
+ var req GetTagInfoRequest
+ err := json.NewDecoder(r.Body).Decode(&req)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+
+ tag, err := api.Db.GetTag(req.ID)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+
+ resp := &GetTagInfoResponse{Tag: tag}
+
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ api.HandleError(w, r, err)
+ return
+ }
+}
diff --git a/pkg/database/method_tag.go b/pkg/database/method_tag.go
new file mode 100644
index 0000000..e2737ff
--- /dev/null
+++ b/pkg/database/method_tag.go
@@ -0,0 +1,40 @@
+package database
+
+func (database *Database) InsertTag(tag string, description string) (*Tag, error) {
+ result, err := database.stmt.insertTag.Exec(tag, description)
+ if err != nil {
+ return nil, err
+ }
+ id, err := result.LastInsertId()
+ if err != nil {
+ return nil, err
+ }
+ return database.GetTag(id)
+}
+
+func (database *Database) GetTag(id int64) (*Tag, error) {
+ tag := &Tag{}
+ err := database.stmt.getTag.QueryRow(id).Scan(&tag.ID, &tag.Name, &tag.Description)
+ if err != nil {
+ return nil, err
+ }
+ return tag, nil
+}
+
+func (database *Database) GetTags() ([]Tag, error) {
+ tags := []Tag{}
+ rows, err := database.stmt.getTags.Query()
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ for rows.Next() {
+ tag := Tag{}
+ err := rows.Scan(&tag.ID, &tag.Name, &tag.Description)
+ if err != nil {
+ return nil, err
+ }
+ tags = append(tags, tag)
+ }
+ return tags, nil
+}
diff --git a/pkg/database/sql_stmt.go b/pkg/database/sql_stmt.go
index a04b2ef..496f3fb 100644
--- a/pkg/database/sql_stmt.go
+++ b/pkg/database/sql_stmt.go
@@ -43,8 +43,9 @@ var initAvatarsTableQuery = `CREATE TABLE IF NOT EXISTS avatars (
);`
var initTagsTableQuery = `CREATE TABLE IF NOT EXISTS tags (
- id INTEGER PRIMARY KEY,
- tag TEXT NOT NULL
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL UNIQUE,
+ description TEXT NOT NULL
);`
var initFileHasTagTableQuery = `CREATE TABLE IF NOT EXISTS file_has_tag (
@@ -169,6 +170,12 @@ var getUserByIdQuery = `SELECT id, username, role, avatar_id FROM users WHERE id
var getAnonymousUserQuery = `SELECT id, username, role, avatar_id FROM users WHERE role = 0 LIMIT 1;`
+var insertTagQuery = `INSERT INTO tags (name, description) VALUES (?, ?);`
+
+var getTagQuery = `SELECT id, name, description FROM tags WHERE id = ? LIMIT 1;`
+
+var getTagsQuery = `SELECT id, name, description FROM tags;`
+
type Stmt struct {
initFilesTable *sql.Stmt
initFoldersTable *sql.Stmt
@@ -201,6 +208,9 @@ type Stmt struct {
getUser *sql.Stmt
getUserById *sql.Stmt
getAnonymousUser *sql.Stmt
+ insertTag *sql.Stmt
+ getTag *sql.Stmt
+ getTags *sql.Stmt
}
func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
@@ -457,5 +467,23 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
}
}
+ // init insertTag
+ stmt.insertTag, err = sqlConn.Prepare(insertTagQuery)
+ if err != nil {
+ return nil, err
+ }
+
+ // init getTag
+ stmt.getTag, err = sqlConn.Prepare(getTagQuery)
+ if err != nil {
+ return nil, err
+ }
+
+ // init getTags
+ stmt.getTags, err = sqlConn.Prepare(getTagsQuery)
+ if err != nil {
+ return nil, err
+ }
+
return stmt, err
}
diff --git a/pkg/database/struct.go b/pkg/database/struct.go
index c7d92ee..13aab35 100644
--- a/pkg/database/struct.go
+++ b/pkg/database/struct.go
@@ -28,10 +28,16 @@ type User struct {
AvatarId int64 `json:"avatar_id"`
}
+type Tag struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+}
+
var (
RoleAnonymous = int64(0)
- RoleAdmin = int64(1)
- RoleUser = int64(2)
+ RoleAdmin = int64(1)
+ RoleUser = int64(2)
)
func (f *File) Path() (string, error) {
diff --git a/web/src/App.js b/web/src/App.js
index afc4b5a..a51c6d0 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -9,6 +9,8 @@ import Manage from "./component/Manage";
import Share from "./component/Share";
import Login from "./component/Login";
import Register from "./component/Register";
+import Tags from "./component/Tags";
+import EditTag from "./component/EditTag";
import AudioPlayer from "./component/AudioPlayer";
import UserStatus from "./component/UserStatus";
import { useState } from "react";
@@ -59,9 +61,26 @@ function App() {
path="/folders/:id"
element={
| Name | +Description | +Actions | +
|---|---|---|
| {tag.name} | +{tag.description} | ++ Edit + | +