interface improvements, use integer ids, add htmx for guestbook creation
This commit is contained in:
		
							parent
							
								
									e54875f943
								
							
						
					
					
						commit
						19364225c9
					
				@ -161,10 +161,15 @@ func (app *application) getUser(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
					func (app *application) getGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newTemplateData(r)
 | 
				
			||||||
 | 
					    if r.Header.Get("HX-Request") == "true" {
 | 
				
			||||||
 | 
					        app.renderHTMX(w, r, http.StatusOK, "guestbookcreate.part.html", data)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    app.render(w, r, http.StatusOK, "guestbookcreate.view.tmpl.html", data)
 | 
					    app.render(w, r, http.StatusOK, "guestbookcreate.view.tmpl.html", data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) postGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
					func (app *application) postGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
				
			||||||
 | 
					    userId := app.sessionManager.GetInt64(r.Context(), "authenticatedUserId")
 | 
				
			||||||
    err := r.ParseForm()
 | 
					    err := r.ParseForm()
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
@ -172,23 +177,29 @@ func (app *application) postGuestbookCreate(w http.ResponseWriter, r* http.Reque
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    siteUrl := r.Form.Get("siteurl")
 | 
					    siteUrl := r.Form.Get("siteurl")
 | 
				
			||||||
    shortId := app.createShortId()
 | 
					    shortId := app.createShortId()
 | 
				
			||||||
    _, err = app.guestbooks.Insert(shortId, siteUrl, 0)
 | 
					    _, err = app.guestbooks.Insert(shortId, siteUrl, userId)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    app.sessionManager.Put(r.Context(), "flash", "Guestbook successfully created!")
 | 
					    app.sessionManager.Put(r.Context(), "flash", "Guestbook successfully created!")
 | 
				
			||||||
 | 
					    if r.Header.Get("HX-Request") == "true" {
 | 
				
			||||||
 | 
					        w.Header().Add("HX-Trigger", "newGuestbook")
 | 
				
			||||||
 | 
					        data := app.newTemplateData(r)
 | 
				
			||||||
 | 
					        app.renderHTMX(w, r, http.StatusOK, "guestbookcreatebutton.part.html", data)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    http.Redirect(w, r, fmt.Sprintf("/guestbooks/%s", shortIdToSlug(shortId)), http.StatusSeeOther)
 | 
					    http.Redirect(w, r, fmt.Sprintf("/guestbooks/%s", shortIdToSlug(shortId)), http.StatusSeeOther)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbookList(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getGuestbookList(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    userId := app.sessionManager.GetInt64(r.Context(), "authenticatedUserId")
 | 
					    userId := app.sessionManager.GetInt64(r.Context(), "authenticatedUserId")
 | 
				
			||||||
    guestbooks, err := app.guestbooks.GetAll(userId)
 | 
					    user, err := app.users.GetById(userId)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    user, err := app.users.GetById(userId)
 | 
					    guestbooks, err := app.guestbooks.GetAll(userId)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
@ -196,6 +207,10 @@ func (app *application) getGuestbookList(w http.ResponseWriter, r *http.Request)
 | 
				
			|||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newTemplateData(r)
 | 
				
			||||||
    data.Guestbooks = guestbooks
 | 
					    data.Guestbooks = guestbooks
 | 
				
			||||||
    data.User = user
 | 
					    data.User = user
 | 
				
			||||||
 | 
					    if r.Header.Get("HX-Request") == "true" {
 | 
				
			||||||
 | 
					        app.renderHTMX(w, r, http.StatusCreated, "guestbooklist.part.html", data)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    app.render(w, r, http.StatusOK, "guestbooklist.view.tmpl.html", data)
 | 
					    app.render(w, r, http.StatusOK, "guestbooklist.view.tmpl.html", data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -312,3 +327,9 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt
 | 
				
			|||||||
    app.sessionManager.Put(r.Context(), "flash", "Comment successfully posted!")
 | 
					    app.sessionManager.Put(r.Context(), "flash", "Comment successfully posted!")
 | 
				
			||||||
    http.Redirect(w, r, fmt.Sprintf("/guestbooks/%s", guestbookSlug), http.StatusSeeOther)
 | 
					    http.Redirect(w, r, fmt.Sprintf("/guestbooks/%s", guestbookSlug), http.StatusSeeOther)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *application) deleteGuestbookComment(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					    // slug := r.PathValue("id")
 | 
				
			||||||
 | 
					    // shortId := slugToShortId(slug)
 | 
				
			||||||
 | 
					    // app.guestbookComments.Delete(shortId)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
	"github.com/gorilla/schema"
 | 
						"github.com/gorilla/schema"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -25,6 +26,21 @@ func (app *application) clientError(w http.ResponseWriter, status int) {
 | 
				
			|||||||
    http.Error(w, http.StatusText(status), status)
 | 
					    http.Error(w, http.StatusText(status), status)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *application) renderHTMX(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
 | 
				
			||||||
 | 
					    ts, ok := app.templateCacheHTMX[page]
 | 
				
			||||||
 | 
					    if !ok {
 | 
				
			||||||
 | 
					        err := fmt.Errorf("the template %s does not exist", page)
 | 
				
			||||||
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    w.WriteHeader(status)
 | 
				
			||||||
 | 
					    err := ts.Execute(w, data)
 | 
				
			||||||
 | 
					    if err != nil {
 | 
				
			||||||
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) render(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
 | 
					func (app *application) render(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
 | 
				
			||||||
    ts, ok := app.templateCache[page]
 | 
					    ts, ok := app.templateCache[page]
 | 
				
			||||||
    if !ok {
 | 
					    if !ok {
 | 
				
			||||||
@ -97,3 +113,14 @@ func (app *application) isAuthenticated(r *http.Request) bool {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return isAuthenticated
 | 
					    return isAuthenticated
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *application) getCurrentUser(r *http.Request) *models.User {
 | 
				
			||||||
 | 
					    if !app.isAuthenticated(r) {
 | 
				
			||||||
 | 
					        return nil
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    user, ok := r.Context().Value(userNameContextKey).(models.User)
 | 
				
			||||||
 | 
					    if !ok {
 | 
				
			||||||
 | 
					        return nil
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return &user
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@ type application struct {
 | 
				
			|||||||
    sequence uint16
 | 
					    sequence uint16
 | 
				
			||||||
    logger *slog.Logger
 | 
					    logger *slog.Logger
 | 
				
			||||||
    templateCache map[string]*template.Template
 | 
					    templateCache map[string]*template.Template
 | 
				
			||||||
 | 
					    templateCacheHTMX map[string]*template.Template
 | 
				
			||||||
    guestbooks *models.GuestbookModel
 | 
					    guestbooks *models.GuestbookModel
 | 
				
			||||||
    users *models.UserModel
 | 
					    users *models.UserModel
 | 
				
			||||||
    guestbookComments *models.GuestbookCommentModel
 | 
					    guestbookComments *models.GuestbookCommentModel
 | 
				
			||||||
@ -48,6 +49,12 @@ func main() {
 | 
				
			|||||||
        os.Exit(1)
 | 
					        os.Exit(1)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    templateCacheHTMX, err := newHTMXTemplateCache()
 | 
				
			||||||
 | 
					    if err != nil {
 | 
				
			||||||
 | 
					        logger.Error(err.Error())
 | 
				
			||||||
 | 
					        os.Exit(1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sessionManager := scs.New()
 | 
					    sessionManager := scs.New()
 | 
				
			||||||
    sessionManager.Store = sqlite3store.New(db)
 | 
					    sessionManager.Store = sqlite3store.New(db)
 | 
				
			||||||
    sessionManager.Lifetime = 12 * time.Hour
 | 
					    sessionManager.Lifetime = 12 * time.Hour
 | 
				
			||||||
@ -58,6 +65,7 @@ func main() {
 | 
				
			|||||||
    app := &application{
 | 
					    app := &application{
 | 
				
			||||||
        sequence: 0,
 | 
					        sequence: 0,
 | 
				
			||||||
        templateCache: templateCache,
 | 
					        templateCache: templateCache,
 | 
				
			||||||
 | 
					        templateCacheHTMX: templateCacheHTMX,
 | 
				
			||||||
        logger: logger,
 | 
					        logger: logger,
 | 
				
			||||||
        sessionManager: sessionManager,
 | 
					        sessionManager: sessionManager,
 | 
				
			||||||
        guestbooks: &models.GuestbookModel{DB: db},
 | 
					        guestbooks: &models.GuestbookModel{DB: db},
 | 
				
			||||||
 | 
				
			|||||||
@ -79,8 +79,14 @@ func (app *application) authenticate(next http.Handler) http.Handler {
 | 
				
			|||||||
            app.serverError(w, r, err)
 | 
					            app.serverError(w, r, err)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        user, err := app.users.GetById(id)
 | 
				
			||||||
 | 
					        if err != nil {
 | 
				
			||||||
 | 
					            app.serverError(w, r, err)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if exists {
 | 
					        if exists {
 | 
				
			||||||
            ctx := context.WithValue(r.Context(), isAuthenticatedContextKey, true)
 | 
					            ctx := context.WithValue(r.Context(), isAuthenticatedContextKey, true)
 | 
				
			||||||
 | 
					            ctx = context.WithValue(ctx, userNameContextKey, user)
 | 
				
			||||||
            r = r.WithContext(ctx)
 | 
					            r = r.WithContext(ctx)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        next.ServeHTTP(w, r)
 | 
					        next.ServeHTTP(w, r)
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,7 @@ type templateData struct {
 | 
				
			|||||||
    Form any
 | 
					    Form any
 | 
				
			||||||
    IsAuthenticated bool
 | 
					    IsAuthenticated bool
 | 
				
			||||||
    CSRFToken string
 | 
					    CSRFToken string
 | 
				
			||||||
 | 
					    CurrentUser *models.User
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func humanDate(t time.Time) string {
 | 
					func humanDate(t time.Time) string {
 | 
				
			||||||
@ -34,6 +35,23 @@ var functions = template.FuncMap {
 | 
				
			|||||||
    "slugToShortId": slugToShortId,
 | 
					    "slugToShortId": slugToShortId,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newHTMXTemplateCache() (map[string]*template.Template, error) {
 | 
				
			||||||
 | 
					    cache := map[string]*template.Template{}
 | 
				
			||||||
 | 
					    pages, err := filepath.Glob("./ui/html/htmx/*.part.html")
 | 
				
			||||||
 | 
					    if err != nil {
 | 
				
			||||||
 | 
					        return nil, err
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for _, page := range pages {
 | 
				
			||||||
 | 
					        name := filepath.Base(page)
 | 
				
			||||||
 | 
					        ts, err := template.New(name).Funcs(functions).ParseFiles(page)
 | 
				
			||||||
 | 
					        if err != nil {
 | 
				
			||||||
 | 
					            return nil, err
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        cache[name] = ts
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return cache, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newTemplateCache() (map[string]*template.Template, error) {
 | 
					func newTemplateCache() (map[string]*template.Template, error) {
 | 
				
			||||||
    cache := map[string]*template.Template{}
 | 
					    cache := map[string]*template.Template{}
 | 
				
			||||||
    pages, err := filepath.Glob("./ui/html/pages/*.tmpl.html")
 | 
					    pages, err := filepath.Glob("./ui/html/pages/*.tmpl.html")
 | 
				
			||||||
@ -65,5 +83,6 @@ func (app *application) newTemplateData(r *http.Request) templateData {
 | 
				
			|||||||
        Flash: app.sessionManager.PopString(r.Context(), "flash"),
 | 
					        Flash: app.sessionManager.PopString(r.Context(), "flash"),
 | 
				
			||||||
        IsAuthenticated: app.isAuthenticated(r),
 | 
					        IsAuthenticated: app.isAuthenticated(r),
 | 
				
			||||||
        CSRFToken: nosurf.Token(r),
 | 
					        CSRFToken: nosurf.Token(r),
 | 
				
			||||||
 | 
					        CurrentUser: app.getCurrentUser(r),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ CREATE TABLE guestbooks (
 | 
				
			|||||||
    Id integer primary key autoincrement,
 | 
					    Id integer primary key autoincrement,
 | 
				
			||||||
    ShortId integer UNIQUE NOT NULL,
 | 
					    ShortId integer UNIQUE NOT NULL,
 | 
				
			||||||
    SiteUrl varchar(512) NOT NULL,
 | 
					    SiteUrl varchar(512) NOT NULL,
 | 
				
			||||||
    UserId blob(16) NOT NULL,
 | 
					    UserId integer NOT NULL,
 | 
				
			||||||
    Created datetime NOT NULL,
 | 
					    Created datetime NOT NULL,
 | 
				
			||||||
    IsDeleted boolean NOT NULL DEFAULT FALSE,
 | 
					    IsDeleted boolean NOT NULL DEFAULT FALSE,
 | 
				
			||||||
    IsActive boolean NOT NULL DEFAULT TRUE,
 | 
					    IsActive boolean NOT NULL DEFAULT TRUE,
 | 
				
			||||||
@ -25,8 +25,8 @@ CREATE TABLE guestbooks (
 | 
				
			|||||||
CREATE TABLE guestbook_comments (
 | 
					CREATE TABLE guestbook_comments (
 | 
				
			||||||
    Id integer primary key autoincrement,
 | 
					    Id integer primary key autoincrement,
 | 
				
			||||||
    ShortId integer UNIQUE NOT NULL,
 | 
					    ShortId integer UNIQUE NOT NULL,
 | 
				
			||||||
    GuestbookId blob(16) NOT NULL,
 | 
					    GuestbookId integer NOT NULL,
 | 
				
			||||||
    ParentId blob(16),
 | 
					    ParentId integer,
 | 
				
			||||||
    AuthorName varchar(256) NOT NULL,
 | 
					    AuthorName varchar(256) NOT NULL,
 | 
				
			||||||
    AuthorEmail varchar(256) NOT NULL,
 | 
					    AuthorEmail varchar(256) NOT NULL,
 | 
				
			||||||
    AuthorSite varchar(256),
 | 
					    AuthorSite varchar(256),
 | 
				
			||||||
 | 
				
			|||||||
@ -2,14 +2,15 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
    <head>
 | 
					    <head>
 | 
				
			||||||
        <title>{{ template "title" }} - Guestbook</title>
 | 
					        <title>{{ template "title" }} - webweav.ing</title>
 | 
				
			||||||
        <meta charset="UTF-8">
 | 
					        <meta charset="UTF-8">
 | 
				
			||||||
        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
					        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
        <link href="/static/css/style.css" rel="stylesheet">
 | 
					        <link href="/static/css/style.css" rel="stylesheet">
 | 
				
			||||||
 | 
					        <script src="/static/js/htmx.min.js"></script>
 | 
				
			||||||
    </head>
 | 
					    </head>
 | 
				
			||||||
    <body>
 | 
					    <body>
 | 
				
			||||||
        <header>
 | 
					        <header>
 | 
				
			||||||
            <h1><a href="/">Guestbook</a></h1>
 | 
					            <h1><a href="/">webweav.ing</a></h1>
 | 
				
			||||||
        </header>
 | 
					        </header>
 | 
				
			||||||
        {{ template "nav" . }}
 | 
					        {{ template "nav" . }}
 | 
				
			||||||
        <main>
 | 
					        <main>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								ui/html/htmx/guestbookcreate.part.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ui/html/htmx/guestbookcreate.part.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<form hx-post="/guestbooks/create" hx-target="closest div">
 | 
				
			||||||
 | 
					    <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
 | 
				
			||||||
 | 
					    <label for="siteurl">Site URL: </label>
 | 
				
			||||||
 | 
					    <input type="text" name="siteurl" id="siteurl" required />
 | 
				
			||||||
 | 
					    <button type="submit">Submit</button>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
							
								
								
									
										1
									
								
								ui/html/htmx/guestbookcreatebutton.part.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ui/html/htmx/guestbookcreatebutton.part.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<button hx-get="/guestbooks/create" hx-target="closest">New Guestbook</button>
 | 
				
			||||||
							
								
								
									
										7
									
								
								ui/html/htmx/guestbooklist.part.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								ui/html/htmx/guestbooklist.part.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					<ul id="guestbooks" hx-get="/guestbooks" hx-trigger="newGuestbook from:body">
 | 
				
			||||||
 | 
					    {{ range .Guestbooks }}
 | 
				
			||||||
 | 
					    <li><a href="/guestbooks/{{ shortIdToSlug .ShortId }}">{{ with .SiteUrl }}{{ . }}{{ else }}Untitled{{ end }}</a></li>
 | 
				
			||||||
 | 
					    {{ else }}
 | 
				
			||||||
 | 
					    <p>No Guestbooks yet</p>
 | 
				
			||||||
 | 
					    {{ end }}
 | 
				
			||||||
 | 
					</ul>
 | 
				
			||||||
							
								
								
									
										5
									
								
								ui/html/htmx/newguestbook.part.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								ui/html/htmx/newguestbook.part.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{{ with .Guestbook }}
 | 
				
			||||||
 | 
					<li>
 | 
				
			||||||
 | 
					    <a href="/guestbooks/{{ shortIdToSlug .ShortId }}">{{ with .SiteUrl }}{{ . }}{{ else }}Untitled{{ end }}</a>
 | 
				
			||||||
 | 
					</li>
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
{{ define "title" }}New Comment{{ end }}
 | 
					{{ define "title" }}New Comment{{ end }}
 | 
				
			||||||
{{ define "main" }}
 | 
					{{ define "main" }}
 | 
				
			||||||
<form action="/guestbooks/{{ shortIdToSlug .Guestbook.ShortId }}/comments/create" method="post">
 | 
					<form action="/guestbooks/{{ shortIdToSlug .Guestbook.ShortId }}/comments/create" method="post">
 | 
				
			||||||
 | 
					    <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <label for="authorname">Name: </label>
 | 
					        <label for="authorname">Name: </label>
 | 
				
			||||||
        {{ with .Form.FieldErrors.authorName }}
 | 
					        {{ with .Form.FieldErrors.authorName }}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,4 @@
 | 
				
			|||||||
{{ define "title" }}Create a Guestbook{{ end }}
 | 
					{{ define "title" }}Create a Guestbook{{ end }}
 | 
				
			||||||
{{ define "main" }}
 | 
					{{ define "main" }}
 | 
				
			||||||
<form action="/guestbooks/create" method="post">
 | 
					{{ template "guestbookcreate" }}
 | 
				
			||||||
    <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
 | 
					 | 
				
			||||||
    <label for="siteurl">Site URL: </label>
 | 
					 | 
				
			||||||
    <input type="text" name="siteurl" id="siteurl" required />
 | 
					 | 
				
			||||||
    <input type="submit" />
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
{{ end }}
 | 
					{{ end }}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
{{ define "title" }} Guestbooks  {{ end }}
 | 
					{{ define "title" }} Guestbooks  {{ end }}
 | 
				
			||||||
{{ define "main" }}
 | 
					{{ define "main" }}
 | 
				
			||||||
<h1>Guestbooks run by {{ .User.Username }}</h1>
 | 
					<h1>Guestbooks run by {{ .User.Username }}</h1>
 | 
				
			||||||
<ul>
 | 
					<div>
 | 
				
			||||||
 | 
					    <button hx-get="/guestbooks/create" hx-target="closest div">New Guestbook</button>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<ul id="guestbooks" hx-get="/guestbooks" hx-trigger="newGuestbook from:body" hx-swap="outerHTML">
 | 
				
			||||||
    {{ range .Guestbooks }}
 | 
					    {{ range .Guestbooks }}
 | 
				
			||||||
    <li><a href="/guestbooks/{{ shortIdToSlug .ShortId }}">{{ with .SiteUrl }}{{ . }}{{ else }}Untitled{{ end }}</a></li>
 | 
					    <li><a href="/guestbooks/{{ shortIdToSlug .ShortId }}">{{ with .SiteUrl }}{{ . }}{{ else }}Untitled{{ end }}</a></li>
 | 
				
			||||||
    {{ else }}
 | 
					    {{ else }}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,12 @@
 | 
				
			|||||||
{{ define "title" }}Home{{ end }}
 | 
					{{ define "title" }}Home{{ end }}
 | 
				
			||||||
{{ define "main" }}
 | 
					{{ define "main" }}
 | 
				
			||||||
<h2>Latest Guestbooks</h2>
 | 
					{{ if .IsAuthenticated }}
 | 
				
			||||||
 | 
					<h2>Tools</h2>
 | 
				
			||||||
<p>
 | 
					<p>
 | 
				
			||||||
    <a href="/guestbooks">View Guestbooks</a>
 | 
					    <a href="/guestbooks">Guestbooks</a>
 | 
				
			||||||
</p>
 | 
					 | 
				
			||||||
<p>
 | 
					 | 
				
			||||||
    <a href="/guestbooks/create">Create a Guestbook</a>
 | 
					 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
 | 
					{{ else }}
 | 
				
			||||||
 | 
					<h2>Welcome</h2>
 | 
				
			||||||
 | 
					Welcome to webweav.ing, a collection of webmastery tools created by the <a href="https://32bit.cafe">32-Bit Cafe</a>.
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
{{ end }}
 | 
					{{ end }}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								ui/html/partials/guestbookcreate.part.tmpl.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ui/html/partials/guestbookcreate.part.tmpl.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					{{ define "guestbookcreate" }}
 | 
				
			||||||
 | 
					<form action="/guestbooks/create" method="post">
 | 
				
			||||||
 | 
					    <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
 | 
				
			||||||
 | 
					    <label for="siteurl">Site URL: </label>
 | 
				
			||||||
 | 
					    <input type="text" name="siteurl" id="siteurl" required />
 | 
				
			||||||
 | 
					    <input type="submit" />
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					{{ end }}
 | 
				
			||||||
@ -6,8 +6,8 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        {{ if .IsAuthenticated }}
 | 
					        {{ if .IsAuthenticated }}
 | 
				
			||||||
            {{ with .User }}
 | 
					            {{ with .CurrentUser }}
 | 
				
			||||||
                <a href="/users/{{ .User.ShortId }}">{{ .User.Username }}</a>
 | 
					                Welcome, {{ .Username }}
 | 
				
			||||||
            {{ end }}
 | 
					            {{ end }}
 | 
				
			||||||
            <form action="/users/logout" method="post">
 | 
					            <form action="/users/logout" method="post">
 | 
				
			||||||
                <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
 | 
					                <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								ui/static/js/htmx.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ui/static/js/htmx.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user