Be able to list users submisions

- Closes: #45
This commit is contained in:
Las Zenow 2019-03-05 19:54:21 +00:00
parent 4903f722b5
commit 60379ba1ef
10 changed files with 143 additions and 9 deletions

View file

@ -31,11 +31,12 @@ type DB interface {
IncDownloads(ID string) error IncDownloads(ID string) error
GetDownloadCounter(ID string) (int, error) GetDownloadCounter(ID string) (int, error)
GetFrontPage() FrontPage GetFrontPage() FrontPage
AddSubmission(submission Submission) (id int, err error) AddSubmission(submission Submission, userName string) (id int, err error)
UpdateSubmission(id int, status string, book *Book) error UpdateSubmission(id int, status string, book *Book) error
UpdateSubmissionByBook(bookID string, status string, book *Book) error UpdateSubmissionByBook(bookID string, status string, book *Book) error
UpdateSubmissionComment(submissionID, bookID, comment string) error UpdateSubmissionComment(submissionID, bookID, comment string) error
GetSubmission(submissionID string) (submission []Submission, err error) GetSubmission(submissionID string) (submission []Submission, err error)
GetUserSubmissions(userName string) (submission []Submission, err error)
GetComment(bookID string) (string, error) GetComment(bookID string) (string, error)
BookLister BookLister
@ -228,12 +229,17 @@ CREATE INDEX IF NOT EXISTS visits_book_id_idx on visits(book_id);
-- Submissions indexes -- Submissions indexes
CREATE INDEX IF NOT EXISTS submissions_id_idx on submissions(submission_id); CREATE INDEX IF NOT EXISTS submissions_id_idx on submissions(submission_id);
CREATE INDEX IF NOT EXISTS submissions_book_idx on submissions(book_id); CREATE INDEX IF NOT EXISTS submissions_book_idx on submissions(book_id);
CREATE INDEX IF NOT EXISTS submissions_user_idx on submissions(user_id);
-- Submissions constraint -- Submissions constraint
ALTER TABLE ONLY submissions ALTER TABLE ONLY submissions
DROP CONSTRAINT IF EXISTS submissions_book_id_fkey; DROP CONSTRAINT IF EXISTS submissions_book_id_fkey;
ALTER TABLE ONLY submissions ALTER TABLE ONLY submissions
ADD CONSTRAINT submissions_book_id_fkey FOREIGN KEY (book_id) REFERENCES books(id) ON DELETE SET NULL; ADD CONSTRAINT submissions_book_id_fkey FOREIGN KEY (book_id) REFERENCES books(id) ON DELETE SET NULL;
ALTER TABLE ONLY submissions
DROP CONSTRAINT IF EXISTS submissions_user_id_fkey;
ALTER TABLE ONLY submissions
ADD CONSTRAINT submissions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-- BookLists indexes -- BookLists indexes
CREATE INDEX IF NOT EXISTS book_lists_list_id_idx on book_lists(list_id); CREATE INDEX IF NOT EXISTS book_lists_list_id_idx on book_lists(list_id);

View file

@ -101,7 +101,7 @@ func (db *roDB) GetFrontPage() FrontPage {
return db.db.GetFrontPage() return db.db.GetFrontPage()
} }
func (db *roDB) AddSubmission(submission Submission) (id int, err error) { func (db *roDB) AddSubmission(submission Submission, userName string) (id int, err error) {
return 0, errors.New("RO database") return 0, errors.New("RO database")
} }
@ -125,6 +125,10 @@ func (db *roDB) GetSubmission(submissionID string) (submission []Submission, err
return db.db.GetSubmission(submissionID) return db.db.GetSubmission(submissionID)
} }
func (db *roDB) GetUserSubmissions(userName string) (submission []Submission, err error) {
return db.db.GetUserSubmissions(userName)
}
func (db *roDB) NewBookList(listID, title, username string, description []string) error { func (db *roDB) NewBookList(listID, title, username string, description []string) error {
return errors.New("RO database") return errors.New("RO database")
} }

View file

@ -1,16 +1,26 @@
package database package database
// TODO: clean up old submissions
type Submission struct { type Submission struct {
ID int `sql:"type:serial"` ID int `sql:"type:serial"`
SubmissionID string `sql:"type:varchar(16)"` SubmissionID string `sql:"type:varchar(16)"`
Filename string Filename string
Status string Status string
Comment string Comment string
UserID int `sql:"type:integer,unique"`
User *User
BookID string `sql:"type:varchar(16),unique"` BookID string `sql:"type:varchar(16),unique"`
Book *Book Book *Book
} }
func (db *pgDB) AddSubmission(submission Submission) (id int, err error) { func (db *pgDB) AddSubmission(submission Submission, userName string) (id int, err error) {
if userName != "" {
user, err := db.getUser(userName)
if err == nil {
submission.UserID = user.ID
}
}
err = db.sql.Insert(&submission) err = db.sql.Insert(&submission)
return submission.ID, err return submission.ID, err
} }
@ -61,6 +71,15 @@ func (db *pgDB) GetSubmission(submissionID string) (submission []Submission, err
return return
} }
func (db *pgDB) GetUserSubmissions(userName string) (submission []Submission, err error) {
err = db.sql.Model(&submission).
Column("Book", "User").
Where("username = ?", userName).
Order("id DESC").
Select()
return
}
func extractID(book *Book) interface{} { func extractID(book *Book) interface{} {
if book == nil { if book == nil {
return nil return nil

View file

@ -193,6 +193,7 @@ func InitRouter(db database.DB, sg *StatsGatherer, assetsPath string) http.Handl
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/", sg.Gather(userSubmissionsHandler))
r.HandleFunc("/submission/{submissionID:"+idPattern+"}", sg.Gather(submissionHandler)) r.HandleFunc("/submission/{submissionID:"+idPattern+"}", sg.Gather(submissionHandler))
r.HandleFunc("/submission/{submissionID:"+idPattern+"}/comment/{id:"+idPattern+"}", sg.Gather(submissionCommentHandler)).Methods("POST") r.HandleFunc("/submission/{submissionID:"+idPattern+"}/comment/{id:"+idPattern+"}", sg.Gather(submissionCommentHandler)).Methods("POST")
r.HandleFunc("/submission/{submissionID:"+idPattern+"}/edit/{id:"+idPattern+"}", sg.Gather(editHandler)) r.HandleFunc("/submission/{submissionID:"+idPattern+"}/edit/{id:"+idPattern+"}", sg.Gather(editHandler))

View file

@ -102,11 +102,11 @@ func uploadPostHandler(h handler) {
log.Error("Can not open uploaded file ", f.Filename, ": ", err) log.Error("Can not open uploaded file ", f.Filename, ": ", err)
h.sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error") h.sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error")
submission.Status = "It was not possible to read the book" submission.Status = "It was not possible to read the book"
h.db.AddSubmission(submission) h.db.AddSubmission(submission, h.sess.User)
continue continue
} }
id, err := h.db.AddSubmission(submission) id, err := h.db.AddSubmission(submission, h.sess.User)
if err != nil { if err != nil {
log.Error("Can add submission to db for ", f.Filename, ": ", err) log.Error("Can add submission to db for ", f.Filename, ": ", err)
} }

View file

@ -112,6 +112,29 @@ func settingsHandler(h handler) {
h.load("settings", data) h.load("settings", data)
} }
func userSubmissionsHandler(h handler) {
if h.sess.User == "" {
notFound(h)
return
}
var data submissionsData
data.S = GetStatus(h)
data.S.Title = "Submissions"
var err error
data.Submissions, err = h.db.GetUserSubmissions(h.sess.User)
if err != nil {
log.Warn("Can't get submissions for user ", h.sess.User, ": ", err)
}
h.load("submissions", data)
}
type submissionsData struct {
S Status
Submissions []database.Submission
}
func userAdminHandler(h handler) { func userAdminHandler(h handler) {
if !h.sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(h) notFound(h)

View file

@ -12,6 +12,7 @@
{{end}} {{end}}
<li class="divider"></li> <li class="divider"></li>
{{end}} {{end}}
<li><a href="/submission/"><i class="icon-tasks"></i> Submissions</a></li>
<li><a href="/settings/"><i class="icon-wrench"></i> Settings</a></li> <li><a href="/settings/"><i class="icon-wrench"></i> Settings</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li> <li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li>

View file

@ -76,6 +76,7 @@
{{end}} {{end}}
<li class="divider"></li> <li class="divider"></li>
{{end}} {{end}}
<li><a href="/submission/"><i class="icon-tasks"></i> Submissions</a></li>
<li><a href="/settings/"><i class="icon-wrench"></i> Settings</a></li> <li><a href="/settings/"><i class="icon-wrench"></i> Settings</a></li>
<li class="divider"></li> <li class="divider"></li>
<li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li> <li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li>

View file

@ -16,10 +16,10 @@
<div class="row"> <div class="row">
<div class="span9"> <div class="span9">
<p><b>{{.Filename}}</b> <p><b>{{.Filename}}</b>
{{if .Book.Active}} {{if not .Book}}
<span class="label label-success">
{{else if not .Book.ID}}
<span class="label label-important"> <span class="label label-important">
{{else if .Book.Active}}
<span class="label label-success">
{{else}} {{else}}
<span class="label label-warning"> <span class="label label-warning">
{{end}} {{end}}
@ -28,7 +28,7 @@
</div> </div>
{{with .Book}} {{with .Book}}
{{if .ID}} {{if .}}
<div class="span1"> <div class="span1">
<p class="pull-right"><a href="/book/{{.ID}}">{{if .Cover}}<img class="img-rounded" src="/cover/{{.ID}}/small/{{.Title}}.jpg" alt="{{.Title}}" />{{end}}</a></p> <p class="pull-right"><a href="/book/{{.ID}}">{{if .Cover}}<img class="img-rounded" src="/cover/{{.ID}}/small/{{.Title}}.jpg" alt="{{.Title}}" />{{end}}</a></p>
</div> </div>
@ -68,10 +68,12 @@
{{end}} {{end}}
</div> </div>
{{if .Book}}
<form class="row form-inline" method="POST" action="/submission/{{$submissionID}}/comment/{{.Book.ID}}"> <form class="row form-inline" method="POST" action="/submission/{{$submissionID}}/comment/{{.Book.ID}}">
<textarea class="span11" id="comment" rows="2" name="comment" placeholder="Comments about this book submission. Is it a better version than an existing one in the library?">{{.Comment}}</textarea> <textarea class="span11" id="comment" rows="2" name="comment" placeholder="Comments about this book submission. Is it a better version than an existing one in the library?">{{.Comment}}</textarea>
<button type="submit" class="btn btn-primary">Send comment</button> <button type="submit" class="btn btn-primary">Send comment</button>
</form> </form>
{{end}}
{{end}} {{end}}
{{template "footer.html"}} {{template "footer.html"}}

View file

@ -0,0 +1,77 @@
{{template "header.html" .S}}
<div class="row">
<h4>All your submissions:</h4>
</div>
{{$role := .S.Role}}
{{range .Submissions}}
<div class="row">
<div class="row">
<div class="span9">
<p><b>{{.Filename}}</b>
{{if not .Book}}
<span class="label label-important">
{{else if .Book.Active}}
<span class="label label-success">
{{else}}
<span class="label label-warning">
{{end}}
{{.Status}}</span></p>
</div>
<div class="span3">
<h6 class="pull-right"><a href="/submission/{{.SubmissionID}}">Submission {{.SubmissionID}}</a></h6>
</div>
</div>
{{$submissionID := .SubmissionID}}
{{with .Book}}
{{if .}}
<div class="span1">
<p class="pull-right"><a href="/book/{{.ID}}">{{if .Cover}}<img class="img-rounded" src="/cover/{{.ID}}/small/{{.Title}}.jpg" alt="{{.Title}}" />{{end}}</a></p>
</div>
<div class="span10 well">
<div class="row">
<div class="span7">
<p>
<span class="muted">[{{if .Lang}}{{.Lang}}{{end}}]</span>
<a href="/search/?q=title:{{.Title}}"><strong>{{.Title}}</strong></a><br />
{{if .Authors}}<strong>Authors:</strong> {{range .Authors}}<a href="/search/?q=author:{{.}}">{{.}}</a>, {{end}}<br />{{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>
</div>
<div class="span3">
{{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="/read/{{.ID}}" class="btn btn-warning"><i class="icon-eye-open icon-white"></i> read it!</a>
</div>
</div>
</div>
</div>
{{end}}
{{end}}
</div>
{{if .Book}}
<form class="row form-inline" method="POST" action="/submission/{{.SubmissionID}}/comment/{{.Book.ID}}">
<textarea class="span11" id="comment" rows="2" name="comment" placeholder="Comments about this book submission. Is it a better version than an existing one in the library?">{{.Comment}}</textarea>
<button type="submit" class="btn btn-primary">Send comment</button>
</form>
{{end}}
{{end}}
{{template "footer.html"}}