|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace Relaticle\Flowforge; |
| 4 | + |
| 5 | +use Exception; |
| 6 | +use Filament\Actions\Action; |
| 7 | +use Filament\Support\Components\ViewComponent; |
| 8 | +use Filament\Support\Concerns\CanAggregateRelatedModels; |
| 9 | +use Filament\Support\Concerns\CanGrow; |
| 10 | +use Filament\Support\Concerns\CanSpanColumns; |
| 11 | +use Filament\Support\Concerns\CanWrapHeader; |
| 12 | +use Filament\Support\Concerns\HasAlignment; |
| 13 | +use Filament\Support\Concerns\HasCellState; |
| 14 | +use Filament\Support\Concerns\HasExtraAttributes; |
| 15 | +use Filament\Support\Concerns\HasPlaceholder; |
| 16 | +use Filament\Support\Concerns\HasVerticalAlignment; |
| 17 | +use Filament\Support\Concerns\HasWidth; |
| 18 | +use Filament\Support\Enums\Alignment; |
| 19 | +use Filament\Tables\Table; |
| 20 | +use Illuminate\Database\Eloquent\Model; |
| 21 | +use Illuminate\Support\HtmlString; |
| 22 | +use Illuminate\View\ComponentAttributeBag; |
| 23 | + |
| 24 | +use function Filament\Support\generate_href_html; |
| 25 | + |
| 26 | +class Column extends ViewComponent |
| 27 | +{ |
| 28 | + use CanAggregateRelatedModels; |
| 29 | + use CanGrow; |
| 30 | + use CanSpanColumns; |
| 31 | + use CanWrapHeader; |
| 32 | + use HasAlignment; |
| 33 | + use HasCellState; |
| 34 | + use HasExtraAttributes; |
| 35 | + use HasPlaceholder; |
| 36 | + use HasVerticalAlignment; |
| 37 | + use HasWidth; |
| 38 | + |
| 39 | + protected string $evaluationIdentifier = 'column'; |
| 40 | + |
| 41 | + protected string $viewIdentifier = 'column'; |
| 42 | + |
| 43 | + final public function __construct(string $name) |
| 44 | + { |
| 45 | + $this->name($name); |
| 46 | + } |
| 47 | + |
| 48 | + public static function make(?string $name = null): static |
| 49 | + { |
| 50 | + $columnClass = static::class; |
| 51 | + |
| 52 | + $name ??= static::getDefaultName(); |
| 53 | + |
| 54 | + if (blank($name)) { |
| 55 | + throw new Exception("Column of class [$columnClass] must have a unique name, passed to the [make()] method."); |
| 56 | + } |
| 57 | + |
| 58 | + $static = app($columnClass, ['name' => $name]); |
| 59 | + $static->configure(); |
| 60 | + |
| 61 | + return $static; |
| 62 | + } |
| 63 | + |
| 64 | + public static function getDefaultName(): ?string |
| 65 | + { |
| 66 | + return null; |
| 67 | + } |
| 68 | + |
| 69 | + public function getTable(): Table |
| 70 | + { |
| 71 | + return $this->table ?? $this->getGroup()?->getTable() ?? $this->getLayout()?->getTable() ?? throw new Exception("The column [{$this->getName()}] is not mounted to a table."); |
| 72 | + } |
| 73 | + |
| 74 | + /** |
| 75 | + * @return array<mixed> |
| 76 | + */ |
| 77 | + protected function resolveDefaultClosureDependencyForEvaluationByName(string $parameterName): array |
| 78 | + { |
| 79 | + return match ($parameterName) { |
| 80 | + 'livewire' => [$this->getLivewire()], |
| 81 | + 'record' => [$this->getRecord()], |
| 82 | + 'rowLoop' => [$this->getRowLoop()], |
| 83 | + 'state' => [$this->getState()], |
| 84 | + 'table' => [$this->getTable()], |
| 85 | + default => parent::resolveDefaultClosureDependencyForEvaluationByName($parameterName), |
| 86 | + }; |
| 87 | + } |
| 88 | + |
| 89 | + /** |
| 90 | + * @return array<mixed> |
| 91 | + */ |
| 92 | + protected function resolveDefaultClosureDependencyForEvaluationByType(string $parameterType): array |
| 93 | + { |
| 94 | + $record = $this->getRecord(); |
| 95 | + |
| 96 | + if (! $record) { |
| 97 | + return parent::resolveDefaultClosureDependencyForEvaluationByType($parameterType); |
| 98 | + } |
| 99 | + |
| 100 | + if (! ($record instanceof Model)) { |
| 101 | + return parent::resolveDefaultClosureDependencyForEvaluationByType($parameterType); |
| 102 | + } |
| 103 | + |
| 104 | + return match ($parameterType) { |
| 105 | + Model::class, $record::class => [$record], |
| 106 | + default => parent::resolveDefaultClosureDependencyForEvaluationByType($parameterType), |
| 107 | + }; |
| 108 | + } |
| 109 | + |
| 110 | + public function renderInLayout(): ?HtmlString |
| 111 | + { |
| 112 | + if ($this->isHidden()) { |
| 113 | + return null; |
| 114 | + } |
| 115 | + |
| 116 | + $attributes = (new ComponentAttributeBag) |
| 117 | + ->gridColumn( |
| 118 | + $this->getColumnSpan(), |
| 119 | + $this->getColumnStart(), |
| 120 | + ) |
| 121 | + ->class([ |
| 122 | + 'fi-growable' => $this->canGrow(), |
| 123 | + (filled($hiddenFrom = $this->getHiddenFrom()) ? "{$hiddenFrom}:fi-hidden" : ''), |
| 124 | + (filled($visibleFrom = $this->getVisibleFrom()) ? "{$visibleFrom}:fi-visible" : ''), |
| 125 | + ]); |
| 126 | + |
| 127 | + $this->inline(); |
| 128 | + |
| 129 | + $action = $this->getAction(); |
| 130 | + $url = $this->getUrl(); |
| 131 | + $isClickDisabled = $this->isClickDisabled(); |
| 132 | + |
| 133 | + $wrapperTag = match (true) { |
| 134 | + $url && (! $isClickDisabled) => 'a', |
| 135 | + $action && (! $isClickDisabled) => 'button', |
| 136 | + default => 'div', |
| 137 | + }; |
| 138 | + |
| 139 | + $attributes = $attributes |
| 140 | + ->merge([ |
| 141 | + 'type' => ($wrapperTag === 'button') ? 'button' : null, |
| 142 | + 'wire:click' => $wireClickAction = match (true) { |
| 143 | + ($wrapperTag !== 'button') => null, |
| 144 | + $action instanceof Action => "mountTableAction('{$action->getName()}', '{$this->getRecordKey()}')", |
| 145 | + filled($action) => "callTableColumnAction('{$this->getName()}', '{$this->getRecordKey()}')", |
| 146 | + default => null, |
| 147 | + }, |
| 148 | + 'wire:loading.attr' => ($wrapperTag === 'button') ? 'disabled' : null, |
| 149 | + 'wire:target' => $wireClickAction, |
| 150 | + ], escape: false) |
| 151 | + ->class([ |
| 152 | + 'fi-ta-col', |
| 153 | + ((($alignment = $this->getAlignment()) instanceof Alignment) ? "fi-align-{$alignment->value}" : (is_string($alignment) ? $alignment : '')), |
| 154 | + 'fi-ta-col-has-column-url' => ($wrapperTag === 'a') && filled($url), |
| 155 | + ]); |
| 156 | + |
| 157 | + ob_start(); ?> |
| 158 | + |
| 159 | + <<?= $wrapperTag ?> |
| 160 | + <?php if ($wrapperTag === 'a') { |
| 161 | + echo generate_href_html($url, $this->shouldOpenUrlInNewTab())->toHtml(); |
| 162 | + } ?> |
| 163 | + <?= $attributes->toHtml() ?> |
| 164 | + > |
| 165 | + <?= $this->toHtml() ?> |
| 166 | + </<?= $wrapperTag ?>> |
| 167 | + |
| 168 | + <?php return new HtmlString(ob_get_clean()); |
| 169 | + } |
| 170 | +} |
0 commit comments