Skip to content

Commit 8dfaf4e

Browse files
committed
fix: only treat an explicitly configured url as a card link
getUrl() falls back to the livewire component's getDefaultActionUrl(), which Filament's resource pages implement for modal-less Create/Edit/View actions. BoardResourcePage extends that class, so honouring the fallback would have turned existing boards into links without the developer asking for it. Gate on hasUrl() so only an explicit ->url() opts a card into link rendering.
1 parent 41fb1bc commit 8dfaf4e

5 files changed

Lines changed: 46 additions & 2 deletions

File tree

resources/views/livewire/card.blade.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,17 @@
99
1010
// A card action configured with ->url() must navigate like a native link instead
1111
// of mounting a modal, so middle-click, cmd-click and "copy link" keep working.
12-
// getUrl() returns null when the action has a modal, and POST urls need a form
12+
//
13+
// Only an explicitly configured url opts a card into link rendering. getUrl()
14+
// also falls back to the livewire component's getDefaultActionUrl(), which
15+
// Filament's resource pages implement for modal-less Create/Edit/View actions;
16+
// honouring that here would silently turn existing boards into links. getUrl()
17+
// still returns null when the action has a modal, and POST urls need a form
1318
// rather than an anchor, so both fall through to the Livewire click handler.
1419
$cardActionInstance = $this->getBoard()->resolveCardAction($processedRecordActions);
15-
$cardActionUrl = $cardActionInstance?->shouldPostToUrl() ? null : $cardActionInstance?->getUrl();
20+
$cardActionUrl = ($cardActionInstance?->hasUrl() && ! $cardActionInstance->shouldPostToUrl())
21+
? $cardActionInstance->getUrl()
22+
: null;
1623
$hasCardActionUrl = filled($cardActionUrl);
1724
$cardActionHref = $hasCardActionUrl
1825
? \Filament\Support\generate_href_html(

tests/Feature/CardActionUrlTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Relaticle\Flowforge\Tests\Fixtures\Task;
77
use Relaticle\Flowforge\Tests\Fixtures\TestBoard;
88
use Relaticle\Flowforge\Tests\Fixtures\TestCardActionBoard;
9+
use Relaticle\Flowforge\Tests\Fixtures\TestCardActionDefaultUrlBoard;
910
use Relaticle\Flowforge\Tests\Fixtures\TestCardActionModalBoard;
1011
use Relaticle\Flowforge\Tests\Fixtures\TestCardActionNewTabBoard;
1112

@@ -60,6 +61,13 @@ function cardTitleHtml(string $html): string
6061
->and($title)->not->toContain('href=');
6162
});
6263

64+
test('card action inheriting only a default action url still mounts the action', function () {
65+
$title = cardTitleHtml(Livewire::test(TestCardActionDefaultUrlBoard::class)->html());
66+
67+
expect($title)->toContain("mountAction('run'")
68+
->and($title)->not->toContain('href=');
69+
});
70+
6371
test('resolveCardAction finds the configured action among record actions', function () {
6472
$board = Livewire::test(TestCardActionBoard::class)->instance()->getBoard();
6573

tests/Fixtures/TestCardActionBoard.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public function board(Board $board): Board
3838
TextInput::make('title'),
3939
])
4040
->action(function (): void {}),
41+
Action::make('run')
42+
->action(function (): void {}),
4143
])
4244
->cardAction($this->cardActionName());
4345
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Relaticle\Flowforge\Tests\Fixtures;
6+
7+
use Filament\Actions\Action;
8+
9+
/**
10+
* A card action with no ->url() of its own, on a page whose getDefaultActionUrl()
11+
* returns a url. Filament's resource pages do exactly this for modal-less
12+
* Create/Edit/View actions, so the card must keep mounting the action rather than
13+
* silently becoming a link.
14+
*/
15+
class TestCardActionDefaultUrlBoard extends TestCardActionBoard
16+
{
17+
public function getDefaultActionUrl(Action $action): ?string
18+
{
19+
return 'https://example.test/default-action-url';
20+
}
21+
22+
protected function cardActionName(): string
23+
{
24+
return 'run';
25+
}
26+
}

tests/Fixtures/TestPanelProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function panel(Panel $panel): Panel
2929
->pages([
3030
TestBoard::class,
3131
TestCardActionBoard::class,
32+
TestCardActionDefaultUrlBoard::class,
3233
TestCardActionModalBoard::class,
3334
TestCardActionNewTabBoard::class,
3435
])

0 commit comments

Comments
 (0)