account page: fixed platform reordering bugs
This commit is contained in:
@@ -12,10 +12,15 @@ import (
|
||||
)
|
||||
|
||||
// TODO: simpify, if possible (single query ideal)
|
||||
func (db *Store) SetOrderOfPlatformOnAccountPage(ctx context.Context, acctID int64, platform Platform, orderIndex int) error {
|
||||
func (db *Store) SetOrderOfPlatformOnAccountPage(
|
||||
ctx context.Context,
|
||||
acctID int64,
|
||||
platform Platform,
|
||||
orderIndex int,
|
||||
) (orderedPlatforms []Platform, prevOrderIndex int, err error) {
|
||||
tx, err := db.db.Begin(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to start transaction: %w", err)
|
||||
return nil, 0, fmt.Errorf("failed to start transaction: %w", err)
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
@@ -39,7 +44,7 @@ func (db *Store) SetOrderOfPlatformOnAccountPage(ctx context.Context, acctID int
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to perform query to look up existing indexes: %w", err)
|
||||
return nil, 0, fmt.Errorf("failed to perform query to look up existing indexes: %w", err)
|
||||
}
|
||||
|
||||
indexes, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct {
|
||||
@@ -47,7 +52,7 @@ func (db *Store) SetOrderOfPlatformOnAccountPage(ctx context.Context, acctID int
|
||||
Order_index int
|
||||
}])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to scan rows for query to look up existing indexes: %w", err)
|
||||
return nil, 0, fmt.Errorf("failed to scan rows for query to look up existing indexes: %w", err)
|
||||
}
|
||||
|
||||
// compute the implied indexes,
|
||||
@@ -74,9 +79,13 @@ func (db *Store) SetOrderOfPlatformOnAccountPage(ctx context.Context, acctID int
|
||||
}
|
||||
}
|
||||
|
||||
prevOrderIndex := indexPerPlatform[platform]
|
||||
prevOrderIndex = indexPerPlatform[platform]
|
||||
orderedPlatforms = make([]Platform, len(allPlatforms))
|
||||
if indexPerPlatform[platform] == orderIndex {
|
||||
return nil
|
||||
for i := range allPlatforms {
|
||||
orderedPlatforms[i] = platformPerIndex[i]
|
||||
}
|
||||
return orderedPlatforms, prevOrderIndex, nil
|
||||
}
|
||||
|
||||
if increased := orderIndex > prevOrderIndex; increased {
|
||||
@@ -110,6 +119,7 @@ func (db *Store) SetOrderOfPlatformOnAccountPage(ctx context.Context, acctID int
|
||||
valuesLines[i] = fmt.Sprintf("(@account_id, @platform_%d, @order_index_%d::smallint)", i, i)
|
||||
args[fmt.Sprintf("platform_%d", i)] = p
|
||||
args[fmt.Sprintf("order_index_%d", i)] = indexPerPlatform[p]
|
||||
orderedPlatforms[i] = platformPerIndex[i]
|
||||
}
|
||||
|
||||
_, err = tx.Exec(
|
||||
@@ -148,14 +158,14 @@ func (db *Store) SetOrderOfPlatformOnAccountPage(ctx context.Context, acctID int
|
||||
args,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to perform query to delete old indexes and insert new indexes: %w", err)
|
||||
return nil, 0, fmt.Errorf("failed to perform query to delete old indexes and insert new indexes: %w", err)
|
||||
}
|
||||
|
||||
if tx.Commit(ctx); err != nil {
|
||||
return fmt.Errorf("failed to commit txn: %w", err)
|
||||
return nil, 0, fmt.Errorf("failed to commit txn: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return orderedPlatforms, prevOrderIndex, nil
|
||||
}
|
||||
|
||||
func (db *Store) GetOrderOfPlatformsOnAccountPage(ctx context.Context, acctID int64) ([]Platform, error) {
|
||||
|
||||
@@ -51,7 +51,7 @@ func (v_ctx *StoreWithContext) GetAccountPointerByUserID(userID string) (*Accoun
|
||||
return v_ctx.Store.GetAccountPointerByUserID(v_ctx.ctx, userID)
|
||||
}
|
||||
|
||||
func (v_ctx *StoreWithContext) SetOrderOfPlatformOnAccountPage(acctID int64, platform Platform, orderIndex int) error {
|
||||
func (v_ctx *StoreWithContext) SetOrderOfPlatformOnAccountPage(acctID int64, platform Platform, orderIndex int) ([]Platform, int, error) {
|
||||
return v_ctx.Store.SetOrderOfPlatformOnAccountPage(v_ctx.ctx, acctID, platform, orderIndex)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
@@ -19,6 +20,7 @@ import (
|
||||
type accountSubrouter struct {
|
||||
log *logging.Logger
|
||||
accts *accounts.Store
|
||||
pub *sse.UpdateNotificationPublisher
|
||||
}
|
||||
|
||||
func Routes(
|
||||
@@ -30,6 +32,7 @@ func Routes(
|
||||
as := &accountSubrouter{
|
||||
log: logger,
|
||||
accts: accts,
|
||||
pub: pub,
|
||||
}
|
||||
|
||||
r.POST("", response.Handler(as.createAccount))
|
||||
@@ -187,9 +190,13 @@ func getOrderIndexForSyncGroupListingDraftFromPath(c *gin.Context) (int, error)
|
||||
return orderIndex, nil
|
||||
}
|
||||
|
||||
// PUT /:acctID/platforms/:platform/order-index"
|
||||
// this endpoint is called when dragging a platform tab in the accounts page.
|
||||
func (s *accountSubrouter) setOrderOfPlatformOnAccountPage(c *gin.Context) (response.Response, error) {
|
||||
acctID := auth.GetIdentity(c).Account.AccountID
|
||||
|
||||
// validate parameters
|
||||
|
||||
var orderIndex int
|
||||
if v, ok := c.GetPostForm("order-index"); !ok {
|
||||
return nil, response.BadRequest().
|
||||
@@ -216,9 +223,34 @@ func (s *accountSubrouter) setOrderOfPlatformOnAccountPage(c *gin.Context) (resp
|
||||
platform = p
|
||||
}
|
||||
|
||||
if err := s.accts.SetOrderOfPlatformOnAccountPage(c, acctID, platform, orderIndex); err != nil {
|
||||
// update the order
|
||||
|
||||
platforms, prevIndex, err := s.accts.SetOrderOfPlatformOnAccountPage(c, acctID, platform, orderIndex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save record: %w", err)
|
||||
}
|
||||
|
||||
return response.Status(200), nil
|
||||
// emit events on all platforms updated, so the tabs can all refresh (including their logic)
|
||||
|
||||
platformEvents := make([]string, max(orderIndex, prevIndex)-min(orderIndex, prevIndex))
|
||||
if orderIndex > prevIndex {
|
||||
for i := range orderIndex - prevIndex {
|
||||
p := platforms[prevIndex+i]
|
||||
platformEvents[i] = fmt.Sprintf("accounts_%d_platforms_%s_order-index", acctID, lowerSnakeCase(p))
|
||||
}
|
||||
} else if orderIndex < prevIndex {
|
||||
for i := range prevIndex - orderIndex {
|
||||
p := platforms[orderIndex+1+i]
|
||||
platformEvents[i] = fmt.Sprintf("accounts_%d_platforms_%s_order-index", acctID, lowerSnakeCase(p))
|
||||
}
|
||||
}
|
||||
if err := s.pub.Push(c, acctID, platformEvents...); err != nil {
|
||||
s.log.Errorf("failed to publish platform order-index events: %v", err)
|
||||
}
|
||||
|
||||
return response.StatusNoContent(), nil
|
||||
}
|
||||
|
||||
func lowerSnakeCase(s accounts.Platform) string {
|
||||
return strings.ToLower(strings.Join(strings.Split(string(s), " "), "_"))
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package sse
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -120,6 +122,34 @@ func (p *UpdateNotificationPublisher) Publish(pathPattern string) gin.HandlerFun
|
||||
}
|
||||
}
|
||||
|
||||
func (p *UpdateNotificationPublisher) Push(ctx context.Context, acctID int64, eventTypes ...string) error {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(eventTypes))
|
||||
|
||||
errs := make([]error, len(eventTypes))
|
||||
for i, e := range eventTypes {
|
||||
i := i
|
||||
e := e
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := p.queue.Send(ctx, Event{
|
||||
AccountID: acctID,
|
||||
Type: e,
|
||||
Data: []byte(fmt.Sprintf(`{"eventType": %q}`, e)),
|
||||
}); err != nil {
|
||||
errs[i] = fmt.Errorf("failed to send sse event to listener: %w", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return errors.Join(errs...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPathSegments(p string) []string {
|
||||
p = path.Clean(p)
|
||||
if p == "" || p == "." || p == "/" {
|
||||
|
||||
@@ -66,7 +66,7 @@ func Routes(
|
||||
},
|
||||
|
||||
// strings
|
||||
"lowerCamelCase": func(s string) string {
|
||||
"lowerSnakeCase": func(s string) string {
|
||||
return strings.ToLower(strings.Join(strings.Split(s, " "), "_"))
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user