kanban-app/backend/app/services/card_position_service.py

121 lines
3.8 KiB
Python
Raw Normal View History

2026-02-27 10:54:34 +00:00
"""Service for managing card positioning and reordering"""
from app import db
from app.models import Card
class CardPositionService:
"""Service for handling card position management"""
@staticmethod
2026-02-27 12:41:44 +00:00
def reorder_cards_in_list(
list_id: int, moved_card_id: int, new_position: float
) -> None:
2026-02-27 10:54:34 +00:00
"""
Reorder all cards in a list when one card is moved to a new position.
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
Args:
list_id: The ID of the list containing the cards
moved_card_id: The ID of the card being moved
new_position: The new position for the moved card
"""
# Get all cards in the list, ordered by their current position
2026-02-27 12:41:44 +00:00
all_cards = Card.query.filter_by(list_id=list_id).order_by(Card.pos).all()
2026-02-27 10:54:34 +00:00
# Find the moved card in the list
moved_card = None
other_cards = []
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
for card in all_cards:
if card.id == moved_card_id:
moved_card = card
else:
other_cards.append(card)
if not moved_card:
return # Card not found in this list
# Remove the moved card from other_cards (already done above)
# Insert the moved card at the new position in other_cards
other_cards.insert(int(new_position), moved_card)
# Update positions for all cards to ensure unique, sequential positions
for index, card in enumerate(other_cards):
card.pos = float(index)
db.session.commit()
@staticmethod
def reorder_cards_between_lists(
2026-02-27 12:41:44 +00:00
from_list_id: int, to_list_id: int, moved_card_id: int, new_position: float
2026-02-27 10:54:34 +00:00
) -> None:
"""
Reorder cards when moving a card from one list to another.
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
Args:
from_list_id: The source list ID
2026-02-27 12:41:44 +00:00
to_list_id: The destination list ID
2026-02-27 10:54:34 +00:00
moved_card_id: The ID of the card being moved
new_position: The new position in the destination list
"""
# Reorder source list (remove the card and compact positions)
source_cards = (
Card.query.filter_by(list_id=from_list_id)
.filter(Card.id != moved_card_id)
.order_by(Card.pos)
.all()
)
for index, card in enumerate(source_cards):
card.pos = float(index)
# Reorder destination list (insert the card at new position)
2026-02-27 12:41:44 +00:00
dest_cards = Card.query.filter_by(list_id=to_list_id).order_by(Card.pos).all()
2026-02-27 10:54:34 +00:00
# Insert moved card at the specified position
dest_cards.insert(int(new_position), None) # Placeholder for moved card
for index, card in enumerate(dest_cards):
if card is None:
# This is where our moved card should go
moved_card = Card.query.get(moved_card_id)
if moved_card:
moved_card.pos = float(index)
else:
card.pos = float(index)
db.session.commit()
@staticmethod
def get_next_position(list_id: int) -> float:
"""
Get the next available position in a list.
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
Args:
list_id: The ID of the list
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
Returns:
The next available position (float)
"""
last_card = (
2026-02-27 12:41:44 +00:00
Card.query.filter_by(list_id=list_id).order_by(Card.pos.desc()).first()
2026-02-27 10:54:34 +00:00
)
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
return float(last_card.pos + 1) if last_card else 0.0
@staticmethod
def ensure_unique_positions(list_id: int) -> None:
"""
Ensure all cards in a list have unique, sequential positions.
Useful for data cleanup.
2026-02-27 12:41:44 +00:00
2026-02-27 10:54:34 +00:00
Args:
list_id: The ID of the list to fix
"""
2026-02-27 12:41:44 +00:00
cards = Card.query.filter_by(list_id=list_id).order_by(Card.pos).all()
2026-02-27 10:54:34 +00:00
for index, card in enumerate(cards):
card.pos = float(index)
2026-02-27 12:41:44 +00:00
db.session.commit()