mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Merge branch 'develop' into feature/key-value-field
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"/js/filament.js": "/js/filament.js?id=f6f25b9e29038b97ab02",
|
||||
"/css/filament.css": "/css/filament.css?id=99d2776c1ace0e75b0a2"
|
||||
"/css/filament.css": "/css/filament.css?id=6355038f8cb08d58efef"
|
||||
}
|
||||
|
||||
@@ -102,10 +102,10 @@ class Field extends Component
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function disabled()
|
||||
public function disabled($disabled = true)
|
||||
{
|
||||
$this->configure(function () {
|
||||
$this->disabled = true;
|
||||
$this->configure(function () use ($disabled) {
|
||||
$this->isDisabled = $disabled;
|
||||
});
|
||||
|
||||
return $this;
|
||||
@@ -114,7 +114,7 @@ class Field extends Component
|
||||
public function enabled()
|
||||
{
|
||||
$this->configure(function () {
|
||||
$this->disabled = false;
|
||||
$this->isDisabled = false;
|
||||
});
|
||||
|
||||
return $this;
|
||||
|
||||
@@ -29,9 +29,7 @@ class Tabs extends Component
|
||||
|
||||
public function tabs($tabs)
|
||||
{
|
||||
$this->configure(function () use ($tabs) {
|
||||
$this->schema($tabs);
|
||||
});
|
||||
$this->schema($tabs);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
@if ($action = $recordAction->getAction($record))
|
||||
<button
|
||||
wire:click="{{ $action }}('{{ $record->getKey() }}')"
|
||||
type="button"
|
||||
class="font-medium transition-colors duration-200 text-primary-600 hover:text-primary-700"
|
||||
>
|
||||
<x-dynamic-component :component="$recordAction->getIcon()" class="w-4 h-4" />
|
||||
</button>
|
||||
@elseif ($url = $recordAction->getUrl($record))
|
||||
<a
|
||||
href="{{ $url }}"
|
||||
class="font-medium transition-colors duration-200 text-primary-600 hover:text-primary-700"
|
||||
@if ($recordAction->shouldOpenUrlInNewTab())
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@endif
|
||||
>
|
||||
<x-dynamic-component :component="$recordAction->getIcon()" class="w-4 h-4" />
|
||||
</a>
|
||||
@else
|
||||
<span
|
||||
class="inline-flex items-center font-medium text-primary-600"
|
||||
>
|
||||
<x-dynamic-component :component="$recordAction->getIcon()" class="w-4 h-4" />
|
||||
</span>
|
||||
@endif
|
||||
@@ -2,21 +2,37 @@
|
||||
<button
|
||||
wire:click="{{ $action }}('{{ $record->getKey() }}')"
|
||||
type="button"
|
||||
class="font-medium transition-colors duration-200 text-primary-600 hover:underline hover:text-primary-700"
|
||||
class="inline-flex items-center font-medium transition-colors duration-200 text-primary-600 hover:underline hover:text-primary-700"
|
||||
>
|
||||
@if ($recordAction->hasIcon())
|
||||
<x-dynamic-component :component="$recordAction->getIcon()" class="w-4 h-4 mr-1" />
|
||||
@endif
|
||||
|
||||
{{ __($recordAction->getLabel()) }}
|
||||
</button>
|
||||
@elseif ($url = $recordAction->getUrl($record))
|
||||
<a
|
||||
href="{{ $url }}"
|
||||
class="font-medium transition-colors duration-200 text-primary-600 hover:underline hover:text-primary-700"
|
||||
class="inline-flex items-center font-medium transition-colors duration-200 text-primary-600 hover:underline hover:text-primary-700"
|
||||
@if ($recordAction->shouldOpenUrlInNewTab())
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@endif
|
||||
>
|
||||
@if ($recordAction->hasIcon())
|
||||
<x-dynamic-component :component="$recordAction->getIcon()" class="w-4 h-4 mr-1" />
|
||||
@endif
|
||||
|
||||
{{ __($recordAction->getLabel()) }}
|
||||
</a>
|
||||
@else
|
||||
<span>{{ __($recordAction->getLabel()) }}</span>
|
||||
<span
|
||||
class="inline-flex items-center font-medium text-primary-600"
|
||||
>
|
||||
@if ($recordAction->hasIcon())
|
||||
<x-dynamic-component :component="$recordAction->getIcon()" class="w-4 h-4 mr-1" />
|
||||
@endif
|
||||
|
||||
{{ __($recordAction->getLabel()) }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
@@ -56,18 +56,6 @@ class Action
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
if ($this->label === null) {
|
||||
return (string) Str::of($this->getName())
|
||||
->kebab()
|
||||
->replace(['-', '_', '.'], ' ')
|
||||
->ucfirst();
|
||||
}
|
||||
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Tables\RecordActions;
|
||||
|
||||
class Icon extends Action
|
||||
{
|
||||
use Concerns\CanCallAction;
|
||||
use Concerns\CanOpenUrl;
|
||||
|
||||
protected $icon;
|
||||
|
||||
public function icon($icon)
|
||||
{
|
||||
$this->configure(function () use ($icon) {
|
||||
$this->icon = $icon;
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIcon()
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
}
|
||||
@@ -11,24 +11,45 @@ class Link extends Action
|
||||
|
||||
protected $label;
|
||||
|
||||
protected $icon;
|
||||
|
||||
public function label($label)
|
||||
{
|
||||
$this->label = $label;
|
||||
$this->configure(function () use ($label) {
|
||||
$this->label = $label;
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function name($name)
|
||||
public function icon($icon)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->configure(function () use ($icon) {
|
||||
$this->icon = $icon;
|
||||
});
|
||||
|
||||
$this->label(
|
||||
(string) Str::of($this->name)
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
if ($this->label === null) {
|
||||
return (string) Str::of($this->getName())
|
||||
->kebab()
|
||||
->replace(['-', '_', '.'], ' ')
|
||||
->ucfirst(),
|
||||
);
|
||||
->ucfirst();
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function getIcon()
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function hasIcon()
|
||||
{
|
||||
return $this->icon !== null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,86 +6,132 @@ use Illuminate\Support\Str;
|
||||
|
||||
class BelongsToSelect extends Select
|
||||
{
|
||||
public $getOptions;
|
||||
protected $getOptions;
|
||||
|
||||
public $view = 'forms::components.select';
|
||||
protected $displayColumnName;
|
||||
|
||||
protected $relationship;
|
||||
|
||||
protected $view = 'forms::components.select';
|
||||
|
||||
public function getDisplayColumnName()
|
||||
{
|
||||
return $this->displayColumnName;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
if ($this->label === null) {
|
||||
return (string) Str::of($this->getRelationshipName())
|
||||
->before('.')
|
||||
->kebab()
|
||||
->replace(['-', '_'], ' ')
|
||||
->ucfirst();
|
||||
}
|
||||
|
||||
return parent::getLabel();
|
||||
}
|
||||
|
||||
public function getOptions()
|
||||
{
|
||||
if ($callback = $this->getOptions) {
|
||||
return $callback();
|
||||
}
|
||||
|
||||
return parent::getOptions();
|
||||
}
|
||||
|
||||
public function getOptionsUsing($callback)
|
||||
{
|
||||
$this->getOptions = $callback;
|
||||
$this->configure(function () use ($callback) {
|
||||
$this->getOptions = $callback;
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRelationship()
|
||||
{
|
||||
$model = $this->getModel();
|
||||
|
||||
return (new $model())->{$this->getRelationshipName()}();
|
||||
}
|
||||
|
||||
public function getRelationshipName()
|
||||
{
|
||||
return $this->relationship;
|
||||
}
|
||||
|
||||
public function preload()
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
$this->configure(function () {
|
||||
$options = $this->getOptions();
|
||||
|
||||
if (! $options || ! $this->getModel()) return;
|
||||
if (! $options || ! $this->getModel()) return;
|
||||
|
||||
$this->options = $options;
|
||||
$this->options = $options;
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function relationship($relationshipName, $displayColumnName, $callback = null)
|
||||
{
|
||||
$this->getDisplayValueUsing(function ($value) use ($displayColumnName, $relationshipName) {
|
||||
$model = $this->getModel();
|
||||
$this->configure(function () use ($callback, $displayColumnName, $relationshipName) {
|
||||
$this->displayColumnName = $displayColumnName;
|
||||
$this->relationship = $relationshipName;
|
||||
|
||||
$relationship = (new $model())->{$relationshipName}();
|
||||
$this->getDisplayValueUsing(function ($value) {
|
||||
$relationship = $this->getRelationship();
|
||||
|
||||
$record = $relationship->getRelated()->where($relationship->getOwnerKeyName(), $value)->first();
|
||||
$record = $relationship->getRelated()->where($relationship->getOwnerKeyName(), $value)->first();
|
||||
|
||||
return $record ? $record->getAttributeValue($displayColumnName) : null;
|
||||
});
|
||||
return $record ? $record->getAttributeValue($this->getDisplayColumnName()) : null;
|
||||
});
|
||||
|
||||
$this->getOptionSearchResultsUsing(function ($search) use ($callback, $displayColumnName, $relationshipName) {
|
||||
$model = $this->getModel();
|
||||
$this->getOptionSearchResultsUsing(function ($search) use ($callback) {
|
||||
$relationship = $this->getRelationship();
|
||||
|
||||
$relationship = (new $model())->{$relationshipName}();
|
||||
$query = $relationship->getRelated();
|
||||
|
||||
$query = $relationship->getRelated();
|
||||
if ($callback) {
|
||||
$query = $callback($query);
|
||||
}
|
||||
|
||||
if ($callback) {
|
||||
$query = $callback($query);
|
||||
$search = Str::lower($search);
|
||||
$searchOperator = [
|
||||
'pgsql' => 'ilike',
|
||||
][$query->getConnection()->getDriverName()] ?? 'like';
|
||||
|
||||
return $query
|
||||
->where($this->getDisplayColumnName(), $searchOperator, "%{$search}%")
|
||||
->pluck($this->getDisplayColumnName(), $relationship->getOwnerKeyName())
|
||||
->toArray();
|
||||
});
|
||||
|
||||
$this->getOptionsUsing(function () use ($callback) {
|
||||
$relationship = $this->getRelationship();
|
||||
|
||||
$query = $relationship->getRelated();
|
||||
|
||||
if ($callback) {
|
||||
$query = $callback($query);
|
||||
}
|
||||
|
||||
return $query
|
||||
->pluck($this->getDisplayColumnName(), $relationship->getOwnerKeyName())
|
||||
->toArray();
|
||||
});
|
||||
|
||||
if ($model = $this->getModel()) {
|
||||
$relationship = $this->getRelationship();
|
||||
|
||||
$relatedModelClass = get_class($relationship->getModel());
|
||||
|
||||
$this->addRules([$this->getName() => "exists:{$relatedModelClass},{$relationship->getOwnerKeyName()}"]);
|
||||
}
|
||||
|
||||
$search = Str::lower($search);
|
||||
$searchOperator = [
|
||||
'pgsql' => 'ilike',
|
||||
][$query->getConnection()->getDriverName()] ?? 'like';
|
||||
|
||||
return $query
|
||||
->where($displayColumnName, $searchOperator, "%{$search}%")
|
||||
->pluck($displayColumnName, $relationship->getOwnerKeyName())
|
||||
->toArray();
|
||||
});
|
||||
|
||||
$this->getOptionsUsing(function () use ($callback, $displayColumnName, $relationshipName) {
|
||||
$model = $this->getModel();
|
||||
|
||||
$relationship = (new $model())->{$relationshipName}();
|
||||
|
||||
$query = $relationship->getRelated();
|
||||
|
||||
if ($callback) {
|
||||
$query = $callback($query);
|
||||
}
|
||||
|
||||
return $query
|
||||
->pluck($displayColumnName, $relationship->getOwnerKeyName())
|
||||
->toArray();
|
||||
});
|
||||
|
||||
$this->label(
|
||||
(string) Str::of($relationshipName)
|
||||
->before('.')
|
||||
->kebab()
|
||||
->replace(['-', '_'], ' ')
|
||||
->ucfirst(),
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ class ListRecords extends Page
|
||||
->filter(function ($record) {
|
||||
return Filament::can('delete', $record);
|
||||
})
|
||||
->map(fn ($record) => $record->getKey())
|
||||
->toArray(),
|
||||
);
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ class RelationManager extends Component
|
||||
->filter(function ($record) {
|
||||
return Filament::can('delete', $record);
|
||||
})
|
||||
->map(fn ($record) => $record->getKey())
|
||||
->toArray(),
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Resources\Tables\RecordActions;
|
||||
|
||||
class Icon extends \Filament\Tables\RecordActions\Icon
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Filament;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use League\Glide\Urls\UrlBuilderFactory;
|
||||
|
||||
if (! function_exists('Filament\format_attributes')) {
|
||||
@@ -57,3 +58,14 @@ if (! function_exists('Filament\get_image_url')) {
|
||||
return route('filament.image', ['path' => ltrim($urlBuilder->getUrl($path, $manipulations), '/')]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('Filament\get_media_contents')) {
|
||||
function get_media_contents($path)
|
||||
{
|
||||
$disk = Storage::disk(config('filament.default_filesystem_disk'));
|
||||
|
||||
if (! $disk->exists($path)) return;
|
||||
|
||||
return $disk->get($path);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user