Add: support delete tag and its references
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -265,58 +269,60 @@ ORDER BY reviews.created_at
|
|||||||
;`
|
;`
|
||||||
|
|
||||||
type Stmt struct {
|
type Stmt struct {
|
||||||
initFilesTable *sql.Stmt
|
initFilesTable *sql.Stmt
|
||||||
initFoldersTable *sql.Stmt
|
initFoldersTable *sql.Stmt
|
||||||
initFeedbacksTable *sql.Stmt
|
initFeedbacksTable *sql.Stmt
|
||||||
initUsersTable *sql.Stmt
|
initUsersTable *sql.Stmt
|
||||||
initAvatarsTable *sql.Stmt
|
initAvatarsTable *sql.Stmt
|
||||||
initTagsTable *sql.Stmt
|
initTagsTable *sql.Stmt
|
||||||
initFileHasTag *sql.Stmt
|
initFileHasTag *sql.Stmt
|
||||||
initLikesTable *sql.Stmt
|
initLikesTable *sql.Stmt
|
||||||
initReviewsTable *sql.Stmt
|
initReviewsTable *sql.Stmt
|
||||||
initPlaybacksTable *sql.Stmt
|
initPlaybacksTable *sql.Stmt
|
||||||
initLogsTable *sql.Stmt
|
initLogsTable *sql.Stmt
|
||||||
initTmpfsTable *sql.Stmt
|
initTmpfsTable *sql.Stmt
|
||||||
insertFolder *sql.Stmt
|
insertFolder *sql.Stmt
|
||||||
insertFile *sql.Stmt
|
insertFile *sql.Stmt
|
||||||
findFolder *sql.Stmt
|
findFolder *sql.Stmt
|
||||||
findFile *sql.Stmt
|
findFile *sql.Stmt
|
||||||
searchFiles *sql.Stmt
|
searchFiles *sql.Stmt
|
||||||
getFolder *sql.Stmt
|
getFolder *sql.Stmt
|
||||||
dropFiles *sql.Stmt
|
dropFiles *sql.Stmt
|
||||||
dropFolder *sql.Stmt
|
dropFolder *sql.Stmt
|
||||||
getFile *sql.Stmt
|
getFile *sql.Stmt
|
||||||
searchFolders *sql.Stmt
|
searchFolders *sql.Stmt
|
||||||
getFilesInFolder *sql.Stmt
|
getFilesInFolder *sql.Stmt
|
||||||
getRandomFiles *sql.Stmt
|
getRandomFiles *sql.Stmt
|
||||||
getRandomFilesWithTag *sql.Stmt
|
getRandomFilesWithTag *sql.Stmt
|
||||||
insertFeedback *sql.Stmt
|
insertFeedback *sql.Stmt
|
||||||
getFeedbacks *sql.Stmt
|
getFeedbacks *sql.Stmt
|
||||||
deleteFeedback *sql.Stmt
|
deleteFeedback *sql.Stmt
|
||||||
insertUser *sql.Stmt
|
insertUser *sql.Stmt
|
||||||
countUser *sql.Stmt
|
countUser *sql.Stmt
|
||||||
countAdmin *sql.Stmt
|
countAdmin *sql.Stmt
|
||||||
getUser *sql.Stmt
|
getUser *sql.Stmt
|
||||||
getUsers *sql.Stmt
|
getUsers *sql.Stmt
|
||||||
getUserById *sql.Stmt
|
getUserById *sql.Stmt
|
||||||
updateUserActive *sql.Stmt
|
updateUserActive *sql.Stmt
|
||||||
updateUsername *sql.Stmt
|
updateUsername *sql.Stmt
|
||||||
updateUserPassword *sql.Stmt
|
updateUserPassword *sql.Stmt
|
||||||
getAnonymousUser *sql.Stmt
|
getAnonymousUser *sql.Stmt
|
||||||
insertTag *sql.Stmt
|
insertTag *sql.Stmt
|
||||||
getTag *sql.Stmt
|
deleteTag *sql.Stmt
|
||||||
getTags *sql.Stmt
|
getTag *sql.Stmt
|
||||||
updateTag *sql.Stmt
|
getTags *sql.Stmt
|
||||||
putTagOnFile *sql.Stmt
|
updateTag *sql.Stmt
|
||||||
getTagsOnFile *sql.Stmt
|
putTagOnFile *sql.Stmt
|
||||||
deleteTagOnFile *sql.Stmt
|
getTagsOnFile *sql.Stmt
|
||||||
updateFoldername *sql.Stmt
|
deleteTagOnFile *sql.Stmt
|
||||||
insertReview *sql.Stmt
|
deleteTagReferenceInFileHasTag *sql.Stmt
|
||||||
getReviewsOnFile *sql.Stmt
|
updateFoldername *sql.Stmt
|
||||||
getReview *sql.Stmt
|
insertReview *sql.Stmt
|
||||||
updateReview *sql.Stmt
|
getReviewsOnFile *sql.Stmt
|
||||||
deleteReview *sql.Stmt
|
getReview *sql.Stmt
|
||||||
getReviewsByUser *sql.Stmt
|
updateReview *sql.Stmt
|
||||||
|
deleteReview *sql.Stmt
|
||||||
|
getReviewsByUser *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user