aboutsummaryrefslogtreecommitdiffstats
path: root/internal/store
diff options
context:
space:
mode:
Diffstat (limited to 'internal/store')
-rw-r--r--internal/store/design.go69
-rw-r--r--internal/store/menu.go42
-rw-r--r--internal/store/modules.go55
3 files changed, 69 insertions, 97 deletions
diff --git a/internal/store/design.go b/internal/store/design.go
new file mode 100644
index 0000000..4556d96
--- /dev/null
+++ b/internal/store/design.go
@@ -0,0 +1,69 @@
+package store
+
+import (
+ "context"
+ "encoding/json"
+)
+
+// SaveDesign stores the design form in one go: the theme, the modules of every
+// area and the menu, so a half-applied save is impossible. mods and menu are
+// the complete new state in display order: rows with an ID are updated, rows
+// without one inserted, and anything else is deleted.
+func (bs *BlogStore) SaveDesign(ctx context.Context, theme json.RawMessage, mods []Module, menu []MenuItem) error {
+ tx, err := bs.db.Begin(ctx)
+ if err != nil {
+ return err
+ }
+ defer tx.Rollback(ctx)
+ if _, err := tx.Exec(ctx, `UPDATE settings SET theme=$1, updated_at=now()`, theme); err != nil {
+ return err
+ }
+
+ keep := []int64{}
+ for _, m := range mods {
+ if m.ID != 0 {
+ keep = append(keep, m.ID)
+ }
+ }
+ if _, err := tx.Exec(ctx, `DELETE FROM modules WHERE id <> ALL($1)`, keep); err != nil {
+ return err
+ }
+ order := map[string]int{} // sort_order restarts in every area
+ for _, m := range mods {
+ pos := order[m.Area]
+ order[m.Area]++
+ if m.ID != 0 { // area and kind never change
+ _, err = tx.Exec(ctx, `UPDATE modules SET title=$2, body=$3, count=$4, sort_order=$5, updated_at=now() WHERE id=$1`, m.ID, m.Title, m.Body, m.Count, pos)
+ } else {
+ _, err = tx.Exec(ctx, `INSERT INTO modules (area, kind, title, body, count, sort_order) VALUES ($1,$2,$3,$4,$5,$6)`, m.Area, m.Kind, m.Title, m.Body, m.Count, pos)
+ }
+ if err != nil {
+ return wrap(err)
+ }
+ }
+
+ keep = keep[:0]
+ for _, it := range menu {
+ if it.ID != 0 {
+ keep = append(keep, it.ID)
+ }
+ }
+ if _, err := tx.Exec(ctx, `DELETE FROM menu_items WHERE id <> ALL($1)`, keep); err != nil {
+ return err
+ }
+ for i, it := range menu {
+ switch {
+ case it.ID != 0:
+ _, err = tx.Exec(ctx, `UPDATE menu_items SET label=$2, url=$3, sort_order=$4 WHERE id=$1`, it.ID, it.Label, it.URL, i)
+ case it.PageID != nil: // a page deleted meanwhile simply adds nothing
+ _, err = tx.Exec(ctx, `INSERT INTO menu_items (page_id, sort_order) SELECT id, $2 FROM pages WHERE id=$1
+ ON CONFLICT (page_id) WHERE page_id IS NOT NULL DO UPDATE SET sort_order=excluded.sort_order`, *it.PageID, i)
+ default:
+ _, err = tx.Exec(ctx, `INSERT INTO menu_items (label, url, sort_order) VALUES ($1,$2,$3)`, it.Label, it.URL, i)
+ }
+ if err != nil {
+ return wrap(err)
+ }
+ }
+ return tx.Commit(ctx)
+}
diff --git a/internal/store/menu.go b/internal/store/menu.go
index cedb7ad..e2314af 100644
--- a/internal/store/menu.go
+++ b/internal/store/menu.go
@@ -76,45 +76,3 @@ func (bs *BlogStore) SetPageInMenu(ctx context.Context, pageID int64, on bool) e
_, err := bs.db.Exec(ctx, `DELETE FROM menu_items WHERE page_id=$1`, pageID)
return err
}
-
-// AddMenuLink appends a custom link to the menu.
-func (bs *BlogStore) AddMenuLink(ctx context.Context, label, url string) error {
- _, err := bs.db.Exec(ctx, `INSERT INTO menu_items (label, url, sort_order)
- VALUES ($1,$2,(SELECT coalesce(max(sort_order),-1)+1 FROM menu_items))`, label, url)
- return err
-}
-
-func (bs *BlogStore) DeleteMenuItem(ctx context.Context, id int64) error {
- _, err := bs.db.Exec(ctx, `DELETE FROM menu_items WHERE id=$1`, id)
- return err
-}
-
-// MoveMenuItem swaps sort_order with the neighbouring entry (dir = -1 up, +1 down).
-func (bs *BlogStore) MoveMenuItem(ctx context.Context, id int64, dir int) error {
- items, err := bs.ListMenu(ctx)
- if err != nil {
- return err
- }
- idx := -1
- for i := range items {
- if items[i].ID == id {
- idx = i
- }
- }
- j := idx + dir
- if idx < 0 || j < 0 || j >= len(items) {
- return nil
- }
- items[idx], items[j] = items[j], items[idx]
- tx, err := bs.db.Begin(ctx)
- if err != nil {
- return err
- }
- defer tx.Rollback(ctx)
- for i, m := range items { // renumber everything; keeps orders dense
- if _, err := tx.Exec(ctx, `UPDATE menu_items SET sort_order=$2 WHERE id=$1`, m.ID, i); err != nil {
- return err
- }
- }
- return tx.Commit(ctx)
-}
diff --git a/internal/store/modules.go b/internal/store/modules.go
index d077975..99aed1a 100644
--- a/internal/store/modules.go
+++ b/internal/store/modules.go
@@ -48,10 +48,6 @@ func (bs *BlogStore) ListModules(ctx context.Context) ([]Module, error) {
return out, rows.Err()
}
-func (bs *BlogStore) ModuleByID(ctx context.Context, id int64) (*Module, error) {
- return scanModule(bs.db.QueryRow(ctx, `SELECT `+moduleCols+` FROM modules WHERE id=$1`, id))
-}
-
// CreateModule appends a module to the end of its area.
func (bs *BlogStore) CreateModule(ctx context.Context, m *Module) (*Module, error) {
return scanModule(bs.db.QueryRow(ctx, `INSERT INTO modules (area, kind, title, body, count, sort_order)
@@ -59,57 +55,6 @@ func (bs *BlogStore) CreateModule(ctx context.Context, m *Module) (*Module, erro
m.Area, m.Kind, m.Title, m.Body, m.Count))
}
-// UpdateModule saves the editable settings; area and kind never change.
-func (bs *BlogStore) UpdateModule(ctx context.Context, m *Module) error {
- _, err := bs.db.Exec(ctx, `UPDATE modules SET title=$2, body=$3, count=$4, updated_at=now() WHERE id=$1`,
- m.ID, m.Title, m.Body, m.Count)
- return wrap(err)
-}
-
-func (bs *BlogStore) DeleteModule(ctx context.Context, id int64) error {
- _, err := bs.db.Exec(ctx, `DELETE FROM modules WHERE id=$1`, id)
- return err
-}
-
-// MoveModule swaps sort_order with the neighbouring module of the same area (dir = -1 up, +1 down).
-func (bs *BlogStore) MoveModule(ctx context.Context, id int64, dir int) error {
- cur, err := bs.ModuleByID(ctx, id)
- if err != nil {
- return err
- }
- all, err := bs.ListModules(ctx)
- if err != nil {
- return err
- }
- var mods []Module
- idx := -1
- for _, m := range all {
- if m.Area != cur.Area {
- continue
- }
- if m.ID == id {
- idx = len(mods)
- }
- mods = append(mods, m)
- }
- j := idx + dir
- if idx < 0 || j < 0 || j >= len(mods) {
- return nil
- }
- mods[idx], mods[j] = mods[j], mods[idx]
- tx, err := bs.db.Begin(ctx)
- if err != nil {
- return err
- }
- defer tx.Rollback(ctx)
- for i, m := range mods { // renumber the area; keeps orders dense
- if _, err := tx.Exec(ctx, `UPDATE modules SET sort_order=$2 WHERE id=$1`, m.ID, i); err != nil {
- return err
- }
- }
- return tx.Commit(ctx)
-}
-
// ResetModules puts the layout back to what a new blog starts with.
func (bs *BlogStore) ResetModules(ctx context.Context) error {
tx, err := bs.db.Begin(ctx)