Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ name: Go CI

on:
push:
pull_request:

jobs:
build-test-lint:
Expand Down Expand Up @@ -41,3 +40,4 @@ jobs:

- name: Run staticcheck
run: staticcheck ./...

35 changes: 24 additions & 11 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,18 @@ All field names are identical to the ones found in the JSON response data.

### Item

| Field | Type | Description |
| ----------- | ------ | ------------------------------------ |
| id | uint | Unique ID |
| list | uint | ID of list this item is in |
| title | string | Items title |
| description | string | Items description |
| creator | uint | ID of user that created this item |
| assignee | uint | ID of user this item is assigned to |
| branch | string | Name of branch this item is tracking |
| createdAt | uint | Unix time of creation |
| updatedAt | uint | Unix time of last update |
| Field | Type | Description |
| ----------- | ------ | -------------------------------------------------------------------- |
| id | uint | Unique ID |
| status | uint | Item status. See `Status` enum. |
| title | string | Items title |
| description | string | Items description |
| creator | uint | ID of user that created this item |
| assignee | uint | ID of user this item is assigned to |
| branch | string | Name of branch this item is tracking |
| createdAt | uint | Unix time of creation |
| updatedAt | uint | Unix time of last update |
| data | string | Additional data field. Usually for board-specific item data as JSON. |

### ID

Expand All @@ -90,3 +91,15 @@ When creating new objects you get its ID in response.
| ----- | ---- | ---------------- |
| id | uint | ID of new object |

### Status

Item status is one of the following values. They are automatically updated if the item contains github repo/branch info.

| Name | Value | Description |
| ---------------- | ----- | -------------------------------------------------------- |
| StatusBacklog | 0 | Item has been created with little to no details |
| StatusReady | 1 | Item is ready to be worked on and has sufficient details |
| StatusInProgress | 2 | Item is being worked on and tracks a branch |
| StatusInReview | 3 | Item has a pull request open |
| StatusClosed | 4 | Items pull request was merged or closed |

30 changes: 21 additions & 9 deletions api/database/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestDatabase(t *testing.T) {
Title: "Initial Task",
Description: "Setup project",
ConnectedBranch: "main",
List: 1,
Status: StatusInProgress,
CreatorID: userID,
AssigneeID: userID,
}
Expand All @@ -76,33 +76,33 @@ func TestDatabase(t *testing.T) {
assert(t, len(users) >= 2, "expected at least 2 users, got %d", len(users))
})

t.Run("Get all items from list", func(t *testing.T) {
t.Run("Get all items with status", func(t *testing.T) {
board := Board{}
assertNoErr(t, db.db.Create(&board).Error)

item := Item{
BoardID: board.ID,
Title: "List Test",
List: 2,
Title: "Status Test",
Status: StatusInReview,
}
_, err := db.CreateItem(item)
assertNoErr(t, err)

items, err := db.GetAllItemsFromList(board.ID, 2)
items, err := db.GetAllItemsWithStatus(board.ID, StatusInReview)
assertNoErr(t, err)
assert(t, len(items) > 0, "expected at least 1 item in list 2")
assert(t, len(items) > 0, "expected at least 1 item with status 2")
})

t.Run("Move item to list", func(t *testing.T) {
t.Run("Set item status", func(t *testing.T) {
items, _ := db.GetAllItems()
item := items[0]

err := db.MoveItemToList(item.ID, 3)
err := db.ChangeItemStatus(item.ID, StatusClosed)
assertNoErr(t, err)

movedItem, err := db.GetItemById(item.ID)
assertNoErr(t, err)
assert(t, movedItem.List == 3, "item was not moved to list 3")
assert(t, movedItem.Status == StatusClosed, "item was not set to status 3")
})

t.Run("Change item title", func(t *testing.T) {
Expand Down Expand Up @@ -150,4 +150,16 @@ func TestDatabase(t *testing.T) {
_, err = db.GetUserById(id)
assert(t, err != nil, "user should have been deleted")
})

t.Run("Get and set item data", func(t *testing.T) {
id, err := db.CreateItem(Item{})
assertNoErr(t, err)

str := "Hello World"
assertNoErr(t, db.SetItemData(id, str))

data, err := db.GetItemData(id)
assertNoErr(t, err)
assert(t, data == str, "data didnt match expected value")
})
}
14 changes: 13 additions & 1 deletion api/database/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ type Board struct {
Users []User `gorm:"many2many:board_users;" json:"users"`
}

type Status uint

const (
StatusBacklog Status = iota // Item has been created with little to no details
StatusReady // Item is ready to be worked on and has sufficient details
StatusInProgress // Item is being worked on and tracks a branch
StatusInReview // Item has a pull request open
StatusClosed // Items pull request was merged or closed
)

type Item struct {
Model
BoardID uint `json:"boardId"`
Expand All @@ -33,13 +43,15 @@ type Item struct {
Title string `json:"title"`
Description string `json:"description"`
ConnectedBranch string `json:"connectedBranch"`
List uint `json:"list"`
Status Status `json:"status"`

CreatorID uint `json:"-"`
Creator User `gorm:"foreignKey:CreatorID" json:"creator"`

AssigneeID uint `json:"-"`
Assignee User `gorm:"foreignKey:AssigneeID" json:"assignee"`

Data string `json:"data"`
}

type User struct {
Expand Down
27 changes: 21 additions & 6 deletions api/database/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,17 @@ func (db *Database) DeleteItemByID(id uint) error {
return nil
}

func (db *Database) GetAllItemsFromList(boardId, list uint) ([]Item, error) {
func (db *Database) GetAllItemsWithStatus(boardId uint, list Status) ([]Item, error) {
var items []Item
if res := db.db.Find(&items, "list = ?", list); res.Error != nil {
return nil, errors.New("could not find all items from list")
if res := db.db.Find(&items, "status = ?", list); res.Error != nil {
return nil, errors.New("could not find items with status")
}
return items, nil
}

func (db *Database) MoveItemToList(id uint, list uint) error {
if res := db.db.Model(&Item{}).Where("id = ?", id).Update("list", list); res.Error != nil {
return errors.New("could not move item")
func (db *Database) ChangeItemStatus(id uint, list Status) error {
if res := db.db.Model(&Item{}).Where("id = ?", id).Update("status", list); res.Error != nil {
return errors.New("could not set item status")
}
return nil
}
Expand All @@ -92,3 +92,18 @@ func (db *Database) ChangeItemDescription(id uint, description string) error {
}
return nil
}

func (db *Database) SetItemData(id uint, data string) error {
if res := db.db.Model(&Item{}).Where("id = ?", id).Update("data", data); res.Error != nil {
return errors.New("could not set data field")
}
return nil
}

func (db *Database) GetItemData(id uint) (data string, err error) {
var item Item
if res := db.db.First(&item, id); res.Error != nil {
return data, errors.New("item not found")
}
return item.Data, nil
}