Add: support delete tag and its references

This commit is contained in:
2021-12-14 00:33:31 +08:00
parent 4bfcf460c9
commit 83ab1a91b2
5 changed files with 158 additions and 53 deletions

View File

@@ -99,6 +99,7 @@ func NewAPI(config Config) (*API, error) {
apiMux.HandleFunc("/put_tag_on_file", api.HandlePutTagOnFile) apiMux.HandleFunc("/put_tag_on_file", api.HandlePutTagOnFile)
apiMux.HandleFunc("/get_tags_on_file", api.HandleGetTagsOnFile) apiMux.HandleFunc("/get_tags_on_file", api.HandleGetTagsOnFile)
apiMux.HandleFunc("/delete_tag_on_file", api.HandleDeleteTagOnFile) apiMux.HandleFunc("/delete_tag_on_file", api.HandleDeleteTagOnFile)
apiMux.HandleFunc("/delete_tag", api.HandleDeleteTag)
// folder // folder
apiMux.HandleFunc("/update_foldername", api.HandleUpdateFoldername) apiMux.HandleFunc("/update_foldername", api.HandleUpdateFoldername)
// review // review

View File

@@ -125,3 +125,34 @@ func (api *API) HandleUpdateTag(w http.ResponseWriter, r *http.Request) {
return return
} }
} }
type DeleteTagRequest struct {
ID int64 `json:"id"`
}
func (api *API) HandleDeleteTag(w http.ResponseWriter, r *http.Request) {
// check if user is admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &DeleteTagRequest{}
err = json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
}
err = api.Db.DeleteTag(req.ID)
if err != nil {
api.HandleError(w, r, err)
return
}
log.Println("Successfully deleted tag and its references", req.ID)
api.HandleOK(w, r)
}

View File

@@ -60,3 +60,33 @@ func (database *Database) UpdateTag(tag *Tag) (*Tag, error) {
} }
return database.GetTag(tag.ID) return database.GetTag(tag.ID)
} }
// delete tag and all its references in file_has_tag
func (database *Database) DeleteTag(id int64) error {
// begin transaction
tx, err := database.sqlConn.Begin()
if err != nil {
return err
}
// delete tag
_, err = tx.Stmt(database.stmt.deleteTag).Exec(id)
if err != nil {
tx.Rollback()
return err
}
// delete file_has_tag
_, err = tx.Stmt(database.stmt.deleteTagReferenceInFileHasTag).Exec(id)
if err != nil {
tx.Rollback()
return err
}
// commit transaction
err = tx.Commit()
if err != nil {
return err
}
return nil
}

View File

@@ -205,6 +205,8 @@ var getAnonymousUserQuery = `SELECT id, username, role, avatar_id FROM users WHE
var insertTagQuery = `INSERT INTO tags (name, description, created_by_user_id) VALUES (?, ?, ?);` var insertTagQuery = `INSERT INTO tags (name, description, created_by_user_id) VALUES (?, ?, ?);`
var deleteTagQuery = `DELETE FROM tags WHERE id = ?;`
var getTagQuery = `SELECT var getTagQuery = `SELECT
tags.id, tags.name, tags.description, tags.id, tags.name, tags.description,
users.id, users.username, users.role, users.avatar_id users.id, users.username, users.role, users.avatar_id
@@ -231,6 +233,8 @@ WHERE file_has_tag.file_id = ?;`
var deleteTagOnFileQuery = `DELETE FROM file_has_tag WHERE tag_id = ? AND file_id = ?;` var deleteTagOnFileQuery = `DELETE FROM file_has_tag WHERE tag_id = ? AND file_id = ?;`
var deleteTagReferenceInFileHasTagQuery = `DELETE FROM file_has_tag WHERE tag_id = ?;`
var updateFoldernameQuery = `UPDATE folders SET foldername = ? WHERE id = ?;` var updateFoldernameQuery = `UPDATE folders SET foldername = ? WHERE id = ?;`
var insertReviewQuery = `INSERT INTO reviews (user_id, file_id, created_at, content) var insertReviewQuery = `INSERT INTO reviews (user_id, file_id, created_at, content)
@@ -304,12 +308,14 @@ type Stmt struct {
updateUserPassword *sql.Stmt updateUserPassword *sql.Stmt
getAnonymousUser *sql.Stmt getAnonymousUser *sql.Stmt
insertTag *sql.Stmt insertTag *sql.Stmt
deleteTag *sql.Stmt
getTag *sql.Stmt getTag *sql.Stmt
getTags *sql.Stmt getTags *sql.Stmt
updateTag *sql.Stmt updateTag *sql.Stmt
putTagOnFile *sql.Stmt putTagOnFile *sql.Stmt
getTagsOnFile *sql.Stmt getTagsOnFile *sql.Stmt
deleteTagOnFile *sql.Stmt deleteTagOnFile *sql.Stmt
deleteTagReferenceInFileHasTag *sql.Stmt
updateFoldername *sql.Stmt updateFoldername *sql.Stmt
insertReview *sql.Stmt insertReview *sql.Stmt
getReviewsOnFile *sql.Stmt getReviewsOnFile *sql.Stmt
@@ -621,6 +627,12 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
return nil, err return nil, err
} }
// init deleteTag
stmt.deleteTag, err = sqlConn.Prepare(deleteTagQuery)
if err != nil {
return nil, err
}
// init getTag // init getTag
stmt.getTag, err = sqlConn.Prepare(getTagQuery) stmt.getTag, err = sqlConn.Prepare(getTagQuery)
if err != nil { if err != nil {
@@ -657,6 +669,13 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
return nil, err return nil, err
} }
// init deleteTagReferenceInFileHasTag
stmt.deleteTagReferenceInFileHasTag, err = sqlConn.Prepare(
deleteTagReferenceInFileHasTagQuery)
if err != nil {
return nil, err
}
// init updateFoldername // init updateFoldername
stmt.updateFoldername, err = sqlConn.Prepare(updateFoldernameQuery) stmt.updateFoldername, err = sqlConn.Prepare(updateFoldernameQuery)
if err != nil { if err != nil {

View File

@@ -1,8 +1,10 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useParams } from "react-router"; import { useParams, useNavigate } from "react-router";
function EditTag() { function EditTag() {
let params = useParams(); let params = useParams();
let navigate = useNavigate();
const [tag, setTag] = useState({ const [tag, setTag] = useState({
id: "", id: "",
name: "", name: "",
@@ -62,6 +64,27 @@ function EditTag() {
refreshTagInfo(); refreshTagInfo();
}, []); }, []);
function deleteTag() {
fetch("/api/v1/delete_tag", {
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 {
alert("Tag deleted successfully");
navigate(-1);
}
});
}
return ( return (
<div className="page"> <div className="page">
<h3>Edit Tag</h3> <h3>Edit Tag</h3>
@@ -107,6 +130,7 @@ function EditTag() {
value={tag.description} value={tag.description}
onChange={(e) => setTag({ ...tag, description: e.target.value })} onChange={(e) => setTag({ ...tag, description: e.target.value })}
/> />
<button onClick={deleteTag}>Delete</button>
<button onClick={() => updateTagInfo()}>Save</button> <button onClick={() => updateTagInfo()}>Save</button>
</div> </div>
</div> </div>