Pagination, readable error messages to user, syntax highlighting started.
Pagination now works. Temporary hardcoded 10 pastes per page, will be put in configuration later. Maybe. From now user will receive readable error message if error occured. Started to work on syntax highlighting, tried to make lexers detection work but apparently to no avail.
This commit is contained in:
@@ -34,8 +34,10 @@ import (
|
||||
|
||||
// local
|
||||
"github.com/pztrn/fastpastebin/api/http/static"
|
||||
"github.com/pztrn/fastpastebin/pagination"
|
||||
|
||||
// other
|
||||
"github.com/alecthomas/chroma/lexers"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
@@ -60,7 +62,8 @@ func pasteGET(ec echo.Context) error {
|
||||
paste, err1 := GetByID(pasteID)
|
||||
if err1 != nil {
|
||||
c.Logger.Error().Msgf("Failed to get paste #%d from database: %s", pasteID, err1.Error())
|
||||
return ec.HTML(http.StatusBadRequest, string(errhtml))
|
||||
errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Paste #"+strconv.Itoa(pasteID)+" not found", 1)
|
||||
return ec.HTML(http.StatusBadRequest, errhtmlAsString)
|
||||
}
|
||||
|
||||
pasteHTML, err2 := static.ReadFile("paste.html")
|
||||
@@ -88,14 +91,23 @@ func pastePOST(ec echo.Context) error {
|
||||
}
|
||||
c.Logger.Debug().Msgf("Received parameters: %+v", params)
|
||||
|
||||
// Do nothing if paste contents is empty.
|
||||
if len(params["paste-contents"][0]) == 0 {
|
||||
c.Logger.Debug().Msg("Empty paste submitted, ignoring")
|
||||
errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Empty pastes aren't allowed.", 1)
|
||||
return ec.HTML(http.StatusBadRequest, errhtmlAsString)
|
||||
}
|
||||
|
||||
if !strings.ContainsAny(params["paste-keep-for"][0], "Mmhd") {
|
||||
c.Logger.Debug().Msgf("'Keep paste for' field have invalid value: %s", params["paste-keep-for"][0])
|
||||
return ec.HTML(http.StatusBadRequest, string(errhtml))
|
||||
errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).", 1)
|
||||
return ec.HTML(http.StatusBadRequest, errhtmlAsString)
|
||||
}
|
||||
|
||||
paste := &Paste{
|
||||
Title: params["paste-title"][0],
|
||||
Data: params["paste-contents"][0],
|
||||
Title: params["paste-title"][0],
|
||||
Data: params["paste-contents"][0],
|
||||
Language: params["paste-language"][0],
|
||||
}
|
||||
|
||||
// Paste creation time in UTC.
|
||||
@@ -111,7 +123,8 @@ func pastePOST(ec echo.Context) error {
|
||||
keepFor, err1 := strconv.Atoi(keepForRaw)
|
||||
if err1 != nil {
|
||||
c.Logger.Debug().Msgf("Failed to parse 'Keep for' integer: %s", err1.Error())
|
||||
return ec.HTML(http.StatusBadRequest, string(errhtml))
|
||||
errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).", 1)
|
||||
return ec.HTML(http.StatusBadRequest, errhtmlAsString)
|
||||
}
|
||||
paste.KeepFor = keepFor
|
||||
|
||||
@@ -119,10 +132,21 @@ func pastePOST(ec echo.Context) error {
|
||||
keepForUnit := PASTE_KEEPS_CORELLATION[keepForUnitRaw]
|
||||
paste.KeepForUnitType = keepForUnit
|
||||
|
||||
// Try to autodetect if it was selected.
|
||||
if params["paste-language"][0] == "autodetect" {
|
||||
lexer := lexers.Analyse(params["paste-language"][0])
|
||||
if lexer != nil {
|
||||
paste.Language = lexer.Config().Name
|
||||
} else {
|
||||
paste.Language = "text"
|
||||
}
|
||||
}
|
||||
|
||||
id, err2 := Save(paste)
|
||||
if err2 != nil {
|
||||
c.Logger.Debug().Msgf("Failed to save paste: %s", err2.Error())
|
||||
return ec.HTML(http.StatusBadRequest, string(errhtml))
|
||||
errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Failed to save paste. Please, try again later.", 1)
|
||||
return ec.HTML(http.StatusBadRequest, errhtmlAsString)
|
||||
}
|
||||
|
||||
newPasteIDAsString := strconv.FormatInt(id, 10)
|
||||
@@ -142,7 +166,7 @@ func pastesGET(ec echo.Context) error {
|
||||
return ec.String(http.StatusNotFound, "pastelist_paste.html wasn't found!")
|
||||
}
|
||||
|
||||
pageFromParamRaw := ec.Param("id")
|
||||
pageFromParamRaw := ec.Param("page")
|
||||
var page = 1
|
||||
if pageFromParamRaw != "" {
|
||||
pageRaw := regexInts.FindAllString(pageFromParamRaw, 1)[0]
|
||||
@@ -187,5 +211,10 @@ func pastesGET(ec echo.Context) error {
|
||||
|
||||
pasteListHTMLAsString := strings.Replace(string(pasteListHTML), "{pastes}", pastesString, 1)
|
||||
|
||||
pages := GetPastesPages()
|
||||
c.Logger.Debug().Msgf("Total pages: %d, current: %d", pages, page)
|
||||
paginationHTML := pagination.CreateHTML(page, pages, "/pastes/")
|
||||
pasteListHTMLAsString = strings.Replace(pasteListHTMLAsString, "{pagination}", paginationHTML, -1)
|
||||
|
||||
return ec.HTML(http.StatusOK, string(pasteListHTMLAsString))
|
||||
}
|
||||
|
@@ -27,6 +27,8 @@ package pastes
|
||||
import (
|
||||
// stdlib
|
||||
"time"
|
||||
// other
|
||||
//"github.com/alecthomas/chroma"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -53,4 +55,7 @@ type Paste struct {
|
||||
CreatedAt *time.Time `db:"created_at"`
|
||||
KeepFor int `db:"keep_for"`
|
||||
KeepForUnitType int `db:"keep_for_unit_type"`
|
||||
Language string `db:"language"`
|
||||
}
|
||||
|
||||
func (p *Paste) Highlight() {}
|
||||
|
@@ -24,6 +24,11 @@
|
||||
|
||||
package pastes
|
||||
|
||||
const (
|
||||
// Pagination. Hardcoded for 30 for now.
|
||||
PAGINATION = 10
|
||||
)
|
||||
|
||||
// GetByID returns a single paste by ID.
|
||||
func GetByID(id int) (*Paste, error) {
|
||||
p := &Paste{}
|
||||
@@ -44,10 +49,10 @@ func GetPagedPastes(page int) ([]Paste, error) {
|
||||
// Pagination - 30 pastes on page.
|
||||
var startPagination = 0
|
||||
if page > 1 {
|
||||
startPagination = (page - 1) * 30
|
||||
startPagination = (page - 1) * PAGINATION
|
||||
}
|
||||
|
||||
err := dbConn.Select(&pastes, dbConn.Rebind("SELECT * FROM `pastes` ORDER BY id DESC LIMIT 30 OFFSET ?"), startPagination)
|
||||
err := dbConn.Select(&pastes, dbConn.Rebind("SELECT * FROM `pastes` ORDER BY id DESC LIMIT ? OFFSET ?"), PAGINATION, startPagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,10 +61,30 @@ func GetPagedPastes(page int) ([]Paste, error) {
|
||||
|
||||
}
|
||||
|
||||
// GetPastesPages returns an integer that represents quantity of pages
|
||||
// that can be requested (or drawn in paginator).
|
||||
func GetPastesPages() int {
|
||||
var pastesCount int
|
||||
dbConn := c.Database.GetDatabaseConnection()
|
||||
err := dbConn.Get(&pastesCount, "SELECT COUNT(id) FROM `pastes`")
|
||||
if err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Calculate pages.
|
||||
pages := pastesCount / PAGINATION
|
||||
// Check if we have any remainder. Add 1 to pages count if so.
|
||||
if pastesCount%PAGINATION != 0 {
|
||||
pages += 1
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
|
||||
// Save saves paste to database and returns it's ID.
|
||||
func Save(p *Paste) (int64, error) {
|
||||
dbConn := c.Database.GetDatabaseConnection()
|
||||
result, err := dbConn.NamedExec("INSERT INTO `pastes` (title, data, created_at, keep_for, keep_for_unit_type) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type)", p)
|
||||
result, err := dbConn.NamedExec("INSERT INTO `pastes` (title, data, created_at, keep_for, keep_for_unit_type, language) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type, :language)", p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user