-
Notifications
You must be signed in to change notification settings - Fork 17
Description
Description
| Type | Size (weeks) |
|---|---|
| Feature | Scope 1: 6 Scope 2: 3 Scope 3: 1 |
Meta issue: #551
This feature should allow user to manually re-order the trainruns inside a node, by manually allocating the ports of the trainrun sections. This will be allowed on Node Edition, user will be able to drag a trainrun section's port to another port slot. Then, the algorithm that already automatically assign ports should take these manual settings into account.
Such train's configuration at a node should be doable (see more examples from SNCF Réseau here)

(Currently hacking with labeled trainruns:)
Mock-ups
Homemade mock-up for an "edited node's view":
empty/assignedports (grey spot)- handles (red spots)
- size of the node adapted to new number of ports
A full empty node should be able to host these empty ports (= minimal size):

Acceptance Criteria
Scope 1 (Port swapping):
- On Node Edition mode (when a node is currently being edited (= double-clicked (Node details are opened on the right side)):
- All the ports of the node are displayed:
- Assigned ones
- Empty ones (not assigned, all the possible ports that the size of the node allows)
- Especially for edges with no trainruns on them, display the empty ports
- Each Port, assigned or not, takes the same space and defines a "row" (or "column") (already current behavior)
- The minimal size of an edge is all the ports (assigned or empty) contained within the first and last assigned ports of the edge (included)
- Ports look different (three visual states):
-
empty: the port is not already assigned -
assigned: the port is already assigned -
receiving(highlighted): the port is not already assigned, but the user is currently dragging a train on this Port -> "preview state"
-
- User can grab an assigned port to drag it to another port location:
- Snapping:
- If inside of the node's edges, then snap to the closest port, including the dragged port (euclidean distance for snapping range can be decided during the implementation)
- Note: If dragging and stopping above the origin, this should be dealt like the other cases: if the cursor is in a snap range ('say the origin), the drag should end up in associated port
- If outside of the node's edges, then cancel the operation to prevent premature cancels (euclidean distance for snapping range can be decided during the implementation)
- If inside of the node's edges, then snap to the closest port, including the dragged port (euclidean distance for snapping range can be decided during the implementation)
- The "receiving" port becomes highlighted when user drags a port onto it without releasing the click
- Dragging a port (=
Port1) of a train (=Train1) to another port (=Port2) location makes its locationlockedto this one- If
Port2was empty,Port1takes the location ofPort2 - If
Port2was already assigned by a train (=Train2)- and
Port2was notlockedforTrain2,Port1takes the location ofPort2andPort2is re-calculated forTrain2(onlyTrain1has alockedPort) - and
Port2waslockedforTrain2,Port1takes the location ofPort2andPort2takes the location ofPort1(bothTrain1andTrain2havelockedPorts, but swapped)
- and
- Note: if
Port1is dragged while snapped at the same position,Port1stays at the same location and becomeslocked
- If
- Snapping:
- A
lockedPort and a notlockedPort look the same (no need for differentiation)
- All the ports of the node are displayed:
- Setting a port a specific location should emit an
Operation - Automated port allocation algorithms still work on the rest of the "not
locked" Ports - To reset all the specific Port allocations made by the user, a button is available in the Node Edition menu. By clicking on it, the user specifications are deleted and the Ports are recalculated by the automatic algorithm. (TODO: need mock-up ; edit: sorry no mock-up yet)
Scope 2: (Node resizing):
- On Node Edition mode, user can grab an edge of the node to resize it
- On hover of an edge, the mouse cursor becomes a bi-directional arrow and the edge is highlighted
- When user drags an edge of a node and drags it on the external direction, the node grows on that direction, adding empty ports for the grown sides (= new behavior than Scope 1)
- This action snaps on the closest previous / next port "row" (or "column")
- If user tries to resize on the internal direction of the node, further that the minimal size of the node, the resize is stuck to the minimal size
- When user stops dragging and releases its click, the node keeps the given size, and the new empty ports are kept (= new behavior than Scope 1)
- When user leaves the Node Edition mode, the Node goes back to its minimal size (= removing the empty Ports before the first assigned Port and after the last assigned port)
Scope 3 (Moving ports using arrow keys)
- Nice-to-have: arrow up/down or left/right feature on a port selection
- In Node Edition mode, user can select a port
- When a port is selected, user can move this port to neighbor port positions
- If the port is on the left or right side, pressing Arrow Up makes it go on the above position, pressing Arrow Down makes it go on the below position
- If Port is on the top or bottom side, pressing Arrow Left makes it go on the left position, pressing Arrow Right makes it go on the right position
- After being moved, the port becomes
locked- Note: and not the other neighbor ports that are swapped by this one
- Selection is kept after pressing any key; selection is discarded after pressing Escape key
Implementation Plan
Enhancement (can be done at any time, but rather in a separated PR):
- Refacto
enum PositionAlignmentand use astringvalue instead ofintenum value- We want something like
TOP = "top", not totally remove the enum
- We want something like
Scope 1 (size 6):
- Update the node size calculation method to take the port index value instead of the ports number
- Note (not sure of what the current implementation is): If
port.getPositionIndex()is already used, this might be already done actually. On the other hand,this.port.lengthis not the good solution imo to get the size (this would end up dealing with 5 ports, even if we have 5 ports and others in between (which are not "existing"). We don't want to have ports withport.getTrainrunSectionId() === undefined, we only want proper ports.
- Note (not sure of what the current implementation is): If
- Node Edition:
- Display all ports
-
assigned -
empty- Especially for empty edges (see above "minimal size" node picture)
-
receiving(only a visual state)
-
- Implement drag operation from a port to another port: update the dragged port
lockedvalue- Update the
Port1,lockedto true,positionIndexandpositionAlignmentattributes - Update the
Port2lockedtofalse(only on swap with an assigned port)
- Update the
- Add the possibility to reset the
lockedattributes of all ports of a node
- Display all ports
- Create new event emitter class
PortOperation(here)- Add
operation.emit()when ports getlocked(or resettinglocked)
- Add
Scope 2 (size 3):
- Allow a node to have a size that is not bounded by first and last assigned ports, but also by empty ports
- Node's edge drag (highlighted edge)
- Resize the node
- Snapping to the previous/next port "row" (or "column")
- On Node Edition closed, resize the node the be bounded back by first and last assigned ports
Scope 3 (size ?):
- Allow to select a port in Node Edition mode
- Implement port move to previous/next right/top/left/bottom index
- Discard port selection when Node Edition mode is closed or on pressing "Escape" key
Tests
Definition of Ready
-
PO/UX-UI
- Mock-ups are complete and validated
- ACs are clear and have been reviewed by another refiner
-
Technical
- Implementation plan has been written and validated by another maintainer
-
General
- Validated by Adrian

