clean up svelte ui big time, and add beginnings of item stuff.
continuous-integration/drone/push Build is passing

This commit is contained in:
2020-02-29 16:54:38 +01:00
parent e724eb57b5
commit bb13195f4b
42 changed files with 1051 additions and 504 deletions
+1
View File
@@ -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.
+10
View File
@@ -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
+197
View File
@@ -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
}
+15
View File
@@ -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
}