Skip to content

Commit

Permalink
Merge pull request #1524 from moonshine-software/old-values
Browse files Browse the repository at this point in the history
Old values
  • Loading branch information
lee-to authored Feb 7, 2025
2 parents aee6339 + 421e99d commit c190273
Show file tree
Hide file tree
Showing 20 changed files with 348 additions and 120 deletions.
58 changes: 58 additions & 0 deletions .meta-storm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,49 @@
<stopCompletion />
</classMethod>

<classMethod
class="\MoonShine\AssetManager\InlineJs"
method="make"
argument="0"
>
<languageInjection language="JavaScript"/>
<stopCompletion />
</classMethod>

<classConstructor
class="\MoonShine\AssetManager\InlineJs"
argument="0"
>
<languageInjection language="JavaScript"/>
<stopCompletion />
</classConstructor>

<classMethod
class="\MoonShine\AssetManager\InlineCss"
method="make"
argument="0"
>
<languageInjection language="CSS"/>
<stopCompletion />
</classMethod>

<classConstructor
class="\MoonShine\AssetManager\InlineCss"
argument="0"
>
<languageInjection language="CSS"/>
<stopCompletion />
</classConstructor>

<classMethod
class="\MoonShine\UI\Components\ActionButton"
method="onClick"
argument="1"
>
<collection name="onclick-modifiers" argument="1" />
<stopCompletion />
</classMethod>

<classMethod
class="\MoonShine\Contracts\UI\FormBuilderContract"
method="asyncMethod"
Expand Down Expand Up @@ -112,5 +155,20 @@
<value>lg</value>
<value>xl</value>
</strings>
<strings name="onclick-modifiers">
<value>prevent</value>
<value>stop</value>
<value>outside</value>
<value>window</value>
<value>document</value>
<value>once</value>
<value>debounce</value>
<value>throttle</value>
<value>self</value>
<value>camel</value>
<value>dot</value>
<value>passive</value>
<value>capture</value>
</strings>
</collections>
</meta-storm>
16 changes: 16 additions & 0 deletions src/Contracts/src/UI/FieldWithComponentContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace MoonShine\Contracts\UI;

/**
* @template TComponent of ComponentContract
*/
interface FieldWithComponentContract
{
/**
* @return TComponent
*/
public function getComponent(): ComponentContract;
}
12 changes: 5 additions & 7 deletions src/Laravel/src/Fields/Relationships/BelongsTo.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ protected function resolvePreview(): string

protected function resolveValue(): mixed
{
if (\is_scalar($this->toValue())) {
return $this->toValue();
}

return $this->toValue()?->getKey();
}

Expand Down Expand Up @@ -122,13 +126,7 @@ public function prepareReactivityValue(mixed $value, mixed &$casted, array &$exc
$value = data_get($value, 'value', $value);

$casted = $this->getRelatedModel();
$related = $this->getRelation()?->getRelated();

$target = $related?->forceFill([
$related->getKeyName() => $value,
]);

$casted?->setRelation($this->getRelationName(), $target);
$casted?->setRelation($this->getRelationName(), $this->makeRelatedModel($value));

return $value;
}
Expand Down
99 changes: 69 additions & 30 deletions src/Laravel/src/Fields/Relationships/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
use Illuminate\Support\Collection;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
use MoonShine\Contracts\UI\ActionButtonContract;
use MoonShine\Contracts\UI\Collection\ActionButtonsContract;
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\Contracts\UI\FieldWithComponentContract;
use MoonShine\Contracts\UI\HasFieldsContract;
use MoonShine\Contracts\UI\TableBuilderContract;
use MoonShine\Laravel\Collections\Fields;
Expand Down Expand Up @@ -46,12 +48,14 @@
*
* @extends ModelRelationField<R>
* @implements HasFieldsContract<Fields|FieldsContract>
* @implements FieldWithComponentContract<TableBuilderContract|ActionButtonContract>
*/
class BelongsToMany extends ModelRelationField implements
HasRelatedValuesContact,
HasPivotContract,
HasFieldsContract,
HasAsyncSearchContract
HasAsyncSearchContract,
FieldWithComponentContract
{
use WithFields;
use WithRelatedValues;
Expand All @@ -70,8 +74,6 @@ class BelongsToMany extends ModelRelationField implements

protected bool $isGroup = true;

protected bool $hasOld = false;

protected bool $resolveValueOnce = true;

protected string $treeParentColumn = '';
Expand Down Expand Up @@ -100,6 +102,8 @@ class BelongsToMany extends ModelRelationField implements

protected ?string $columnLabel = null;

protected ?TableBuilderContract $resolvedComponent = null;

public function onlyCount(): static
{
$this->onlyCount = true;
Expand Down Expand Up @@ -187,7 +191,7 @@ public function getRelatedKeyName(): string

public function getCollectionValue(): EloquentCollection
{
return new EloquentCollection($this->toValue() ?? []);
return new EloquentCollection($this->getValue() ?? []);
}

public function getSelectedValue(): string|array
Expand Down Expand Up @@ -222,6 +226,11 @@ protected function getResourceColumnLabel(): string
return $this->columnLabel ?? $this->getResource()->getTitle();
}

public function getPivotName(): string
{
return "{$this->getRelationName()}_pivot";
}

/**
* @throws Throwable
*/
Expand All @@ -233,7 +242,7 @@ protected function prepareFields(): FieldsContract
->setColumn("{$this->getPivotAs()}.{$field->getColumn()}")
->class('js-pivot-field')
->withoutWrapper(),
performName: fn (string $name): string => str_replace($this->getRelationName(), "{$this->getRelationName()}_pivot", $name),
performName: fn (string $name): string => str_replace($this->getRelationName(), $this->getPivotName(), $name),
);
}

Expand All @@ -248,19 +257,25 @@ protected function prepareFill(array $raw = [], ?DataWrapperContract $casted = n
return $values;
}

/**
* @throws Throwable
*/
protected function resolveValue(): mixed
public function setValues(array $values): void
{
$this->setValue(new Collection($values));
}

public function getAvailableValues(): mixed
{
if (! \is_null($this->memoizeValues)) {
return $this->memoizeValues;
}

// fix for filters
if ($this->isAsyncSearch() && ! $this->isValueWithModels($this->memoizeValues) && filled($this->toValue())) {
$keys = $this->isSelectMode() ? $this->getCollectionValue()->toArray() : $this->getCollectionValue()->keys();

$this->memoizeValues = $this->getRelation()
?->getRelated()
?->newQuery()
?->findMany($keys) ?? EloquentCollection::make();
?->getRelated()
?->newQuery()
?->findMany($keys) ?? EloquentCollection::make();
}

if ($this->isSelectMode()) {
Expand Down Expand Up @@ -289,9 +304,13 @@ protected function resolveValue(): mixed
});
}

protected function getComponent(): ComponentContract
public function getComponent(): ComponentContract
{
$values = $this->getValue();
if (! \is_null($this->resolvedComponent)) {
return $this->resolvedComponent;
}

$values = $this->getAvailableValues();

if ($this->isRelatedLink()) {
return $this->getRelatedLink();
Expand Down Expand Up @@ -326,7 +345,7 @@ protected function getComponent(): ComponentContract
)
->prepend($identityField);

return TableBuilder::make(items: $values)
return $this->resolvedComponent = TableBuilder::make(items: $values)
->name($this->getTableComponentName())
->customAttributes($this->getAttributes()->jsonSerialize())
->fields($fields)
Expand Down Expand Up @@ -359,6 +378,33 @@ protected function getColumnOrFormattedValue(Model $item, string|int $default):
return $default;
}

protected function resolveOldValue(mixed $old): mixed
{
// otherwise you will have to make a db query to receive records by keys
if ($this->isAsyncSearch()) {
return $this->toValue();
}

$oldPivot = $this->getCore()->getRequest()->getOld($this->getPivotName());

return collect($old)
->map(fn ($key): ?Model => clone $this->makeRelatedModel($key, relations: $oldPivot[$key] ?? []))
->values();
}

protected function resolveValue(): mixed
{
if (\is_array($this->toValue())) {
$this->setValue(
collect($this->toValue())
->map(fn ($key): ?Model => clone $this->makeRelatedModel($key))
->values()
);
}

return parent::resolveValue();
}

protected function resolveRawValue(): mixed
{
return $this->getCollectionValue()
Expand Down Expand Up @@ -443,7 +489,7 @@ public function getCheckedKeys(): Collection

public function getKeys(): array
{
if (\is_null($this->toValue())) {
if (\is_null($this->getValue())) {
return [];
}

Expand Down Expand Up @@ -547,11 +593,9 @@ protected function resolveAfterDestroy(mixed $data): mixed
public function prepareReactivityValue(mixed $value, mixed &$casted, array &$except): mixed
{
$casted = $this->getRelatedModel();
$related = $this->getRelation()?->getRelated();

$value = collect($value)->map(fn ($v) => clone $related->forceFill([
$related->getKeyName() => $v,
]))->values();
$value = collect($value)
->map(fn ($key): ?Model => clone $this->makeRelatedModel($key))
->values();

$casted?->setRelation($this->getRelationName(), $value);
$except[$this->getColumn()] = $this->getColumn();
Expand All @@ -565,11 +609,7 @@ public function getReactiveValue(): mixed
throw FieldException::reactivityNotSupported(static::class, 'with asyncSearch');
}

if (! $this->isTree() || $this->isSelectMode()) {
return $this->getCollectionValue()->pluck($this->getRelatedKeyName());
}

return parent::getReactiveValue();
return $this->getCollectionValue()->pluck($this->getRelatedKeyName());
}

/**
Expand Down Expand Up @@ -598,6 +638,7 @@ protected function viewData(): array
return [
...$viewData,
'isSearchable' => $this->isSearchable(),
'values' => $this->getAvailableValues(),
];
}

Expand All @@ -608,12 +649,10 @@ protected function viewData(): array
];
}

$component = $this->getComponent();

return [
...$viewData,
'component' => $component,
'componentName' => $component->getName(),
'component' => $this->getComponent(),
'componentName' => $this->getComponent()->getName(),
'buttons' => $this->getButtons(),
];
}
Expand Down
13 changes: 11 additions & 2 deletions src/Laravel/src/Fields/Relationships/HasMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use MoonShine\Contracts\UI\ActionButtonContract;
use MoonShine\Contracts\UI\ComponentContract;
use MoonShine\Contracts\UI\FieldContract;
use MoonShine\Contracts\UI\FieldWithComponentContract;
use MoonShine\Contracts\UI\FormBuilderContract;
use MoonShine\Contracts\UI\HasFieldsContract;
use MoonShine\Contracts\UI\TableBuilderContract;
use MoonShine\Laravel\Buttons\HasManyButton;
Expand All @@ -34,8 +36,9 @@
* @template-covariant R of (HasOneOrMany|HasOneOrManyThrough|MorphOneOrMany)
* @extends ModelRelationField<R>
* @implements HasFieldsContract<Fields|FieldsContract>
* @implements FieldWithComponentContract<TableBuilderContract|FormBuilderContract|ActionButtonContract>
*/
class HasMany extends ModelRelationField implements HasFieldsContract
class HasMany extends ModelRelationField implements HasFieldsContract, FieldWithComponentContract
{
use WithFields;
use WithRelatedLink;
Expand Down Expand Up @@ -83,6 +86,8 @@ class HasMany extends ModelRelationField implements HasFieldsContract

protected bool $withoutModals = false;

protected null|TableBuilderContract|FormBuilderContract|ActionButtonContract $resolvedComponent = null;

public function withoutModals(): static
{
$this->withoutModals = true;
Expand Down Expand Up @@ -559,7 +564,11 @@ protected function resolveValue(): mixed
*/
public function getComponent(): ComponentContract
{
return $this->isRelatedLink()
if (! \is_null($this->resolvedComponent)) {
return $this->resolvedComponent;
}

return $this->resolvedComponent = $this->isRelatedLink()
? $this->getRelatedLink()
: $this->getTableValue();
}
Expand Down
Loading

0 comments on commit c190273

Please sign in to comment.