Dan Anglin
0e186be66b
Create a BoltItem interface which is used to make the database fucntions more generic. As part of this change, the Status and Card types have migrated back into the board package.
175 lines
3.9 KiB
Go
175 lines
3.9 KiB
Go
package board
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/gob"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"forge.dananglin.me.uk/code/dananglin/pelican/internal/database"
|
|
bolt "go.etcd.io/bbolt"
|
|
)
|
|
|
|
// LoadBoard reads the board from the database. If no board exists then a new one will be created.
|
|
func LoadBoard(path string) (*bolt.DB, error) {
|
|
db, err := database.OpenDatabase(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to open the database, %w", err)
|
|
}
|
|
|
|
statusList, err := ReadStatusList(db)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(statusList) == 0 {
|
|
newStatusList := defaultStatusList()
|
|
|
|
boltItems := make([]database.BoltItem, len(newStatusList))
|
|
|
|
for i := range newStatusList {
|
|
boltItems[i] = &newStatusList[i]
|
|
}
|
|
|
|
if err := database.WriteMany(db, database.StatusBucket, boltItems); err != nil {
|
|
return nil, fmt.Errorf("unable to save the default status list to the database, %w", err)
|
|
}
|
|
}
|
|
|
|
return db, nil
|
|
}
|
|
|
|
// ReadStatusList returns the ordered list of statuses from the database.
|
|
func ReadStatusList(db *bolt.DB) ([]Status, error) {
|
|
data, err := database.ReadAll(db, database.StatusBucket)
|
|
if err != nil {
|
|
return []Status{}, fmt.Errorf("unable to read the status list, %w", err)
|
|
}
|
|
|
|
statuses := make([]Status, len(data))
|
|
|
|
for i, d := range data {
|
|
buf := bytes.NewBuffer(d)
|
|
|
|
decoder := gob.NewDecoder(buf)
|
|
|
|
var s Status
|
|
|
|
if err := decoder.Decode(&s); err != nil {
|
|
return []Status{}, fmt.Errorf("unable to decode data, %w", err)
|
|
}
|
|
|
|
statuses[i] = s
|
|
}
|
|
|
|
sort.Sort(ByStatusOrder(statuses))
|
|
|
|
return statuses, nil
|
|
}
|
|
|
|
// TODO: Finish implementation.
|
|
func ReadStatus(db *bolt.DB) (Status, error) {
|
|
return Status{}, nil
|
|
}
|
|
|
|
// TODO: Finish implementation.
|
|
func CreateStatus(db *bolt.DB) error {
|
|
return nil
|
|
}
|
|
|
|
// TODO: Finish implementation.
|
|
func UpdateStatus(db *bolt.DB) error {
|
|
return nil
|
|
}
|
|
|
|
// TODO: Finish implementation.
|
|
func DeleteStatus(db *bolt.DB) error {
|
|
return nil
|
|
}
|
|
|
|
// CreateCard creates a card in the database.
|
|
func CreateCard(db *bolt.DB, title, content string) error {
|
|
statusList, err := ReadStatusList(db)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to read the status list, %w", err)
|
|
}
|
|
|
|
if len(statusList) == 0 {
|
|
return statusListEmptyError{}
|
|
}
|
|
|
|
card := Card{
|
|
ID: -1,
|
|
Title: title,
|
|
Content: content,
|
|
}
|
|
|
|
cardID, err := database.Write(db, database.CardBucket, &card)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to write card to the database, %w", err)
|
|
}
|
|
|
|
initialStatus := statusList[0]
|
|
|
|
initialStatus.AddCardID(cardID)
|
|
|
|
if _, err := database.Write(db, database.StatusBucket, &initialStatus); err != nil {
|
|
return fmt.Errorf("unable to write the %s status to the database, %w", initialStatus.Name, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ReadCard returns a Card value from the database.
|
|
func ReadCard(db *bolt.DB, id int) (Card, error) {
|
|
data, err := database.Read(db, database.CardBucket, id)
|
|
if err != nil {
|
|
return Card{}, fmt.Errorf("unable to read card [%d] from the database, %w", id, err)
|
|
}
|
|
|
|
var card Card
|
|
|
|
buf := bytes.NewBuffer(data)
|
|
|
|
decoder := gob.NewDecoder(buf)
|
|
|
|
if err := decoder.Decode(&card); err != nil {
|
|
return Card{}, fmt.Errorf("unable to decode data, %w", err)
|
|
}
|
|
|
|
return card, nil
|
|
}
|
|
|
|
// UpdateCard modifies an existing card and saves the modification to the database.
|
|
func UpdateCard(db *bolt.DB, id int, title, content string) error {
|
|
card, err := ReadCard(db, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(title) > 0 {
|
|
card.Title = title
|
|
}
|
|
|
|
if len(content) > 0 {
|
|
card.Content = content
|
|
}
|
|
|
|
if _, err := database.Write(db, database.CardBucket, &card); err != nil {
|
|
return fmt.Errorf("unable to write card to the database, %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// MoveCard moves a card between statuses.
|
|
// TODO: finish implementation.
|
|
func MoveCard(db *bolt.DB, fromStatusID, toStatusID int) error {
|
|
return nil
|
|
}
|
|
|
|
// DeleteCard deletes a card from the database.
|
|
// TODO: finish implementation.
|
|
func DeleteCard(db *bolt.DB, id int) error {
|
|
return nil
|
|
}
|