Implement delete in web interface

This commit is contained in:
Radhi Fadlillah 2019-05-29 20:08:58 +07:00
parent 093b398b2f
commit 7ab6c533a3
5 changed files with 127 additions and 31 deletions

View file

@ -36,6 +36,7 @@ export default {
imageURL: String, imageURL: String,
showId: Boolean, showId: Boolean,
listMode: Boolean, listMode: Boolean,
index: Number,
tags: { tags: {
type: Array, type: Array,
default () { default () {
@ -62,13 +63,16 @@ export default {
this.$emit("tagClicked", name); this.$emit("tagClicked", name);
}, },
editBookmark() { editBookmark() {
this.$emit("edit", this.id); this.$emit("edit", this.id, this.index);
}, },
deleteBookmark() { deleteBookmark() {
this.$emit("delete", this.id); this.$emit("delete", {
id: this.id,
index: this.index
});
}, },
updateBookmark() { updateBookmark() {
this.$emit("update", this.id); this.$emit("update", this.id, this.index);
} }
} }
} }

View file

@ -16,12 +16,14 @@ var template = `
</a> </a>
</div> </div>
<div id="bookmarks-grid" ref="bookmarksGrid" :class="{list: displayOptions.listMode}"> <div id="bookmarks-grid" ref="bookmarksGrid" :class="{list: displayOptions.listMode}">
<bookmark-item v-for="book in bookmarks" <bookmark-item v-for="(book, index) in bookmarks"
v-bind="book" v-bind="book"
:key="book.id" :index="index"
:showId="displayOptions.showId" :key="book.id"
:listMode="displayOptions.listMode" :showId="displayOptions.showId"
@tagClicked="filterTag"> :listMode="displayOptions.listMode"
@tagClicked="filterTag"
@delete="showDialogDelete">
</bookmark-item> </bookmark-item>
<div class="pagination-box" v-if="maxPage > 0"> <div class="pagination-box" v-if="maxPage > 0">
<p>Page</p> <p>Page</p>
@ -284,6 +286,70 @@ export default {
} }
}); });
}, },
showDialogDelete(items) {
// Check and filter items
if (typeof items !== "object") return;
if (!Array.isArray(items)) items = [items];
items = items.filter(item => {
var id = (typeof item.id === "number") ? item.id : 0,
index = (typeof item.index === "number") ? item.index : -1;
return id > 0 && index > -1;
});
if (items.length === 0) return;
// Split ids and indices
var ids = items.map(item => item.id),
indices = items.map(item => item.index).sort((a, b) => b - a);
// Create title and content
var title = "Delete Bookmarks",
content = "Delete the selected bookmarks ? This action is irreversible.";
if (items.length === 1) {
title = "Delete Bookmark";
content = "Are you sure ? This action is irreversible.";
}
// Show dialog
this.showDialog({
title: title,
content: content,
mainText: 'Yes',
secondText: 'No',
mainClick: () => {
this.dialog.loading = true;
fetch("/api/bookmarks", {
method: "delete",
body: JSON.stringify(ids),
headers: {
"Content-Type": "application/json",
},
})
.then(response => {
if (!response.ok) throw response;
return response;
})
.then(() => {
this.dialog.loading = false;
this.dialog.visible = false;
indices.forEach(index => this.bookmarks.splice(index, 1))
if (this.bookmarks.length < 20) {
this.loadData(false);
}
})
.catch(err => {
this.dialog.loading = false;
err.text().then(msg => {
this.showErrorDialog(`${msg} (${err.status})`);
})
});
}
});
},
}, },
mounted() { mounted() {
var stateWatcher = (e) => { var stateWatcher = (e) => {

File diff suppressed because one or more lines are too long

View file

@ -6,6 +6,7 @@ import (
"math" "math"
"net/http" "net/http"
nurl "net/url" nurl "net/url"
"os"
"path" "path"
fp "path/filepath" fp "path/filepath"
"strconv" "strconv"
@ -277,3 +278,28 @@ func (h *handler) apiInsertBookmark(w http.ResponseWriter, r *http.Request, ps h
err = json.NewEncoder(w).Encode(&book) err = json.NewEncoder(w).Encode(&book)
checkError(err) checkError(err)
} }
// apiDeleteBookmarks is handler for DELETE /api/bookmark
func (h *handler) apiDeleteBookmark(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// Make sure session still valid
err := h.validateSession(r)
checkError(err)
// Decode request
ids := []int{}
err = json.NewDecoder(r.Body).Decode(&ids)
checkError(err)
// Delete bookmarks
err = h.DB.DeleteBookmarks(ids...)
checkError(err)
// Delete thumbnail image from local disk
for _, id := range ids {
strID := strconv.Itoa(id)
imgPath := fp.Join(h.DataDir, "thumb", strID)
os.Remove(imgPath)
}
fmt.Fprint(w, 1)
}

View file

@ -40,10 +40,10 @@ func ServeApp(DB database.DB, dataDir string, port int) error {
router.GET("/api/bookmarks", hdl.apiGetBookmarks) router.GET("/api/bookmarks", hdl.apiGetBookmarks)
router.GET("/api/tags", hdl.apiGetTags) router.GET("/api/tags", hdl.apiGetTags)
router.POST("/api/bookmarks", hdl.apiInsertBookmark) router.POST("/api/bookmarks", hdl.apiInsertBookmark)
router.DELETE("/api/bookmarks", hdl.apiDeleteBookmark)
// router.PUT("/api/cache", hdl.apiUpdateCache) // router.PUT("/api/cache", hdl.apiUpdateCache)
// router.PUT("/api/bookmarks", hdl.apiUpdateBookmark) // router.PUT("/api/bookmarks", hdl.apiUpdateBookmark)
// router.PUT("/api/bookmarks/tags", hdl.apiUpdateBookmarkTags) // router.PUT("/api/bookmarks/tags", hdl.apiUpdateBookmarkTags)
// router.DELETE("/api/bookmarks", hdl.apiDeleteBookmark)
// Route for panic // Route for panic
router.PanicHandler = func(w http.ResponseWriter, r *http.Request, arg interface{}) { router.PanicHandler = func(w http.ResponseWriter, r *http.Request, arg interface{}) {