clean up svelte ui big time, and add beginnings of item stuff.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -13,6 +13,7 @@ type Database interface {
|
||||
UserSessions() repositories.UserSessionRepository
|
||||
Activities() repositories.ActivityRepository
|
||||
Periods() repositories.PeriodRepository
|
||||
Items() repositories.ItemRepository
|
||||
}
|
||||
|
||||
// Init gets you database based on the configuration provided.
|
||||
|
||||
@@ -15,6 +15,7 @@ type Database struct {
|
||||
userSessions repositories.UserSessionRepository
|
||||
activities repositories.ActivityRepository
|
||||
periods repositories.PeriodRepository
|
||||
items repositories.ItemRepository
|
||||
}
|
||||
|
||||
func (database *Database) Users() repositories.UserRepository {
|
||||
@@ -33,6 +34,10 @@ func (database *Database) Periods() repositories.PeriodRepository {
|
||||
return database.periods
|
||||
}
|
||||
|
||||
func (database *Database) Items() repositories.ItemRepository {
|
||||
return database.items
|
||||
}
|
||||
|
||||
func Init(cfg config.Database) (*Database, error) {
|
||||
opts := *bbolt.DefaultOptions
|
||||
opts.Timeout = time.Second * 5
|
||||
@@ -57,12 +62,17 @@ func Init(cfg config.Database) (*Database, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items, err := newItemRepository(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
database := &Database{
|
||||
users: users,
|
||||
userSessions: userSessions,
|
||||
periods: periods,
|
||||
activities: activities,
|
||||
items: items,
|
||||
}
|
||||
|
||||
return database, nil
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gisle/stufflog/database/repositories"
|
||||
"github.com/gisle/stufflog/models"
|
||||
"github.com/gisle/stufflog/slerrors"
|
||||
"github.com/vmihailenco/msgpack/v4"
|
||||
"go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
var bnItems = []byte("Item")
|
||||
|
||||
type itemRepository struct {
|
||||
db *bbolt.DB
|
||||
userIdIdx *index
|
||||
}
|
||||
|
||||
func (r *itemRepository) FindID(ctx context.Context, id string) (*models.Item, error) {
|
||||
item := new(models.Item)
|
||||
err := r.db.View(func(tx *bbolt.Tx) error {
|
||||
value := tx.Bucket(bnItems).Get(unsafeStringToBytes(id))
|
||||
if value == nil {
|
||||
return slerrors.NotFound("Period")
|
||||
}
|
||||
err := msgpack.Unmarshal(value, item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (r *itemRepository) List(ctx context.Context) ([]*models.Item, error) {
|
||||
items := make([]*models.Item, 0, 16)
|
||||
err := r.db.View(func(tx *bbolt.Tx) error {
|
||||
cursor := tx.Bucket(bnItems).Cursor()
|
||||
|
||||
for key, value := cursor.First(); key != nil; key, value = cursor.Next() {
|
||||
item := new(models.Item)
|
||||
err := msgpack.Unmarshal(value, item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (r *itemRepository) ListUser(ctx context.Context, user models.User) ([]*models.Item, error) {
|
||||
items := make([]*models.Item, 0, 16)
|
||||
err := r.db.View(func(tx *bbolt.Tx) error {
|
||||
bucket := tx.Bucket(bnItems)
|
||||
|
||||
ids, err := r.userIdIdx.WithTx(tx).Get(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
value := bucket.Get(id)
|
||||
if value == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
item := new(models.Item)
|
||||
err := msgpack.Unmarshal(value, item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (r *itemRepository) Insert(ctx context.Context, item models.Item) error {
|
||||
value, err := msgpack.Marshal(&item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.db.Update(func(tx *bbolt.Tx) error {
|
||||
err := tx.Bucket(bnItems).Put(unsafeStringToBytes(item.ID), value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.index(tx, &item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *itemRepository) Update(ctx context.Context, item models.Item, updates []*models.ItemUpdate) (*models.Item, error) {
|
||||
for _, update := range updates {
|
||||
err := item.ApplyUpdate(*update)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
value, err := msgpack.Marshal(&item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = r.db.Update(func(tx *bbolt.Tx) error {
|
||||
return tx.Bucket(bnItems).Put(unsafeStringToBytes(item.ID), value)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &item, nil
|
||||
}
|
||||
|
||||
func (r *itemRepository) Remove(ctx context.Context, item models.Item) error {
|
||||
return r.db.Update(func(tx *bbolt.Tx) error {
|
||||
err := tx.Bucket(bnItems).Delete(unsafeStringToBytes(item.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.unIndex(tx, &item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *itemRepository) index(tx *bbolt.Tx, item *models.Item) error {
|
||||
idBytes := unsafeStringToBytes(item.ID)
|
||||
|
||||
err := r.userIdIdx.WithTx(tx).Set(idBytes, item.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *itemRepository) unIndex(tx *bbolt.Tx, item *models.Item) error {
|
||||
idBytes := unsafeStringToBytes(item.ID)
|
||||
|
||||
err := r.userIdIdx.WithTx(tx).Set(idBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newItemRepository(db *bbolt.DB) (repositories.ItemRepository, error) {
|
||||
err := db.Update(func(tx *bbolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists(bnItems)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userIdIdx, err := newModelIndex(db, "Item", "UserID")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &itemRepository{
|
||||
db: db,
|
||||
userIdIdx: userIdIdx,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gisle/stufflog/models"
|
||||
)
|
||||
|
||||
type ItemRepository interface {
|
||||
FindID(ctx context.Context, id string) (*models.Item, error)
|
||||
List(ctx context.Context) ([]*models.Item, error)
|
||||
ListUser(ctx context.Context, user models.User) ([]*models.Item, error)
|
||||
Insert(ctx context.Context, item models.Item) error
|
||||
Update(ctx context.Context, item models.Item, updates []*models.ItemUpdate) (*models.Item, error)
|
||||
Remove(ctx context.Context, item models.Item) error
|
||||
}
|
||||
Reference in New Issue
Block a user