Add the avility to edit metadata and delete books after submission
This commit is contained in:
parent
de58f0251e
commit
8d126fbe7a
7 changed files with 93 additions and 48 deletions
28
lib/admin.go
28
lib/admin.go
|
@ -17,14 +17,15 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func deleteHandler(h handler) {
|
func deleteHandler(h handler) {
|
||||||
if !h.sess.IsModerator() {
|
ids := strings.Split(mux.Vars(h.r)["ids"], "/")
|
||||||
|
submissionID := mux.Vars(h.r)["submissionID"]
|
||||||
|
if !h.sess.IsModerator() && !h.booksInSubmission(ids, submissionID) {
|
||||||
notFound(h)
|
notFound(h)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var titles []string
|
var titles []string
|
||||||
var isNew bool
|
var isNew bool
|
||||||
ids := strings.Split(mux.Vars(h.r)["ids"], "/")
|
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
continue
|
continue
|
||||||
|
@ -50,16 +51,25 @@ func deleteHandler(h handler) {
|
||||||
h.sess.Notify("Removed books!", "The books "+strings.Join(titles, ", ")+" are completly removed", "success")
|
h.sess.Notify("Removed books!", "The books "+strings.Join(titles, ", ")+" are completly removed", "success")
|
||||||
}
|
}
|
||||||
h.sess.Save(h.w, h.r)
|
h.sess.Save(h.w, h.r)
|
||||||
if isNew {
|
if submissionID != "" {
|
||||||
|
http.Redirect(h.w, h.r, "/submission/"+submissionID, http.StatusFound)
|
||||||
|
} else if isNew {
|
||||||
http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound)
|
http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound)
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(h.w, h.r, "/", http.StatusFound)
|
http.Redirect(h.w, h.r, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type editData struct {
|
||||||
|
S Status
|
||||||
|
Book database.Book
|
||||||
|
SubmissionID string
|
||||||
|
}
|
||||||
|
|
||||||
func editHandler(h handler) {
|
func editHandler(h handler) {
|
||||||
id := mux.Vars(h.r)["id"]
|
id := mux.Vars(h.r)["id"]
|
||||||
if !h.sess.IsModerator() {
|
submissionID := mux.Vars(h.r)["submissionID"]
|
||||||
|
if !h.sess.IsModerator() && !h.booksInSubmission([]string{id}, submissionID) {
|
||||||
notFound(h)
|
notFound(h)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -69,9 +79,10 @@ func editHandler(h handler) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var data bookData
|
var data editData
|
||||||
data.Book = book
|
data.Book = book
|
||||||
data.S = GetStatus(h)
|
data.S = GetStatus(h)
|
||||||
|
data.SubmissionID = submissionID
|
||||||
author := ""
|
author := ""
|
||||||
if len(book.Authors) > 0 {
|
if len(book.Authors) > 0 {
|
||||||
author = " by " + book.Authors[0]
|
author = " by " + book.Authors[0]
|
||||||
|
@ -93,7 +104,8 @@ func cleanEmptyStr(s []string) []string {
|
||||||
func saveHandler(h handler) {
|
func saveHandler(h handler) {
|
||||||
// XXX: check for errors (ISBN, length(lang), ...)
|
// XXX: check for errors (ISBN, length(lang), ...)
|
||||||
id := mux.Vars(h.r)["id"]
|
id := mux.Vars(h.r)["id"]
|
||||||
if !h.sess.IsModerator() {
|
submissionID := mux.Vars(h.r)["submissionID"]
|
||||||
|
if !h.sess.IsModerator() && !h.booksInSubmission([]string{id}, submissionID) {
|
||||||
notFound(h)
|
notFound(h)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -123,7 +135,9 @@ func saveHandler(h handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
h.sess.Save(h.w, h.r)
|
h.sess.Save(h.w, h.r)
|
||||||
if h.db.IsBookActive(id) {
|
if submissionID != "" {
|
||||||
|
http.Redirect(h.w, h.r, "/submission/"+submissionID, http.StatusFound)
|
||||||
|
} else if h.db.IsBookActive(id) {
|
||||||
http.Redirect(h.w, h.r, "/book/"+id, http.StatusFound)
|
http.Redirect(h.w, h.r, "/book/"+id, http.StatusFound)
|
||||||
} else {
|
} else {
|
||||||
// XXX: I can't use a referer here :(
|
// XXX: I can't use a referer here :(
|
||||||
|
|
24
lib/stats.go
24
lib/stats.go
|
@ -50,6 +50,30 @@ func (h handler) load(tmpl string, data interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h handler) booksInSubmission(bookIDs []string, submissionID string) bool {
|
||||||
|
submissions, err := h.db.GetSubmission(submissionID)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, bookID := range bookIDs {
|
||||||
|
if bookID == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, s := range submissions {
|
||||||
|
if s.BookID == bookID && !s.Book.Active {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type StatsGatherer struct {
|
type StatsGatherer struct {
|
||||||
db database.DB
|
db database.DB
|
||||||
store storage.Store
|
store storage.Store
|
||||||
|
|
|
@ -167,9 +167,14 @@ func InitRouter(db database.DB, sg *StatsGatherer, assetsPath string) http.Handl
|
||||||
|
|
||||||
r.HandleFunc("/book/{id:"+idPattern+"}", sg.Gather(bookHandler))
|
r.HandleFunc("/book/{id:"+idPattern+"}", sg.Gather(bookHandler))
|
||||||
r.HandleFunc("/search/", sg.Gather(searchHandler))
|
r.HandleFunc("/search/", sg.Gather(searchHandler))
|
||||||
|
|
||||||
r.HandleFunc("/upload/", sg.Gather(uploadHandler)).Methods("GET")
|
r.HandleFunc("/upload/", sg.Gather(uploadHandler)).Methods("GET")
|
||||||
r.HandleFunc("/upload/", sg.Gather(uploadPostHandler)).Methods("POST")
|
r.HandleFunc("/upload/", sg.Gather(uploadPostHandler)).Methods("POST")
|
||||||
r.HandleFunc("/submission/{id:"+idPattern+"}", sg.Gather(submissionHandler))
|
r.HandleFunc("/submission/{submissionID:"+idPattern+"}", sg.Gather(submissionHandler))
|
||||||
|
r.HandleFunc("/submission/{submissionID:"+idPattern+"}/edit/{id:"+idPattern+"}", sg.Gather(editHandler))
|
||||||
|
r.HandleFunc("/submission/{submissionID:"+idPattern+"}/save/{id:"+idPattern+"}", sg.Gather(saveHandler)).Methods("POST")
|
||||||
|
r.HandleFunc("/submission/{submissionID:"+idPattern+"}/delete/{ids:(?:"+idPattern+"/)+}", sg.Gather(deleteHandler))
|
||||||
|
|
||||||
r.HandleFunc("/read/{id:"+idPattern+"}", sg.Gather(readStartHandler))
|
r.HandleFunc("/read/{id:"+idPattern+"}", sg.Gather(readStartHandler))
|
||||||
r.HandleFunc("/read/{id:"+idPattern+"}/{file:.*}", sg.Gather(readHandler))
|
r.HandleFunc("/read/{id:"+idPattern+"}/{file:.*}", sg.Gather(readHandler))
|
||||||
r.HandleFunc("/content/{id:"+idPattern+"}/{file:.*}", sg.Gather(contentHandler))
|
r.HandleFunc("/content/{id:"+idPattern+"}/{file:.*}", sg.Gather(contentHandler))
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package trantor
|
package trantor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
log "github.com/cihub/seelog"
|
log "github.com/cihub/seelog"
|
||||||
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
@ -110,32 +112,23 @@ func uploadPostHandler(h handler) {
|
||||||
}
|
}
|
||||||
uploadChannel <- uploadRequest{file, f, id}
|
uploadChannel <- uploadRequest{file, f, id}
|
||||||
}
|
}
|
||||||
_uploadHandler(h, submissionID)
|
http.Redirect(h.w, h.r, "/submission/"+submissionID, http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadHandler(h handler) {
|
func uploadHandler(h handler) {
|
||||||
_uploadHandler(h, "")
|
var data struct{ S Status }
|
||||||
}
|
|
||||||
|
|
||||||
func _uploadHandler(h handler, submissionID string) {
|
|
||||||
var data uploadData
|
|
||||||
data.SubmissionID = submissionID
|
|
||||||
data.S = GetStatus(h)
|
data.S = GetStatus(h)
|
||||||
data.S.Title = "Upload -- " + data.S.Title
|
data.S.Title = "Upload -- " + data.S.Title
|
||||||
data.S.Upload = true
|
data.S.Upload = true
|
||||||
h.load("upload", data)
|
h.load("upload", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
type uploadData struct {
|
|
||||||
S Status
|
|
||||||
SubmissionID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func submissionHandler(h handler) {
|
func submissionHandler(h handler) {
|
||||||
var data submissionData
|
var data submissionData
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
submissionID := mux.Vars(h.r)["id"]
|
submissionID := mux.Vars(h.r)["submissionID"]
|
||||||
|
data.SubmissionID = submissionID
|
||||||
data.Submissions, err = h.db.GetSubmission(submissionID)
|
data.Submissions, err = h.db.GetSubmission(submissionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Can get submission ", submissionID, ": ", err)
|
log.Error("Can get submission ", submissionID, ": ", err)
|
||||||
|
@ -146,8 +139,9 @@ func submissionHandler(h handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type submissionData struct {
|
type submissionData struct {
|
||||||
S Status
|
S Status
|
||||||
Submissions []database.Submission
|
SubmissionID string
|
||||||
|
Submissions []database.Submission
|
||||||
}
|
}
|
||||||
|
|
||||||
func genID() string {
|
func genID() string {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{{template "header.html" .S}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
|
{{$submissionID := .SubmissionID}}
|
||||||
{{with .Book}}
|
{{with .Book}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{if .Cover}}
|
{{if .Cover}}
|
||||||
|
@ -9,7 +10,12 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
<form class="form-horizontal" method="POST" action="/save/{{.ID}}">
|
<form class="form-horizontal" method="POST"
|
||||||
|
{{if $submissionID}}
|
||||||
|
action="/submission/{{$submissionID}}/save/{{.ID}}">
|
||||||
|
{{else}}
|
||||||
|
action="/save/{{.ID}}">
|
||||||
|
{{end}}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="title">Title</label>
|
<label class="control-label" for="title">Title</label>
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
{{template "header.html" .S}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h4>The status of your submission:</h4>
|
<h4>Review your submission:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Check if the book is already in the library, please remove the books that are already in the library in a better or similar edition/quality. You can click on the title or the authors to search for similar books in the library.</li>
|
||||||
|
<li>Edit if needed the title, authors, publisher, ...</li>
|
||||||
|
</ul>
|
||||||
|
<p>Thank you for your submission.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{$role := .S.Role}}
|
{{$role := .S.Role}}
|
||||||
|
{{$submissionID := .SubmissionID}}
|
||||||
{{range .Submissions}}
|
{{range .Submissions}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -19,19 +25,8 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{.Status}}</span></p>
|
{{.Status}}</span></p>
|
||||||
</div>
|
</div>
|
||||||
{{with .Book}}
|
|
||||||
{{if and .ID (not .Active)}}
|
|
||||||
<div class="span2">
|
|
||||||
{{if eq $role "admin" "moderator"}}
|
|
||||||
<div class="btn-group pull-right">
|
|
||||||
<a href="/store/{{.ID}}/" class="btn btn-success"><i class="icon-ok"></i> Save</a>
|
|
||||||
<a href="/edit/{{.ID}}" class="btn btn-primary"><i class="icon-pencil"></i> Edit</a>
|
|
||||||
<a href="/delete/{{.ID}}/" class="btn btn-danger"><i class="icon-remove"></i> Delete</a>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{with .Book}}
|
||||||
|
|
||||||
{{if .ID}}
|
{{if .ID}}
|
||||||
<div class="span1">
|
<div class="span1">
|
||||||
|
@ -42,13 +37,27 @@
|
||||||
<div class="span7">
|
<div class="span7">
|
||||||
<p>
|
<p>
|
||||||
<span class="muted">[{{if .Lang}}{{.Lang}}{{end}}]</span>
|
<span class="muted">[{{if .Lang}}{{.Lang}}{{end}}]</span>
|
||||||
<a href="/book/{{.ID}}"><strong>{{.Title}}</strong></a>
|
<a href="/search/?q=title:{{.Title}}"><strong>{{.Title}}</strong></a><br />
|
||||||
<span class="muted">{{if .Publisher}}{{.Publisher}}{{end}}</span><br />
|
{{if .Authors}}<strong>Authors:</strong> {{range .Authors}}<a href="/search/?q=author:{{.}}">{{.}}</a>, {{end}}<br />{{end}}
|
||||||
{{range .Authors}}{{.}}, {{end}}
|
{{if .Publisher}}<strong>Publisher:</strong> <a href="/search/?q=publisher:{{.Publisher}}">{{.Publisher}}</a><br />{{end}}
|
||||||
|
{{if .Tags}}<strong>Tags:</strong> {{range .Tags}}<a href="/search/?q=tag:{{.}}">{{.}}</a>, {{end}}<br />{{end}}
|
||||||
|
{{if .Isbn}}<strong>ISBN:</strong> {{.Isbn}}<br />{{end}}
|
||||||
|
{{if .Date}}<strong>Date:</strong> {{.Date}}<br />{{end}}
|
||||||
|
{{.Description}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="span3">
|
<div class="span3">
|
||||||
<div class="btn-group pull-right">
|
{{if and .ID (not .Active)}}
|
||||||
|
<div class="row btn-group pull-right">
|
||||||
|
{{if eq $role "admin" "moderator"}}
|
||||||
|
<a href="/store/{{.ID}}/" class="btn btn-success"><i class="icon-ok"></i> Save</a>
|
||||||
|
{{end}}
|
||||||
|
<a href="/submission/{{$submissionID}}/edit/{{.ID}}" class="btn btn-primary"><i class="icon-pencil"></i> Edit</a>
|
||||||
|
<a href="/submission/{{$submissionID}}/delete/{{.ID}}/" class="btn btn-danger"><i class="icon-remove"></i> Delete</a>
|
||||||
|
</div>
|
||||||
|
<div class="row"><p></p></div>
|
||||||
|
{{end}}
|
||||||
|
<div class="row btn-group pull-right">
|
||||||
<a href="/download/{{.ID}}/{{.Title}}.epub" class="btn btn-inverse"><i class="icon-download-alt icon-white"></i> download</a>
|
<a href="/download/{{.ID}}/{{.Title}}.epub" class="btn btn-inverse"><i class="icon-download-alt icon-white"></i> download</a>
|
||||||
<a href="/read/{{.ID}}" class="btn btn-warning"><i class="icon-eye-open icon-white"></i> read it!</a>
|
<a href="/read/{{.ID}}" class="btn btn-warning"><i class="icon-eye-open icon-white"></i> read it!</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
{{template "header.html" .S}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
{{if .SubmissionID}}
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<button class="close" data-dismiss="alert">×</button>
|
|
||||||
<strong>Upload successful!</strong> Thank you for your contribution (<a href="/submission/{{.SubmissionID}}">Review the status of your upload</a>)
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<p>Upload your epubs to help the library.</p>
|
<p>Upload your epubs to help the library.</p>
|
||||||
|
|
||||||
<form class="well form-inline" method="POST" enctype="multipart/form-data">
|
<form class="well form-inline" method="POST" enctype="multipart/form-data">
|
||||||
|
|
Reference in a new issue