Skip to content

Conversation

@ffischbach-ino
Copy link
Member

@ffischbach-ino ffischbach-ino commented Sep 15, 2025

Description

This feature implements real-time card locking to prevent multiple users from simultaneously dragging the same card, eliminating conflicting drag operations. When a user starts dragging a card, other users see visual indicators showing who is currently moving it and are prevented from interfering with the drag operation.

Changelog

Added real-time collaborative drag locking system that displays user avatars and names on cards being moved by other participants, preventing drag conflicts and improving the collaborative editing experience. The system includes WebSocket-based event broadcasting, Redux state management, and comprehensive visual feedback with proper error handling for network failures

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • The light- and dark-theme are both supported and tested
  • The design was implemented and is responsive for all devices and screen sizes
  • The application was tested in the most commonly used browsers (e.g. Chrome, Firefox, Safari)

(Optional) Visual Changes

@ffischbach-ino ffischbach-ino force-pushed the ff/disable-note-moving-for-others-while-dragging-#2891 branch from 0bb8014 to c2942e0 Compare September 15, 2025 11:13
@Schwehn42 Schwehn42 added the Changes Requested Changes requested by the reviewer label Sep 16, 2025
Copy link
Member

@Schwehn42 Schwehn42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locks aren't sent to users who join after it was created:

  1. User A: start dragging a note (can be done on mobile to keep the lock)
  2. User B: reload page
  3. result: lock is not displayed for User B

@Schwehn42 Schwehn42 removed the Changes Requested Changes requested by the reviewer label Oct 9, 2025
Copy link
Member

@Schwehn42 Schwehn42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me all in all!

only comment I have is, currently the websocket handler for incoming messages is part of draglocks itself. would it make sense to abstract/generalize in order to make it usable for other use cases as well?

@Planlos5000
Copy link
Collaborator

I would like to revist the backend implementation for this feature.
I currently found out that nats can provide a key value store with a ttl (https://docs.nats.io/nats-concepts/jetstream/key-value-store) and so can redis. Since we already use nats or redis for messaging, this could be a better fit for this feature to store the lock.

@Planlos5000 Planlos5000 force-pushed the ff/disable-note-moving-for-others-while-dragging-#2891 branch 6 times, most recently from 9e4670c to 0a86128 Compare November 3, 2025 12:10
@Planlos5000 Planlos5000 force-pushed the ff/disable-note-moving-for-others-while-dragging-#2891 branch from e12cb40 to 02c1af4 Compare November 10, 2025 10:43
Prevent multiple users from simultaneously dragging the same card by implementing
a real-time locking system with visual feedback.

- Add NOTE_DRAG_START and NOTE_DRAG_END WebSocket events
- Create dragLocks Redux slice for state management
- Add API endpoints for broadcasting drag events
- Implement visual indicators showing which user is dragging
- Display user avatar and name on locked cards
- Disable drag interactions on locked cards
- Add proper styling with DragLockIndicator.scss

This prevents conflicting drag operations and provides clear visual feedback
about who is currently moving each card.
Extract remaining inline styles from Sortable.tsx to Sortable.scss for better
maintainability and separation of concerns. All styling is now properly
organized in CSS files with BEM methodology.
Revert shouldCombine class name to maintain compatibility with existing
Note.scss styling that depends on .shouldCombine selector for visual
feedback during note stacking operations.
Remove console.log and console.warn statements from drag lock
implementation to resolve ESLint warnings while maintaining
silent error handling for better user experience.
- Implement in-memory drag lock management with automatic cleanup
- Add configurable timeout and cleanup intervals with sensible defaults
- Support concurrent access with RWMutex for thread safety
- Include background cleanup goroutine for expired locks
- Provide dependency injection interface for testability
- Create drag_locks table with note_id as primary key
- Add foreign key constraints to notes, users, and boards
- Include indexes for performance optimization
- Support atomic lock operations across multiple pods
- Add PostgreSQL-based drag lock management with raw SQL
- Support atomic lock acquisition using INSERT ON CONFLICT
- Include automatic cleanup of expired locks (30 seconds)
- Broadcast lock events via NATS for multi-pod coordination
- Follow established patterns from reactions service
- Remove in-memory implementation from service.go
- Keep only interface and factory function
- Configure main.go to use database service
- Enable multi-pod drag lock coordination
- Replace separate drag-start/drag-end endpoints with unified drag-state
- Implement lock acquisition with HTTP 409 conflict responses
- Integrate with drag lock service for coordination
- Broadcast realtime events for drag state changes
- Add updateNoteDragState API method with boolean drag state
- Update Redux thunks to use new unified endpoint
- Maintain backward compatibility with existing drag thunks
- Prepare for enhanced error handling and conflict detection
- Remove created_at index as table will have minimal rows (~50-100)
- Keep board_id index for GetLocksForBoard queries
- Reduce index maintenance overhead for short-lived locks
- Add drag_locks table to track note dragging state
- Include foreign key constraints for data integrity
- Add proper indexes for performance optimization
- Add WebSocket message handling for drag lock operations
- Implement acquire and release lock functionality
- Add automatic lock cleanup on user disconnect
- Include comprehensive test coverage for database operations
ffischbach-ino and others added 24 commits December 1, 2025 13:04
- Add missing context parameter to BroadcastToBoard calls in drag locks
- Add handleWebSocketMessage function to route drag lock WebSocket messages
- Integrate drag lock message handling in board WebSocket connection
- Release user drag locks when WebSocket connection closes
- Update mock Publish method to expect 3 parameters instead of 2
- Fixes test failures due to updated realtime broker interface
- Affects database service and websocket handler test suites
- Add nil dragLocks parameter to New() function call in board templates test
- Fixes test compilation error due to updated router signature
- Required for API integration tests to pass
Update sendWebSocketMessage parameter type from 'any' to 'string' to improve type safety and align with WebSocket API expectations.
Add DragLockMessage interface and ClientMessage union type to support
type-safe client-to-server WebSocket messaging for drag lock operations.
Update sendWebSocketMessage function to accept ClientMessage type
instead of generic string parameter, ensuring type safety for
WebSocket client messages.
- Add DragOverlay.scss for subtle column color tinting of dragged notes
- Update CustomDndContext to pass colorClassName to dragged note
- Apply background color and border styling based on original column
- Include dark theme support with appropriate color variants
- Move indicator to bottom-right outside the note (-12px positioning)
- Increase z-index for better visibility
- Simplify styles by removing custom pill styling
- Add enhanced shadow for prominence in both light and dark themes
- Replace custom drag indicator with note-author__container--self styling
- Import and reuse NoteAuthorList.scss for consistent design
- Switch from Avatar to UserAvatar component for proper prop support
- Maintain semantic structure with figure and aria attributes
- Apply column color theming through existing CSS variables
- Rename shadowed variable 'note' to 'targetNote'
- Replace unsafe non-null assertion with safe fallback for user ID
- Create dedicated DragIndicatorPill component for drag indicators
- Replace complex inline note-author structure in Sortable component
- Simplify DragLockIndicator.scss to only handle positioning
- Add proper TypeScript types with AvataaarProps
- Enable automatic column color theming through CSS variables
- Improve code maintainability and component reusability
- Import AvataaarProps from 'types/avatar' instead of 'avataaars'
- Align with codebase conventions used in other components
- Add flexbox centering properties to avatar container
- Ensure avatar is perfectly centered horizontally and vertically
- Improve visual alignment of user avatars in drag indicators
- Change avatar dimensions from spacing-md to icon-medium
- Use semantic icon sizing constants for better consistency
- Maintain visual proportions while following design system conventions
- Add 'isMovingThis' translation key for English and German
- Prepare translation infrastructure for drag indicator messages
- Translation values need completion in follow-up
- Reduce opacity of locked notes from 0.7 to 0.4
- Make it more obvious when notes are being dragged by other users
- Enhance user experience by clearly indicating non-interactive state
@Planlos5000 Planlos5000 force-pushed the ff/disable-note-moving-for-others-while-dragging-#2891 branch from 02c1af4 to e42bb46 Compare December 2, 2025 14:04
@Planlos5000 Planlos5000 force-pushed the ff/disable-note-moving-for-others-while-dragging-#2891 branch from e42bb46 to 5e48481 Compare December 3, 2025 08:55
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

The deployment to the dev cluster was successful. You can find the deployment here: https://5410.development.scrumlr.fra.ics.inovex.io
This deployment is only for testing purposes and will be deleted after 1 week.
To redeploy rerun the workflow.
DO NOT STORE IMPORTANT DATA ON THIS DEPLOYMENT

Deployed Images
  • ghcr.io/inovex/scrumlr.io/scrumlr-frontend:sha-85394cb

  • ghcr.io/inovex/scrumlr.io/scrumlr-server:sha-85394cb

@Planlos5000 Planlos5000 added the feat This pull request or issue adds a new feature label Dec 3, 2025
@Planlos5000 Planlos5000 linked an issue Dec 3, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat This pull request or issue adds a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hidden note while moving

4 participants