parent
4903f722b5
commit
60379ba1ef
10 changed files with 143 additions and 9 deletions
|
@ -31,11 +31,12 @@ type DB interface {
|
|||
IncDownloads(ID string) error
|
||||
GetDownloadCounter(ID string) (int, error)
|
||||
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
|
||||
UpdateSubmissionByBook(bookID string, status string, book *Book) error
|
||||
UpdateSubmissionComment(submissionID, bookID, comment string) error
|
||||
GetSubmission(submissionID string) (submission []Submission, err error)
|
||||
GetUserSubmissions(userName string) (submission []Submission, err error)
|
||||
GetComment(bookID string) (string, error)
|
||||
|
||||
BookLister
|
||||
|
@ -228,12 +229,17 @@ CREATE INDEX IF NOT EXISTS visits_book_id_idx on visits(book_id);
|
|||
-- Submissions indexes
|
||||
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_user_idx on submissions(user_id);
|
||||
|
||||
-- Submissions constraint
|
||||
ALTER TABLE ONLY submissions
|
||||
DROP CONSTRAINT IF EXISTS submissions_book_id_fkey;
|
||||
ALTER TABLE ONLY submissions
|
||||
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
|
||||
CREATE INDEX IF NOT EXISTS book_lists_list_id_idx on book_lists(list_id);
|
||||
|
|
|
@ -101,7 +101,7 @@ func (db *roDB) GetFrontPage() FrontPage {
|
|||
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")
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,10 @@ func (db *roDB) GetSubmission(submissionID string) (submission []Submission, err
|
|||
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 {
|
||||
return errors.New("RO database")
|
||||
}
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
package database
|
||||
|
||||
// TODO: clean up old submissions
|
||||
|
||||
type Submission struct {
|
||||
ID int `sql:"type:serial"`
|
||||
SubmissionID string `sql:"type:varchar(16)"`
|
||||
Filename string
|
||||
Status string
|
||||
Comment string
|
||||
UserID int `sql:"type:integer,unique"`
|
||||
User *User
|
||||
BookID string `sql:"type:varchar(16),unique"`
|
||||
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)
|
||||
return submission.ID, err
|
||||
}
|
||||
|
@ -61,6 +71,15 @@ func (db *pgDB) GetSubmission(submissionID string) (submission []Submission, err
|
|||
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{} {
|
||||
if book == nil {
|
||||
return nil
|
||||
|
|
|
@ -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(uploadPostHandler)).Methods("POST")
|
||||
r.HandleFunc("/submission/", sg.Gather(userSubmissionsHandler))
|
||||
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+"}/edit/{id:"+idPattern+"}", sg.Gather(editHandler))
|
||||
|
|
|
@ -102,11 +102,11 @@ func uploadPostHandler(h handler) {
|
|||
log.Error("Can not open uploaded file ", f.Filename, ": ", err)
|
||||
h.sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error")
|
||||
submission.Status = "It was not possible to read the book"
|
||||
h.db.AddSubmission(submission)
|
||||
h.db.AddSubmission(submission, h.sess.User)
|
||||
continue
|
||||
}
|
||||
|
||||
id, err := h.db.AddSubmission(submission)
|
||||
id, err := h.db.AddSubmission(submission, h.sess.User)
|
||||
if err != nil {
|
||||
log.Error("Can add submission to db for ", f.Filename, ": ", err)
|
||||
}
|
||||
|
|
23
lib/user.go
23
lib/user.go
|
@ -112,6 +112,29 @@ func settingsHandler(h handler) {
|
|||
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) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
{{end}}
|
||||
<li class="divider"></li>
|
||||
{{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 class="divider"></li>
|
||||
<li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li>
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
{{end}}
|
||||
<li class="divider"></li>
|
||||
{{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 class="divider"></li>
|
||||
<li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li>
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
<div class="row">
|
||||
<div class="span9">
|
||||
<p><b>{{.Filename}}</b>
|
||||
{{if .Book.Active}}
|
||||
<span class="label label-success">
|
||||
{{else if not .Book.ID}}
|
||||
{{if not .Book}}
|
||||
<span class="label label-important">
|
||||
{{else if .Book.Active}}
|
||||
<span class="label label-success">
|
||||
{{else}}
|
||||
<span class="label label-warning">
|
||||
{{end}}
|
||||
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
{{with .Book}}
|
||||
|
||||
{{if .ID}}
|
||||
{{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>
|
||||
|
@ -68,10 +68,12 @@
|
|||
{{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"}}
|
||||
|
|
77
templates/submissions.html
Normal file
77
templates/submissions.html
Normal 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"}}
|
Reference in a new issue