Compare commits

...

2 commits

Author SHA1 Message Date
Leon Mika 2411e64a53 Did some restyling 2025-03-29 21:54:14 +11:00
Leon Mika d1e212d5e0 Fixed styling of loging page 2025-03-16 09:57:20 +11:00
14 changed files with 173 additions and 46 deletions

View file

@ -56,6 +56,23 @@ div.post {
* Post form
*/
form.prefs fieldset {
display: inline-grid;
grid-template-columns: auto 1fr;
column-gap: 1rem;
row-gap: 0.5rem;
align-items: center;
border: none;
}
form.prefs label {
text-align: right;
}
form.prefs input[type=text] {
min-width: 400px;
}
form.post-form {
display: grid;
grid-template-columns: auto 23vw;
@ -115,4 +132,29 @@ dialog h3 {
dialog textarea {
min-height: 10vh !important;
width: 100%;
}
@media (max-width: 1000px) {
body.role-site nav.vert {
display: none;
}
form.prefs fieldset {
display: grid;
padding-inline: 0;
margin-block-end: 12px;
grid-template-columns: 1fr;
}
form.prefs label {
margin-block-start: 12px;
display: block;
text-align: left;
}
form.prefs input[type=text] {
width: 100%;
min-width: 50px;
}
}

View file

@ -95,6 +95,47 @@ func (ns NullPageRole) Value() (driver.Value, error) {
return string(ns.PageRole), nil
}
type PostFormat string
const (
PostFormatMarkdown PostFormat = "markdown"
)
func (e *PostFormat) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = PostFormat(s)
case string:
*e = PostFormat(s)
default:
return fmt.Errorf("unsupported scan type for PostFormat: %T", src)
}
return nil
}
type NullPostFormat struct {
PostFormat PostFormat
Valid bool // Valid is true if PostFormat is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullPostFormat) Scan(value interface{}) error {
if value == nil {
ns.PostFormat, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.PostFormat.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullPostFormat) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.PostFormat), nil
}
type PostState string
const (
@ -233,6 +274,7 @@ type Page struct {
BundleID int64
Name string
NameProvenance PageNameProvenance
Format PostFormat
Title pgtype.Text
PostTypeID pgtype.Int8
Body string
@ -249,6 +291,7 @@ type Post struct {
SiteID int64
Title pgtype.Text
PostTypeID pgtype.Int8
Format PostFormat
Body string
State PostState
Props []byte

View file

@ -21,7 +21,7 @@ func (q *Queries) DeletePageWithID(ctx context.Context, id int64) error {
}
const getPageWithID = `-- name: GetPageWithID :one
SELECT id, site_id, bundle_id, name, name_provenance, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE id = $1
SELECT id, site_id, bundle_id, name, name_provenance, format, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE id = $1
`
func (q *Queries) GetPageWithID(ctx context.Context, id int64) (Page, error) {
@ -33,6 +33,7 @@ func (q *Queries) GetPageWithID(ctx context.Context, id int64) (Page, error) {
&i.BundleID,
&i.Name,
&i.NameProvenance,
&i.Format,
&i.Title,
&i.PostTypeID,
&i.Body,
@ -101,7 +102,7 @@ func (q *Queries) InsertPage(ctx context.Context, arg InsertPageParams) (int64,
}
const listPages = `-- name: ListPages :many
SELECT id, site_id, bundle_id, name, name_provenance, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE site_id = $1 ORDER BY name ASC LIMIT 25
SELECT id, site_id, bundle_id, name, name_provenance, format, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at FROM pages WHERE site_id = $1 ORDER BY name ASC LIMIT 25
`
func (q *Queries) ListPages(ctx context.Context, siteID int64) ([]Page, error) {
@ -119,6 +120,7 @@ func (q *Queries) ListPages(ctx context.Context, siteID int64) ([]Page, error) {
&i.BundleID,
&i.Name,
&i.NameProvenance,
&i.Format,
&i.Title,
&i.PostTypeID,
&i.Body,
@ -140,7 +142,7 @@ func (q *Queries) ListPages(ctx context.Context, siteID int64) ([]Page, error) {
}
const listPublishablePages = `-- name: ListPublishablePages :many
SELECT id, site_id, bundle_id, name, name_provenance, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at
SELECT id, site_id, bundle_id, name, name_provenance, format, title, post_type_id, body, state, props, role, publish_date, created_at, updated_at
FROM pages
WHERE id > $1 AND site_id = $2 AND state = 'published'
ORDER BY id LIMIT 100
@ -166,6 +168,7 @@ func (q *Queries) ListPublishablePages(ctx context.Context, arg ListPublishableP
&i.BundleID,
&i.Name,
&i.NameProvenance,
&i.Format,
&i.Title,
&i.PostTypeID,
&i.Body,

View file

@ -21,7 +21,7 @@ func (q *Queries) DeletePost(ctx context.Context, id int64) error {
}
const getPostWithID = `-- name: GetPostWithID :one
SELECT id, site_id, title, post_type_id, body, state, props, publish_date, created_at, updated_at FROM posts WHERE id = $1 LIMIT 1
SELECT id, site_id, title, post_type_id, format, body, state, props, publish_date, created_at, updated_at FROM posts WHERE id = $1 LIMIT 1
`
func (q *Queries) GetPostWithID(ctx context.Context, id int64) (Post, error) {
@ -32,6 +32,7 @@ func (q *Queries) GetPostWithID(ctx context.Context, id int64) (Post, error) {
&i.SiteID,
&i.Title,
&i.PostTypeID,
&i.Format,
&i.Body,
&i.State,
&i.Props,
@ -84,7 +85,7 @@ func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (int64,
}
const listPosts = `-- name: ListPosts :many
SELECT id, site_id, title, post_type_id, body, state, props, publish_date, created_at, updated_at FROM posts WHERE site_id = $1 ORDER BY publish_date DESC LIMIT 25
SELECT id, site_id, title, post_type_id, format, body, state, props, publish_date, created_at, updated_at FROM posts WHERE site_id = $1 ORDER BY publish_date DESC LIMIT 25
`
func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) {
@ -101,6 +102,7 @@ func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) {
&i.SiteID,
&i.Title,
&i.PostTypeID,
&i.Format,
&i.Body,
&i.State,
&i.Props,
@ -119,7 +121,7 @@ func (q *Queries) ListPosts(ctx context.Context, siteID int64) ([]Post, error) {
}
const listPublishablePosts = `-- name: ListPublishablePosts :many
SELECT id, site_id, title, post_type_id, body, state, props, publish_date, created_at, updated_at
SELECT id, site_id, title, post_type_id, format, body, state, props, publish_date, created_at, updated_at
FROM posts
WHERE id > $1 AND site_id = $2 AND state = 'published' AND publish_date <= $3
ORDER BY id LIMIT 100
@ -145,6 +147,7 @@ func (q *Queries) ListPublishablePosts(ctx context.Context, arg ListPublishableP
&i.SiteID,
&i.Title,
&i.PostTypeID,
&i.Format,
&i.Body,
&i.State,
&i.Props,

View file

@ -27,22 +27,35 @@ func (q *Queries) GetSiteWithID(ctx context.Context, id int64) (Site, error) {
return i, err
}
const listSites = `-- name: ListSites :one
const listSites = `-- name: ListSites :many
SELECT id, owner_user_id, name, title, theme, props FROM sites
`
func (q *Queries) ListSites(ctx context.Context) (Site, error) {
row := q.db.QueryRow(ctx, listSites)
var i Site
err := row.Scan(
&i.ID,
&i.OwnerUserID,
&i.Name,
&i.Title,
&i.Theme,
&i.Props,
)
return i, err
func (q *Queries) ListSites(ctx context.Context) ([]Site, error) {
rows, err := q.db.Query(ctx, listSites)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Site
for rows.Next() {
var i Site
if err := rows.Scan(
&i.ID,
&i.OwnerUserID,
&i.Name,
&i.Title,
&i.Theme,
&i.Props,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const newSite = `-- name: NewSite :one

View file

@ -3,9 +3,11 @@ package handlers
import (
"fmt"
"github.com/gofiber/fiber/v3"
"lmika.dev/lmika/hugo-cms/services/sites"
)
type IndexHandler struct {
Sites *sites.Service
}
func (h IndexHandler) Index(c fiber.Ctx) error {
@ -14,5 +16,12 @@ func (h IndexHandler) Index(c fiber.Ctx) error {
return c.Redirect().To(fmt.Sprintf("/sites/%v/posts", prefs.SiteID))
}
return c.Render("index", fiber.Map{}, "layouts/main")
sites, err := h.Sites.ListSites(c.Context())
if err != nil {
return err
}
return c.Render("index", fiber.Map{
"sites": sites,
}, "layouts/main")
}

View file

@ -88,7 +88,7 @@ func main() {
postService := posts.New(dbp, siteBuilderService, jobService)
pageService := pages.New(dbp, siteBuilderService, jobService)
indexHandlers := handlers.IndexHandler{}
indexHandlers := handlers.IndexHandler{Sites: siteService}
siteHandlers := handlers.Site{Site: siteService, Bus: bus}
postHandlers := handlers.Post{Post: postService}
pageHandlers := handlers.Pages{Svc: pageService}

View file

@ -4,8 +4,18 @@ import (
"context"
"lmika.dev/lmika/hugo-cms/gen/sqlc/dbq"
"lmika.dev/lmika/hugo-cms/models"
"lmika.dev/pkg/modash/moslice"
)
func (db *DB) ListSites(ctx context.Context) ([]models.Site, error) {
res, err := db.q.ListSites(ctx)
if err != nil {
return nil, err
}
return moslice.Map(res, dbSiteToSite), nil
}
func (db *DB) InsertSite(ctx context.Context, site *models.Site) error {
id, err := db.q.NewSite(ctx, dbq.NewSiteParams{
Name: site.Name,
@ -27,13 +37,7 @@ func (db *DB) GetSite(ctx context.Context, id int64) (models.Site, error) {
return models.Site{}, err
}
return models.Site{
ID: site.ID,
OwnerUserID: site.OwnerUserID,
Name: site.Name,
Title: site.Title,
Theme: site.Theme,
}, nil
return dbSiteToSite(site), nil
}
func (db *DB) UpdateSite(ctx context.Context, site models.Site) error {
@ -44,3 +48,13 @@ func (db *DB) UpdateSite(ctx context.Context, site models.Site) error {
Theme: site.Theme,
})
}
func dbSiteToSite(site dbq.Site) models.Site {
return models.Site{
ID: site.ID,
OwnerUserID: site.OwnerUserID,
Name: site.Name,
Title: site.Title,
Theme: site.Theme,
}
}

View file

@ -38,6 +38,10 @@ func NewService(
}
}
func (s *Service) ListSites(ctx context.Context) ([]models.Site, error) {
return s.db.ListSites(ctx)
}
func (s *Service) GetSite(ctx context.Context, id int) (models.Site, error) {
return s.db.GetSite(ctx, int64(id))
}

View file

@ -1,4 +1,4 @@
-- name: ListSites :one
-- name: ListSites :many
SELECT * FROM sites;
-- name: GetSiteWithID :one

View file

@ -1,4 +1,4 @@
<form method="post" action="/auth/login" class="post-form">
<form method="post" action="/auth/login">
<p>
<input name="email" value="" placeholder="Email">
</p>

View file

@ -1,6 +1,10 @@
<h1>Thing</h1>
<h1>Sites</h1>
User = {{.user.Email}}
<ul>
{{range .sites}}
<li><a href="/sites/{{.ID}}/posts">{{ .Name }}</a></li>
{{end}}
</ul>
<form method="post" action="/sites">
<input type="submit" value="Create Site">

View file

@ -1,12 +1,10 @@
<form method="post" action="/sites/{{.site.ID}}/posts/new-link">
<p>
<form class="prefs" method="post" action="/sites/{{.site.ID}}/posts/new-link">
<fieldset>
<label>Link URL</label>
<input type="text" name="link_url" value="" />
</p>
<p>
<label>Via URL</label>
<input type="text" name="via_url" value="" />
</p>
</fieldset>
<div class="bottom-area">
<input type="submit" value="Create Post">
</div>

View file

@ -1,9 +1,7 @@
<form method="POST" action="/sites/{{.site.ID}}/settings">
<p>
<form class="prefs" method="POST" action="/sites/{{.site.ID}}/settings">
<fieldset>
<label>Title</label>
<input type="text" name="site_title" value="{{.site.Title}}" />
</p>
<p>
<label>Theme</label>
<select name="site_theme">
{{range .themes}}
@ -14,15 +12,11 @@
{{end}}
{{end}}
</select>
</p>
<p>
<label>URL</label>
<input type="text" name="target_url" value="{{.target.URL}}" />
</p>
<p>
<label>Netlify Site ID</label>
<input type="text" name="target_ref" value="{{.target.TargetRef}}" />
</p>
</fieldset>
<p>
<input type="submit" value="Save" />
</p>