From 2c802ca8071acfb3be17bc052df4b2960f0041b0 Mon Sep 17 00:00:00 2001 From: heimoshuiyu Date: Sun, 12 Dec 2021 17:09:16 +0800 Subject: [PATCH] Add: put tag on file --- pkg/api/api.go | 2 + pkg/api/handle_error.go | 1 + pkg/api/handle_tag_and_file.go | 82 ++++++++++++++++++++++ pkg/database/method_tag_and_file.go | 25 +++++++ pkg/database/sql_stmt.go | 22 ++++++ web/src/component/FileInfo.js | 105 +++++++++++++++++++++++++++- 6 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 pkg/api/handle_tag_and_file.go create mode 100644 pkg/database/method_tag_and_file.go diff --git a/pkg/api/api.go b/pkg/api/api.go index b4c14b4..0935b6a 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -87,6 +87,8 @@ func NewAPI(config Config) (*API, error) { apiMux.HandleFunc("/get_tag_info", api.HandleGetTagInfo) apiMux.HandleFunc("/insert_tag", api.HandleInsertTag) apiMux.HandleFunc("/update_tag", api.HandleUpdateTag) + apiMux.HandleFunc("/put_tag_on_file", api.HandlePutTagOnFile) + apiMux.HandleFunc("/get_tags_on_file", api.HandleGetTagsOnFile) // below needs token apiMux.HandleFunc("/walk", api.HandleWalk) apiMux.HandleFunc("/reset", api.HandleReset) diff --git a/pkg/api/handle_error.go b/pkg/api/handle_error.go index 320d4d3..dad0e28 100644 --- a/pkg/api/handle_error.go +++ b/pkg/api/handle_error.go @@ -10,6 +10,7 @@ import ( var ( ErrNotLoggedIn = errors.New("not logged in") ErrNotAdmin = errors.New("not admin") + ErrEmpty = errors.New("Empty field detected, please fill in all fields") ) type Error struct { diff --git a/pkg/api/handle_tag_and_file.go b/pkg/api/handle_tag_and_file.go new file mode 100644 index 0000000..da8343f --- /dev/null +++ b/pkg/api/handle_tag_and_file.go @@ -0,0 +1,82 @@ +package api + +import ( + "encoding/json" + "log" + "msw-open-music/pkg/database" + "net/http" +) + +type PutTagOnFileRequest struct { + TagID int64 `json:"tag_id"` + FileID int64 `json:"file_id"` +} + +func (api *API) HandlePutTagOnFile(w http.ResponseWriter, r *http.Request) { + // check if the user is admin + err := api.CheckAdmin(w, r) + if err != nil { + api.HandleError(w, r, err) + return + } + + req := &PutTagOnFileRequest{} + err = json.NewDecoder(r.Body).Decode(req) + if err != nil { + api.HandleError(w, r, err) + return + } + + userID, err := api.GetUserID(w, r) + if err != nil { + api.HandleError(w, r, err) + return + } + + // check empty + if req.TagID == 0 || req.FileID == 0 { + api.HandleError(w, r, ErrEmpty) + return + } + + log.Println("Put tag on file request:", req, "userID:", userID) + + api.Db.PutTagOnFile(req.TagID, req.FileID, userID) + + api.HandleOK(w, r) +} + +type GetTagsOnFileRequest struct { + ID int64 `json:"id"` +} + +type GetTagsOnFileResponse struct { + Tags []*database.Tag `json:"tags"` +} + +func (api *API) HandleGetTagsOnFile(w http.ResponseWriter, r *http.Request) { + req := &GetTagsOnFileRequest{} + err := json.NewDecoder(r.Body).Decode(req) + if err != nil { + api.HandleError(w, r, err) + return + } + + log.Println("Get tags on file request:", req) + + tags, err := api.Db.GetTagsOnFile(req.ID) + if err != nil { + api.HandleError(w, r, err) + return + } + + resp := &GetTagsOnFileResponse{ + Tags: tags, + } + + err = json.NewEncoder(w).Encode(resp) + if err != nil { + api.HandleError(w, r, err) + return + } +} diff --git a/pkg/database/method_tag_and_file.go b/pkg/database/method_tag_and_file.go new file mode 100644 index 0000000..1a7f3a2 --- /dev/null +++ b/pkg/database/method_tag_and_file.go @@ -0,0 +1,25 @@ +package database + +func (database *Database) PutTagOnFile(tagID, fileID, userID int64) error { + _, err := database.stmt.putTagOnFile.Exec(tagID, fileID, userID) + return err +} + +func (database *Database) GetTagsOnFile(fileID int64) ([]*Tag, error) { + rows, err := database.stmt.getTagsOnFile.Query(fileID) + if err != nil { + return nil, err + } + defer rows.Close() + + tags := make([]*Tag, 0) + for rows.Next() { + tag := &Tag{} + err = rows.Scan(&tag.ID, &tag.Name, &tag.Description, &tag.CreatedByUserId) + 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 2c16e79..7d83d20 100644 --- a/pkg/database/sql_stmt.go +++ b/pkg/database/sql_stmt.go @@ -190,6 +190,14 @@ JOIN users ON tags.created_by_user_id = users.id var updateTagQuery = `UPDATE tags SET name = ?, description = ? WHERE id = ?;` +var putTagOnFileQuery = `INSERT INTO file_has_tag (tag_id, file_id, user_id) VALUES (?, ?, ?);` + +var getTagsOnFileQuery = `SELECT +tags.id, tags.name, tags.description, tags.created_by_user_id +FROM file_has_tag +JOIN tags ON file_has_tag.tag_id = tags.id +WHERE file_has_tag.file_id = ?;` + type Stmt struct { initFilesTable *sql.Stmt initFoldersTable *sql.Stmt @@ -226,6 +234,8 @@ type Stmt struct { getTag *sql.Stmt getTags *sql.Stmt updateTag *sql.Stmt + putTagOnFile *sql.Stmt + getTagsOnFile *sql.Stmt } func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) { @@ -506,5 +516,17 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) { return nil, err } + // init putTagOnFile + stmt.putTagOnFile, err = sqlConn.Prepare(putTagOnFileQuery) + if err != nil { + return nil, err + } + + // init getTagsOnFile + stmt.getTagsOnFile, err = sqlConn.Prepare(getTagsOnFileQuery) + if err != nil { + return nil, err + } + return stmt, err } diff --git a/web/src/component/FileInfo.js b/web/src/component/FileInfo.js index 31c73cf..6eace3b 100644 --- a/web/src/component/FileInfo.js +++ b/web/src/component/FileInfo.js @@ -11,6 +11,9 @@ function FileInfo(props) { filename: "", filesize: "", }); + const [tags, setTags] = useState([]); + const [tagsOnFile, setTagsOnFile] = useState([]); + const [selectedTagID, setSelectedTagID] = useState(""); function refresh() { fetch(`/api/v1/get_file_info`, { @@ -32,8 +35,42 @@ function FileInfo(props) { }); } + function getTags() { + fetch(`/api/v1/get_tags`) + .then((res) => res.json()) + .then((data) => { + if (data.error) { + alert(data.error); + } else { + setTags(data.tags); + } + }); + } + + function getTagsOnFile() { + fetch(`/api/v1/get_tags_on_file`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: parseInt(params.id), + }), + }) + .then((res) => res.json()) + .then((data) => { + if (data.error) { + alert(data.error); + } else { + setTagsOnFile(data.tags); + } + }); + } + useEffect(() => { refresh(); + getTags(); + getTagsOnFile(); }, []); return ( @@ -41,9 +78,13 @@ function FileInfo(props) {

File Details

- +
+
+ + +
+ + +
+
); }