checkpoint: column repositioning implementation
This commit is contained in:
parent
73547c49c6
commit
4286d8fcc2
2 changed files with 83 additions and 7 deletions
|
@ -11,6 +11,7 @@ import (
|
||||||
bolt "go.etcd.io/bbolt"
|
bolt "go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Board is probably the heart of Pelican.
|
||||||
type Board struct {
|
type Board struct {
|
||||||
db *bolt.DB
|
db *bolt.DB
|
||||||
}
|
}
|
||||||
|
@ -90,9 +91,7 @@ func (b *Board) StatusList() ([]Status, error) {
|
||||||
return statuses, nil
|
return statuses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status returns a single status from the db.
|
// Status returns a single status from the database.
|
||||||
// TODO: Add a test case that handles when a status does not exist.
|
|
||||||
// Or use in delete status case.
|
|
||||||
func (b *Board) Status(statusID int) (Status, error) {
|
func (b *Board) Status(statusID int) (Status, error) {
|
||||||
data, err := db.Read(b.db, db.StatusBucket, statusID)
|
data, err := db.Read(b.db, db.StatusBucket, statusID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -116,6 +115,7 @@ func (b *Board) Status(statusID int) (Status, error) {
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatusArgs is an argument type for creating or updating statuses.
|
||||||
type StatusArgs struct {
|
type StatusArgs struct {
|
||||||
Name string
|
Name string
|
||||||
Position int
|
Position int
|
||||||
|
@ -198,21 +198,44 @@ func (b *Board) DeleteStatus(statusID int) error {
|
||||||
return fmt.Errorf("unable to delete the status from the database; %w", err)
|
return fmt.Errorf("unable to delete the status from the database; %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := b.normaliseStatusesPositionValues(); err != nil {
|
if err := b.normaliseStatusesPositionValuesFromDatabase(); err != nil {
|
||||||
return fmt.Errorf("unable to normalise the statuses position values; %w", err)
|
return fmt.Errorf("unable to normalise the statuses position values; %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// normaliseStatusesPositionValues retrieves the ordered list of statuses from the database and sets
|
// RepositionStatus re-positions a status on the Kanban board.
|
||||||
// each status' positional value based on its position in the list.
|
func (b *Board) RepositionStatus(currentPosition, targetPosition int) error {
|
||||||
func (b *Board) normaliseStatusesPositionValues() error {
|
|
||||||
statuses, err := b.StatusList()
|
statuses, err := b.StatusList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get the list of statuses; %w", err)
|
return fmt.Errorf("unable to get the list of statuses; %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statuses = moveAndShuffle(statuses, currentPosition, targetPosition)
|
||||||
|
|
||||||
|
if err := b.normaliseStatusesPositionValues(statuses); err != nil {
|
||||||
|
return fmt.Errorf("unable to normalise the statuses position values; %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// normaliseStatusesPositionValuesFromDatabase retrieves the ordered list of statuses from the database and sets
|
||||||
|
// each status' positional value based on its position in the list before saving the updates to the database.
|
||||||
|
func (b *Board) normaliseStatusesPositionValuesFromDatabase() error {
|
||||||
|
statuses, err := b.StatusList()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get the list of statuses; %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.normaliseStatusesPositionValues(statuses)
|
||||||
|
}
|
||||||
|
|
||||||
|
// normaliseStatusesPositionValues takes a list of statuses and sets
|
||||||
|
// each status' positional value based on its position in the list before
|
||||||
|
// saving the updates to the database.
|
||||||
|
func (b *Board) normaliseStatusesPositionValues(statuses []Status) error {
|
||||||
for i, status := range statuses {
|
for i, status := range statuses {
|
||||||
updateArgs := UpdateStatusArgs{
|
updateArgs := UpdateStatusArgs{
|
||||||
StatusID: status.ID,
|
StatusID: status.ID,
|
||||||
|
@ -230,6 +253,7 @@ func (b *Board) normaliseStatusesPositionValues() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MoveToStatusArgs is an argument type for moving a card between statuses.
|
||||||
type MoveToStatusArgs struct {
|
type MoveToStatusArgs struct {
|
||||||
CardID int
|
CardID int
|
||||||
CurrentStatusID int
|
CurrentStatusID int
|
||||||
|
@ -260,6 +284,7 @@ func (b *Board) MoveToStatus(args MoveToStatusArgs) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CardArgs is an argument type for creating or updating cards.
|
||||||
type CardArgs struct {
|
type CardArgs struct {
|
||||||
NewTitle string
|
NewTitle string
|
||||||
NewDescription string
|
NewDescription string
|
||||||
|
@ -360,6 +385,7 @@ func (b *Board) CardList(ids []int) ([]Card, error) {
|
||||||
return cards, nil
|
return cards, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateCardArgs is an argument type for updating a card.
|
||||||
type UpdateCardArgs struct {
|
type UpdateCardArgs struct {
|
||||||
CardID int
|
CardID int
|
||||||
CardArgs
|
CardArgs
|
||||||
|
@ -387,6 +413,7 @@ func (b *Board) UpdateCard(args UpdateCardArgs) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteCardArgs is an argument type for deleting a card.
|
||||||
type DeleteCardArgs struct {
|
type DeleteCardArgs struct {
|
||||||
CardID int
|
CardID int
|
||||||
StatusID int
|
StatusID int
|
||||||
|
|
49
internal/board/shuffle.go
Normal file
49
internal/board/shuffle.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package board
|
||||||
|
|
||||||
|
type shuffleDirection int
|
||||||
|
|
||||||
|
const (
|
||||||
|
forwards shuffleDirection = iota
|
||||||
|
backwards
|
||||||
|
)
|
||||||
|
|
||||||
|
// moveAndShuffle creates a new list where the element specified at the index of the current
|
||||||
|
// position is moved to the index of the target position. Elements within the range of the
|
||||||
|
// old and new positions will then shuffle forwards or backwards in the list depending on the
|
||||||
|
// direction of the move.
|
||||||
|
// This is currently used to move specified columns forwards or backwards on the Kanban board.
|
||||||
|
// When a column changes position the other columns shuffle forward or backwards as required.
|
||||||
|
func moveAndShuffle(input []Status, currentPosition, targetPosition int) []Status {
|
||||||
|
var shuffle shuffleDirection
|
||||||
|
|
||||||
|
if targetPosition < currentPosition {
|
||||||
|
// affected elements will need to shuffle backwards if the focused
|
||||||
|
// element moves towards the beginning of the list...
|
||||||
|
shuffle = backwards
|
||||||
|
} else {
|
||||||
|
// ...or else the elements need to shuffle forwards if the focused
|
||||||
|
// element moves towards the end of the list.
|
||||||
|
shuffle = forwards
|
||||||
|
}
|
||||||
|
|
||||||
|
output := make([]Status, len(input))
|
||||||
|
|
||||||
|
for ind := range input {
|
||||||
|
switch {
|
||||||
|
case (shuffle == backwards) && (ind < targetPosition || ind > currentPosition):
|
||||||
|
output[ind] = input[ind]
|
||||||
|
case (shuffle == backwards) && (ind == currentPosition):
|
||||||
|
output[targetPosition] = input[ind]
|
||||||
|
case (shuffle == backwards):
|
||||||
|
output[ind+1] = input[ind]
|
||||||
|
case (shuffle == forwards) && (ind < currentPosition || ind > targetPosition):
|
||||||
|
output[ind] = input[ind]
|
||||||
|
case (shuffle == forwards) && (ind == currentPosition):
|
||||||
|
output[targetPosition] = input[ind]
|
||||||
|
case (shuffle == forwards):
|
||||||
|
output[ind-1] = input[ind]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
Loading…
Reference in a new issue