Started working on pages
This commit is contained in:
parent
e2f159e980
commit
ba12398d2f
30 changed files with 1391 additions and 145 deletions
183
services/pages/services.go
Normal file
183
services/pages/services.go
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
package pages
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"lmika.dev/lmika/hugo-cms/models"
|
||||
"lmika.dev/lmika/hugo-cms/providers/db"
|
||||
"lmika.dev/lmika/hugo-cms/services/jobs"
|
||||
"lmika.dev/lmika/hugo-cms/services/sitebuilder"
|
||||
"lmika.dev/pkg/modash/moslice"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
db *db.DB
|
||||
sb *sitebuilder.Service
|
||||
jobs *jobs.Service
|
||||
}
|
||||
|
||||
func New(
|
||||
db *db.DB,
|
||||
sb *sitebuilder.Service,
|
||||
jobs *jobs.Service,
|
||||
) *Service {
|
||||
return &Service{
|
||||
db: db,
|
||||
sb: sb,
|
||||
jobs: jobs,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) ListPagesOfSite(ctx context.Context, site models.Site) ([]models.Page, error) {
|
||||
return s.db.ListPagesOfSite(ctx, site.ID)
|
||||
}
|
||||
|
||||
func (s *Service) GetPage(ctx context.Context, id int) (models.Page, error) {
|
||||
post, err := s.db.GetPage(ctx, int64(id))
|
||||
if err != nil {
|
||||
return models.Page{}, err
|
||||
}
|
||||
|
||||
return post, nil
|
||||
}
|
||||
|
||||
func (s *Service) DeletePage(ctx context.Context, site models.Site, id int) error {
|
||||
post, err := s.db.GetPage(ctx, int64(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.db.DeletePage(ctx, int64(id)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.jobs.Queue(ctx, s.sb.DeletePage(site, post))
|
||||
}
|
||||
|
||||
func (s *Service) Create(ctx context.Context, site models.Site, req NewPost) (models.Page, error) {
|
||||
siteBundles, err := s.db.ListBundles(ctx, site.ID)
|
||||
if err != nil {
|
||||
return models.Page{}, err
|
||||
} else if len(siteBundles) == 0 {
|
||||
return models.Page{}, errors.New("no bundles found")
|
||||
}
|
||||
|
||||
rootBundle, ok := moslice.FindWhere(siteBundles, func(t models.Bundle) bool {
|
||||
return t.Name == models.RootBundleName
|
||||
})
|
||||
if !ok {
|
||||
return models.Page{}, errors.New("root bundle not found")
|
||||
}
|
||||
|
||||
publishTime := time.Now()
|
||||
|
||||
name := s.normalizePageName(req.Title)
|
||||
nameProvenance := models.TitleNameProvenance
|
||||
if name == "" {
|
||||
// Use the timestamp as the name
|
||||
name = publishTime.Format("2006-01-02-150405")
|
||||
nameProvenance = models.DateNameProvenance
|
||||
}
|
||||
|
||||
post := models.Page{
|
||||
SiteID: site.ID,
|
||||
BundleID: rootBundle.ID,
|
||||
Name: s.normalizePageName(req.Title),
|
||||
NameProvenance: nameProvenance,
|
||||
Title: req.Title,
|
||||
Body: req.Body,
|
||||
State: models.PostStatePublished,
|
||||
PublishDate: time.Now(),
|
||||
}
|
||||
|
||||
if err := s.save(ctx, site, rootBundle, &post); err != nil {
|
||||
return models.Page{}, err
|
||||
}
|
||||
|
||||
return post, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, site models.Site, pageID int64, req NewPost) (models.Page, error) {
|
||||
page, err := s.db.GetPage(ctx, pageID)
|
||||
if err != nil {
|
||||
return models.Page{}, err
|
||||
}
|
||||
|
||||
if page.SiteID != site.ID {
|
||||
return models.Page{}, errors.New("page not found")
|
||||
}
|
||||
|
||||
bundle, err := s.db.GetBundleWithID(ctx, page.BundleID)
|
||||
if err != nil {
|
||||
return models.Page{}, err
|
||||
} else if bundle.SiteID != site.ID {
|
||||
return models.Page{}, errors.New("page not found")
|
||||
}
|
||||
|
||||
// Update the title if it wasn't set by the user
|
||||
if page.NameProvenance != models.UserNameProvenance {
|
||||
if req.Title == "" {
|
||||
page.Name = page.PublishDate.Format("2006-01-02-150405")
|
||||
page.NameProvenance = models.DateNameProvenance
|
||||
} else {
|
||||
page.Name = s.normalizePageName(req.Title)
|
||||
page.NameProvenance = models.TitleNameProvenance
|
||||
}
|
||||
}
|
||||
page.Title = req.Title
|
||||
page.Body = req.Body
|
||||
|
||||
if err := s.save(ctx, site, bundle, &page); err != nil {
|
||||
return models.Page{}, err
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (s *Service) save(ctx context.Context, site models.Site, bundle models.Bundle, page *models.Page) error {
|
||||
page.SiteID = site.ID
|
||||
|
||||
if page.ID == 0 {
|
||||
page.CreatedAt = time.Now()
|
||||
page.UpdatedAt = time.Now()
|
||||
if err := s.db.InsertPage(ctx, page); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
page.UpdatedAt = time.Now()
|
||||
if err := s.db.UpdatePage(ctx, page); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return s.jobs.Queue(ctx, s.sb.WritePage(site, bundle, *page))
|
||||
}
|
||||
|
||||
func (s *Service) normalizePageName(title string) string {
|
||||
var sb strings.Builder
|
||||
lastSpace := false
|
||||
for _, r := range title {
|
||||
switch {
|
||||
case unicode.IsSpace(r):
|
||||
if !lastSpace {
|
||||
sb.WriteRune('-')
|
||||
lastSpace = true
|
||||
}
|
||||
case unicode.IsNumber(r):
|
||||
lastSpace = false
|
||||
sb.WriteRune(r)
|
||||
case unicode.IsLetter(r):
|
||||
lastSpace = false
|
||||
sb.WriteRune(unicode.ToLower(r))
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
type NewPost struct {
|
||||
Title string
|
||||
Body string
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue