Implement dynamically getting board data

This commit is contained in:
Dominic Ferrando
2025-04-17 19:27:47 -04:00
parent 576cc763b0
commit e5b52712d1
16 changed files with 135 additions and 26 deletions
+1 -1
View File
@@ -1 +1 @@
internal/db/comfychan.db
internal/database/comfychan.db
+2 -2
View File
@@ -14,8 +14,8 @@ live:
make -j2 live/templ live/sync_assets
db/seed:
sqlite3 ./internal/db/comfychan.db < ./internal/db/seed.sql
sqlite3 ./internal/database/comfychan.db < ./internal/database/seed.sql
db/seed/f:
rm ./internal/db/comfychan.db && sqlite3 ./internal/db/comfychan.db < ./internal/db/seed.sql
rm ./internal/database/comfychan.db && sqlite3 ./internal/database/comfychan.db < ./internal/database/seed.sql
+19 -4
View File
@@ -1,11 +1,13 @@
package main
import (
"database/sql"
"fmt"
"net/http"
"github.com/dominicf2001/comfychan/internal/database"
"github.com/dominicf2001/comfychan/web/views"
"github.com/dominicf2001/comfychan/web/views/boards"
_ "github.com/mattn/go-sqlite3"
"log"
"net/http"
)
var dev = true
@@ -21,6 +23,12 @@ func disableCacheInDevMode(next http.Handler) http.Handler {
}
func main() {
db, err := sql.Open("sqlite3", "internal/database/comfychan.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
http.Handle("/static/",
disableCacheInDevMode(
http.StripPrefix("/static",
@@ -31,7 +39,14 @@ func main() {
})
http.HandleFunc("/comfy", func(w http.ResponseWriter, r *http.Request) {
boards.Comfy().Render(r.Context(), w)
board, err := database.GetBoard(db, "comfy")
if err != nil {
http.Error(w, "Failed to load boards", http.StatusInternalServerError)
log.Printf("Error fetching boards: %v", err)
return
}
views.Board(board).Render(r.Context(), w)
})
fmt.Println("Listening on :8080")
+2
View File
@@ -3,3 +3,5 @@ module github.com/dominicf2001/comfychan
go 1.23.8
require github.com/a-h/templ v0.3.857
require github.com/mattn/go-sqlite3 v1.14.28 // indirect
+2
View File
@@ -2,3 +2,5 @@ github.com/a-h/templ v0.3.857 h1:6EqcJuGZW4OL+2iZ3MD+NnIcG7nGkaQeF2Zq5kf9ZGg=
github.com/a-h/templ v0.3.857/go.mod h1:qhrhAkRFubE7khxLZHsBFHfX+gWwVNKbzKeF9GlPV4M=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
Binary file not shown.
+34
View File
@@ -0,0 +1,34 @@
package database
import (
"database/sql"
)
func GetBoards(db *sql.DB) ([]Board, error) {
rows, err := db.Query(`select id, name, slug, tag from boards order by slug`)
if err != nil {
return nil, err
}
defer rows.Close()
var result []Board
for rows.Next() {
var b Board
err := rows.Scan(&b.Id, &b.Name, &b.Slug, &b.Tag)
if err != nil {
return nil, err
}
result = append(result, b)
}
return result, rows.Err()
}
func GetBoard(db *sql.DB, slug string) (Board, error) {
row := db.QueryRow(`SELECT id, name, slug, tag FROM boards WHERE slug = ?`, slug)
var result Board
row.Scan(&result.Id, &result.Name, &result.Slug, &result.Tag)
return result, row.Err()
}
+26
View File
@@ -0,0 +1,26 @@
package database
import "time"
type Board struct {
Id int
Slug string
Name string
Tag string
}
type Thread struct {
Id int
BoardId int
Subject string
CreatedAt time.Time
BumpedAt time.Time
}
type Post struct {
Id int
ThreadId int
Author string
Body string
CreatedAt time.Time
}
@@ -8,13 +8,13 @@ CREATE TABLE IF NOT EXISTS boards (
id INTEGER PRIMARY KEY,
slug TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
tag TEXT
tag TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS threads (
id INTEGER PRIMARY KEY AUTOINCREMENT,
board_id INTEGER NOT NULL,
subject TEXT,
subject TEXT NOT NULL DEFAULT '',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
bumped_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE
-1
View File
@@ -1 +0,0 @@
package db
-1
View File
@@ -1 +0,0 @@
package internal
-1
View File
@@ -1 +0,0 @@
package internal
@@ -1,6 +1,10 @@
package boards
package views
import "github.com/dominicf2001/comfychan/web/views/shared"
import (
"fmt"
database "github.com/dominicf2001/comfychan/internal/database"
"github.com/dominicf2001/comfychan/web/views/shared"
)
templ NewThreadForm() {
<form style="display: none;" id="newThreadForm" style="display: ;">
@@ -21,14 +25,14 @@ templ NewThreadForm() {
</form>
}
templ Comfy() {
templ Board(board database.Board) {
@shared.Layout() {
<header class="board-header">
<img src="/static/img/banner-comfy.png"/>
<h1>
"/comfy/" - Comfy
{ fmt.Sprintf("/%s/ - %s", board.Slug, board.Name) }
</h1>
<p>Be comfy fren</p>
<p>{ board.Tag }</p>
</header>
<div class="new-thread-container">
<button _="on click hide me then show #newThreadForm" id="newThreadBtn">[New Thread]</button>
@@ -1,14 +1,18 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.857
package boards
package views
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "github.com/dominicf2001/comfychan/web/views/shared"
import (
"fmt"
database "github.com/dominicf2001/comfychan/internal/database"
"github.com/dominicf2001/comfychan/web/views/shared"
)
func NewThreadForm() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
@@ -39,7 +43,7 @@ func NewThreadForm() templ.Component {
})
}
func Comfy() templ.Component {
func Board(board database.Board) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -72,7 +76,33 @@ func Comfy() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<header class=\"board-header\"><img src=\"/static/img/banner-comfy.png\"><h1>\"/comfy/\" - Comfy</h1><p>Be comfy fren</p></header><div class=\"new-thread-container\"><button _=\"on click hide me then show #newThreadForm\" id=\"newThreadBtn\">[New Thread]</button>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<header class=\"board-header\"><img src=\"/static/img/banner-comfy.png\"><h1>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/%s/ - %s", board.Slug, board.Name))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/views/board.templ`, Line: 33, Col: 54}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1><p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(board.Tag)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/views/board.templ`, Line: 35, Col: 17}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></header><div class=\"new-thread-container\"><button _=\"on click hide me then show #newThreadForm\" id=\"newThreadBtn\">[New Thread]</button>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -80,7 +110,7 @@ func Comfy() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+2 -3
View File
@@ -19,9 +19,8 @@ templ Layout() {
</span>
<span>
[
<a href="/comfy">comfy</a>
/
<a href="#">r9k</a>
<a href="/comfy">comfy</a> /
<a href="/r9k">r9k</a>
]
</span>
</div>
+1 -1
View File
@@ -29,7 +29,7 @@ func Layout() templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>Comfychan</title><script src=\"https://unpkg.com/hyperscript.org@0.9.14\"></script><link rel=\"stylesheet\" href=\"/static/reset.css\"><link rel=\"stylesheet\" href=\"/static/index.css\"></head><body><div id=\"boardList\"><span>[ <a href=\"/\">index</a> ]</span> <span>[ <a href=\"/comfy\">comfy</a> / <a href=\"#\">r9k</a> ]</span></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>Comfychan</title><script src=\"https://unpkg.com/hyperscript.org@0.9.14\"></script><link rel=\"stylesheet\" href=\"/static/reset.css\"><link rel=\"stylesheet\" href=\"/static/index.css\"></head><body><div id=\"boardList\"><span>[ <a href=\"/\">index</a> ]</span> <span>[ <a href=\"/comfy\">comfy</a> / <a href=\"/r9k\">r9k</a> ]</span></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}