Skip to content

Commit f8b97a3

Browse files
committed
refactor: improve so moving logic
1 parent e8e74cb commit f8b97a3

6 files changed

Lines changed: 77 additions & 4 deletions

File tree

features/admin/page/sorting_content_elements_on_page.feature

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,19 @@ Feature: Sorting content elements on a page
5151
And I add a heading content element with type "h1" and "My Title" content
5252
And I add a textarea content element with "My body text" content
5353
Then the move down button of the 2nd content element should be disabled
54+
55+
@ui @javascript
56+
Scenario: Moving a content element down keeps its content when editing an existing page
57+
Given there is a page in the store with a textarea content element with "First content" content and a textarea content element with "Second content" content
58+
When I want to edit this page
59+
And I move the 1st content element down
60+
Then the 1st content element should contain "Second content"
61+
And the 2nd content element should contain "First content"
62+
63+
@ui @javascript
64+
Scenario: Moving a content element up keeps its content when editing an existing page
65+
Given there is a page in the store with a textarea content element with "First content" content and a textarea content element with "Second content" content
66+
When I want to edit this page
67+
And I move the 2nd content element up
68+
Then the 1st content element should contain "Second content"
69+
And the 2nd content element should contain "First content"

src/Twig/Component/Trait/ContentElementsCollectionFormComponentTrait.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,21 @@ public function moveCollectionItem(
7070
return;
7171
}
7272

73-
$swapKey = $keys[$swapPos];
74-
[$data[$index], $data[$swapKey]] = [$data[$swapKey], $data[$index]];
73+
$items = array_values($data);
74+
[$items[$currentPos], $items[$swapPos]] = [$items[$swapPos], $items[$currentPos]];
75+
76+
// Re-key the whole collection with fresh, monotonically increasing indices so the
77+
// moved rows are rendered with new DOM ids. This forces the Live Component to
78+
// re-create them instead of patching them in place, which is required because
79+
// stateful widgets (e.g. the WYSIWYG editor) opt out of morphing via
80+
// "data-live-ignore" and would otherwise keep their stale content after a move.
81+
$nextIndex = $this->provideNewCollectionItemIndex($data);
82+
$reordered = [];
83+
foreach ($items as $item) {
84+
$reordered[$nextIndex++] = $item;
85+
}
7586

76-
$propertyAccessor->setValue($this->formValues, $propertyPath, $data);
87+
$propertyAccessor->setValue($this->formValues, $propertyPath, $reordered);
7788
}
7889

7990
#[LiveAction]

tests/Behat/Context/Setup/PageContext.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,27 @@ public function thereIsAPageInTheStoreWithContentElements(string $contentElement
7878
$this->savePage($page);
7979
}
8080

81+
/**
82+
* @Given there is a page in the store with a textarea content element with :firstContent content and a textarea content element with :secondContent content
83+
*/
84+
public function thereIsAPageInTheStoreWithTwoTextareaContentElements(string $firstContent, string $secondContent): void
85+
{
86+
$page = $this->createPage();
87+
88+
foreach ([$firstContent, $secondContent] as $content) {
89+
/** @var ContentConfigurationInterface $contentConfiguration */
90+
$contentConfiguration = new ContentConfiguration();
91+
$contentConfiguration->setType('textarea');
92+
$contentConfiguration->setLocale('en_US');
93+
$contentConfiguration->setConfiguration(['textarea' => $content]);
94+
$contentConfiguration->setPage($page);
95+
96+
$page->addContentElement($contentConfiguration);
97+
}
98+
99+
$this->savePage($page);
100+
}
101+
81102
/**
82103
* @Given there is an existing page with :name name
83104
*/

tests/Behat/Context/Ui/Admin/ContentCollectionContext.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,17 @@ public function theContentElementAtPositionShouldBeOfType(string $ordinal, strin
217217
);
218218
}
219219

220+
/**
221+
* @Then the :ordinal content element should contain :content
222+
*/
223+
public function theContentElementAtPositionShouldContain(string $ordinal, string $content): void
224+
{
225+
Assert::contains(
226+
$this->contentElementsCollectionElement->getContentElementContentAtPosition($this->parseOrdinal($ordinal)),
227+
$content,
228+
);
229+
}
230+
220231
/**
221232
* @Then the move up button of the :ordinal content element should be disabled
222233
*/

tests/Behat/Element/Admin/ContentElementsCollectionElement.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,18 @@ public function getContentElementTypeAtPosition(int $position): string
174174
return $selectedOption->getText();
175175
}
176176

177+
public function getContentElementContentAtPosition(int $position): string
178+
{
179+
$elements = $this->getContentElements();
180+
Assert::keyExists($elements, $position - 1, sprintf('No content element at position %d.', $position));
181+
182+
// Read the visible WYSIWYG editor content instead of the (morphed) hidden input,
183+
// so the assertion reflects what the user actually sees after a move.
184+
$editor = $elements[$position - 1]->find('css', 'trix-editor');
185+
186+
return $editor instanceof NodeElement ? $editor->getText() : $elements[$position - 1]->getText();
187+
}
188+
177189
public function insertContentElementAfterPosition(string $type, int $afterPosition): void
178190
{
179191
$this->insertContentElementAtDividerIndex($type, $afterPosition);
@@ -223,7 +235,7 @@ private function getSortButton(int $position, string $direction): NodeElement
223235
$elements = $this->getContentElements();
224236
Assert::keyExists($elements, $position - 1, sprintf('No content element at position %d.', $position));
225237

226-
$button = $elements[$position - 1]->find('css', sprintf('[data-sort-direction="%s"]', $direction));
238+
$button = $elements[$position - 1]->find('css', sprintf('[data-live-direction-param="%s"]', $direction));
227239
Assert::notNull($button, sprintf('Sort %s button not found at position %d.', $direction, $position));
228240

229241
return $button;

tests/Behat/Element/Admin/ContentElementsCollectionElementInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public function moveContentElementDown(int $position): void;
4444

4545
public function getContentElementTypeAtPosition(int $position): string;
4646

47+
public function getContentElementContentAtPosition(int $position): string;
48+
4749
public function isContentElementMoveUpButtonDisabled(int $position): bool;
4850

4951
public function isContentElementMoveDownButtonDisabled(int $position): bool;

0 commit comments

Comments
 (0)