add nova
This commit is contained in:
96
nova/src/Menu/Breadcrumb.php
Normal file
96
nova/src/Menu/Breadcrumb.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use JsonSerializable;
|
||||
use Laravel\Nova\AuthorizedToSee;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\Resource;
|
||||
|
||||
class Breadcrumb implements JsonSerializable
|
||||
{
|
||||
use AuthorizedToSee,
|
||||
Makeable;
|
||||
|
||||
/**
|
||||
* The breadcrumb's name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The breadcrumb's path.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* Construct a new Breadcrumb instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $path
|
||||
*/
|
||||
public function __construct($name, $path = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a breadcrumb from a resource class.
|
||||
*
|
||||
* @param \Laravel\Nova\Resource|class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return static
|
||||
*/
|
||||
public static function resource($resourceClass)
|
||||
{
|
||||
if ($resourceClass instanceof Resource && $resourceClass->model()->exists === true) {
|
||||
return static::make(
|
||||
Nova::__(':resource Details: :title', [
|
||||
'resource' => $resourceClass::singularLabel(),
|
||||
'title' => $resourceClass->title(),
|
||||
])
|
||||
)->path('/resources/'.$resourceClass::uriKey().'/'.$resourceClass->getKey())
|
||||
->canSee(function ($request) use ($resourceClass) {
|
||||
return $resourceClass->authorizedToView($request);
|
||||
});
|
||||
}
|
||||
|
||||
return static::make(
|
||||
Nova::__($resourceClass::label())
|
||||
)->path('/resources/'.$resourceClass::uriKey())
|
||||
->canSee(function ($request) use ($resourceClass) {
|
||||
return $resourceClass::availableForNavigation($request) && $resourceClass::authorizedToViewAny($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set breadcrumb's path.
|
||||
*
|
||||
* @param string $href
|
||||
* @return $this
|
||||
*/
|
||||
public function path($href)
|
||||
{
|
||||
$this->path = $href;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array{name: string, path: string|null}
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'path' => $this->authorizedToSee(app(NovaRequest::class)) ? $this->path : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
56
nova/src/Menu/Breadcrumbs.php
Normal file
56
nova/src/Menu/Breadcrumbs.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use JsonSerializable;
|
||||
use Laravel\Nova\AuthorizedToSee;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
|
||||
class Breadcrumbs implements JsonSerializable
|
||||
{
|
||||
use AuthorizedToSee;
|
||||
use Makeable;
|
||||
|
||||
/**
|
||||
* The breadcrumb's path.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* Construct a new Breadcrumb instance.
|
||||
*
|
||||
* @param string|null $items
|
||||
*/
|
||||
public function __construct($items = null)
|
||||
{
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set breadcrumb's path.
|
||||
*
|
||||
* @param string $href
|
||||
* @return $this
|
||||
*/
|
||||
public function items($href)
|
||||
{
|
||||
$this->items = $href;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array{name: string, path: string|null}|array
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->authorizedToSee(app(NovaRequest::class))
|
||||
? $this->items
|
||||
: [];
|
||||
}
|
||||
}
|
||||
105
nova/src/Menu/Menu.php
Normal file
105
nova/src/Menu/Menu.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use JsonSerializable;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
|
||||
/**
|
||||
* @phpstan-type TMenu \Laravel\Nova\Menu\MenuGroup|\Laravel\Nova\Menu\MenuItem|\Laravel\Nova\Menu\MenuList|\Laravel\Nova\Menu\MenuSection
|
||||
*
|
||||
* @method static static make(array|iterable $items = [])
|
||||
*/
|
||||
class Menu implements JsonSerializable
|
||||
{
|
||||
use Makeable;
|
||||
|
||||
/**
|
||||
* The items for the menu.
|
||||
*
|
||||
* @var \Illuminate\Support\Collection|array
|
||||
*/
|
||||
public $items = [];
|
||||
|
||||
/**
|
||||
* Create a new Menu instance.
|
||||
*
|
||||
* @param array|iterable $items
|
||||
*/
|
||||
public function __construct($items = [])
|
||||
{
|
||||
$this->items = collect($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given menu if not already wrapped.
|
||||
*
|
||||
* @param \Laravel\Nova\Menu\Menu|array|iterable $menu
|
||||
* @return \Laravel\Nova\Menu\Menu
|
||||
*/
|
||||
public static function wrap($menu)
|
||||
{
|
||||
return $menu instanceof self
|
||||
? $menu
|
||||
: self::make($menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push items into the menu.
|
||||
*
|
||||
* @param \JsonSerializable|array|iterable $items
|
||||
* @return $this
|
||||
*
|
||||
* @phpstan-param TMenu|array|iterable $items
|
||||
*/
|
||||
public function push($items = [])
|
||||
{
|
||||
return $this->append($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append items into the menu.
|
||||
*
|
||||
* @param \JsonSerializable|array|iterable $items
|
||||
* @return $this
|
||||
*
|
||||
* @phpstan-param TMenu|array|iterable $items
|
||||
*/
|
||||
public function append($items = [])
|
||||
{
|
||||
$this->items[] = $items;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend items to the menu.
|
||||
*
|
||||
* @param TMenu|array|iterable $items
|
||||
* @return $this
|
||||
*/
|
||||
public function prepend($items = [])
|
||||
{
|
||||
$this->items->prepend($items);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array<array-key, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
$request = app(NovaRequest::class);
|
||||
|
||||
return $this->items->flatten()
|
||||
->reject(function ($item) use ($request) {
|
||||
return method_exists($item, 'authorizedToSee') && ! $item->authorizedToSee($request);
|
||||
})
|
||||
->values()
|
||||
->jsonSerialize();
|
||||
}
|
||||
}
|
||||
51
nova/src/Menu/MenuCollection.php
Normal file
51
nova/src/Menu/MenuCollection.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use JsonSerializable;
|
||||
|
||||
/**
|
||||
* @template TKey of int
|
||||
* @template TValue of \Laravel\Nova\Menu\MenuGroup|\Laravel\Nova\Menu\MenuItem|\Laravel\Nova\Menu\MenuList|non-empty-array
|
||||
*
|
||||
* @extends \Illuminate\Support\Collection<TKey, TValue>
|
||||
*/
|
||||
class MenuCollection extends Collection
|
||||
{
|
||||
/**
|
||||
* Filter menus should be displayed for the given request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return static<int, TValue>
|
||||
*/
|
||||
public function authorized(Request $request)
|
||||
{
|
||||
return $this->reject(function ($menu) use ($request) {
|
||||
return method_exists($menu, 'authorizedToSee') && ! $menu->authorizedToSee($request);
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves menus and remove empty group or lists.
|
||||
*
|
||||
* @return static<int, TValue>
|
||||
*/
|
||||
public function withoutEmptyItems()
|
||||
{
|
||||
return $this->transform(function ($menu) {
|
||||
if ($menu instanceof JsonSerializable) {
|
||||
$payload = $menu->jsonSerialize();
|
||||
|
||||
if (($menu instanceof MenuGroup || $menu instanceof MenuList) && count($payload['items']) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
return $menu;
|
||||
})->filter()->values();
|
||||
}
|
||||
}
|
||||
84
nova/src/Menu/MenuGroup.php
Normal file
84
nova/src/Menu/MenuGroup.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Laravel\Nova\AuthorizedToSee;
|
||||
use Laravel\Nova\Fields\Collapsable;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
|
||||
/**
|
||||
* @method static static make(string $name, array $items = [])
|
||||
*/
|
||||
class MenuGroup implements \JsonSerializable
|
||||
{
|
||||
use AuthorizedToSee;
|
||||
use Collapsable;
|
||||
use Macroable;
|
||||
use Makeable;
|
||||
|
||||
/**
|
||||
* The menu's component.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $component = 'menu-group';
|
||||
|
||||
/**
|
||||
* The menu's name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The menu's items.
|
||||
*
|
||||
* @var \Laravel\Nova\Menu\MenuCollection
|
||||
*/
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* Construct a new Menu Group instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $items
|
||||
*/
|
||||
public function __construct($name, $items = [])
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->items = new MenuCollection($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the menu's unique key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return md5($this->name.$this->items->reduce(function ($carry, $item) {
|
||||
return $carry.'-'.$item->name;
|
||||
}, ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
$request = app(NovaRequest::class);
|
||||
|
||||
return [
|
||||
'component' => $this->component,
|
||||
'name' => $this->name,
|
||||
'items' => $this->items->authorized($request)->withoutEmptyItems()->all(),
|
||||
'collapsable' => $this->collapsable,
|
||||
'collapsedByDefault' => $this->collapsedByDefault,
|
||||
'key' => $this->key(),
|
||||
];
|
||||
}
|
||||
}
|
||||
451
nova/src/Menu/MenuItem.php
Normal file
451
nova/src/Menu/MenuItem.php
Normal file
@@ -0,0 +1,451 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
use JsonSerializable;
|
||||
use Laravel\Nova\AuthorizedToSee;
|
||||
use Laravel\Nova\Contracts\Filter as FilterContract;
|
||||
use Laravel\Nova\Filters\FilterEncoder;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\URL;
|
||||
use Laravel\Nova\WithBadge;
|
||||
|
||||
/**
|
||||
* @method static static make(string $name, string|null $path = null)
|
||||
*/
|
||||
class MenuItem implements JsonSerializable
|
||||
{
|
||||
use AuthorizedToSee;
|
||||
use Macroable;
|
||||
use Makeable;
|
||||
use WithBadge;
|
||||
|
||||
/**
|
||||
* The menu's component.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $component = 'menu-item';
|
||||
|
||||
/**
|
||||
* The menu item's name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The menu's path.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* The menu's request method (GET, POST, PUT, PATCH, DELETE).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $method = 'GET';
|
||||
|
||||
/**
|
||||
* The menu's data.
|
||||
*
|
||||
* @var array<string, string>|null
|
||||
*/
|
||||
public $data = null;
|
||||
|
||||
/**
|
||||
* The menu's headers.
|
||||
*
|
||||
* @var array<string, string>|null
|
||||
*/
|
||||
public $headers = null;
|
||||
|
||||
/**
|
||||
* Indicate whether the menu's resolve to an external URL.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $external = false;
|
||||
|
||||
/**
|
||||
* The target value for external link.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $target;
|
||||
|
||||
/**
|
||||
* The active menu callback.
|
||||
*
|
||||
* @var (callable(\Illuminate\Http\Request, \Laravel\Nova\URL):bool)|bool|null
|
||||
*/
|
||||
public $activeMenuCallback;
|
||||
|
||||
/**
|
||||
* The filters for the menu item.
|
||||
*
|
||||
* @var \Illuminate\Support\Collection
|
||||
*/
|
||||
public $filters;
|
||||
|
||||
/**
|
||||
* The resource class name.
|
||||
*
|
||||
* @var class-string<\Laravel\Nova\Resource>|null
|
||||
*/
|
||||
public $resource;
|
||||
|
||||
/**
|
||||
* Construct a new Menu Item instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $path
|
||||
*/
|
||||
public function __construct($name, $path = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->path = $path;
|
||||
$this->filters = collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu item from a resource class.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return static
|
||||
*/
|
||||
public static function resource($resourceClass)
|
||||
{
|
||||
return static::make($resourceClass::label())
|
||||
->forResource($resourceClass)
|
||||
->path('/resources/'.$resourceClass::uriKey())
|
||||
->activeWhen(function ($request, $url) {
|
||||
return ! $request->routeIs('nova.pages.lens') ? $url->active() : false;
|
||||
})
|
||||
->canSee(function ($request) use ($resourceClass) {
|
||||
return $resourceClass::availableForNavigation($request) && $resourceClass::authorizedToViewAny($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu item from a lens class.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @param class-string<\Laravel\Nova\Lenses\Lens> $lensClass
|
||||
* @return static
|
||||
*/
|
||||
public static function lens($resourceClass, $lensClass)
|
||||
{
|
||||
return with(new $lensClass, function ($lens) use ($resourceClass) {
|
||||
return static::make($lens->name())
|
||||
->path('/resources/'.$resourceClass::uriKey().'/lens/'.$lens->uriKey())
|
||||
->canSee(function ($request) use ($lens) {
|
||||
return $lens->authorizedToSee($request);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu item from a resource with a set of filters.
|
||||
*
|
||||
* @param string $name
|
||||
* @param class-string $resourceClass
|
||||
* @param \Laravel\Nova\Filters\Filter|null $filter
|
||||
* @param mixed|null $value
|
||||
* @return static
|
||||
*/
|
||||
public static function filter($name, $resourceClass, $filter = null, $value = null)
|
||||
{
|
||||
$item = static::make($name)
|
||||
->forResource($resourceClass);
|
||||
|
||||
if ($filter) {
|
||||
$item->applies($filter, $value);
|
||||
}
|
||||
|
||||
return $item
|
||||
->activeWhen(function ($request, $url) {
|
||||
return "/{$request->path()}?{$request->getQueryString()}" === (string) $url;
|
||||
})
|
||||
->canSee(function ($request) use ($resourceClass) {
|
||||
return $resourceClass::availableForNavigation($request) && $resourceClass::authorizedToViewAny($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a filter to the menu item.
|
||||
*
|
||||
* @param \Laravel\Nova\Filters\Filter|string $filter
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function applies($filter, $value)
|
||||
{
|
||||
// If the filter is an actual filter instance, and not a filter generated from
|
||||
// a `filterable` field, let's ensure the user is authorized to see it.
|
||||
// If not, don't push the filter into the filter's collection.
|
||||
if ($filter instanceof FilterContract && ! $filter->authorizedToSee(app(NovaRequest::class))) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->filters->push([
|
||||
'class' => $filter instanceof FilterContract ? get_class($filter) : $filter,
|
||||
'value' => $value,
|
||||
]);
|
||||
|
||||
$queryString = $this->queryString();
|
||||
|
||||
$path = '/resources/'.$this->resource::uriKey().'?'.$queryString;
|
||||
|
||||
return $this->path($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resource to be used for the menu item.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return $this
|
||||
*/
|
||||
protected function forResource($resourceClass)
|
||||
{
|
||||
$this->resource = $resourceClass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query string for a filtered resource menu item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function queryString()
|
||||
{
|
||||
return Arr::query([
|
||||
$this->resource::uriKey().'_filter' => $this->encodedFilters(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function encodedFilters()
|
||||
{
|
||||
return (new FilterEncoder($this->filters->all()))->encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's path.
|
||||
*
|
||||
* @param string $href
|
||||
* @return $this
|
||||
*/
|
||||
public function path($href)
|
||||
{
|
||||
$this->path = $href;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu from dashboard class.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Dashboard> $dashboard
|
||||
* @return static
|
||||
*/
|
||||
public static function dashboard($dashboard)
|
||||
{
|
||||
return with(new $dashboard(), function ($dashboard) {
|
||||
return static::make(
|
||||
$dashboard->label(),
|
||||
'/dashboards/'.$dashboard->uriKey()
|
||||
)->canSee(function ($request) use ($dashboard) {
|
||||
return $dashboard->authorizedToSee($request);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create menu to an internal Nova path.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @return static
|
||||
*/
|
||||
public static function link($name, $path)
|
||||
{
|
||||
return new static($name, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create menu to an external URL.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @return static
|
||||
*/
|
||||
public static function externalLink($name, $path)
|
||||
{
|
||||
return (new static($name, $path))->external();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marked as external url.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function external()
|
||||
{
|
||||
$this->external = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the menu's target to open in a new tab.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function openInNewTab()
|
||||
{
|
||||
$this->target = '_blank';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's method, and optionally data or headers.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array<string, mixed>|null $data
|
||||
* @param array<string, string>|null $headers
|
||||
* @return $this
|
||||
*/
|
||||
public function method($method, $data = null, $headers = null)
|
||||
{
|
||||
if (! in_array($method, ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])) {
|
||||
throw new InvalidArgumentException('Only supports GET, POST, PUT, PATCH or DELETE method');
|
||||
}
|
||||
|
||||
$this->method = $method;
|
||||
|
||||
return $this->data($data)->headers($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's method, and optionally data or headers. This request will be handled via Inertia.visit().
|
||||
*
|
||||
* @param string $method
|
||||
* @param array<string, mixed>|null $data
|
||||
* @param array<string, string>|null $headers
|
||||
* @return static
|
||||
*/
|
||||
public function inertia($method = 'GET', $data = null, $headers = null)
|
||||
{
|
||||
if ($method !== 'GET') {
|
||||
$headers = Arr::wrap($headers);
|
||||
}
|
||||
|
||||
return $this->method($method, $data, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's headers.
|
||||
*
|
||||
* @param array<string, string>|null $headers
|
||||
* @return $this
|
||||
*/
|
||||
public function headers($headers = null)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's data.
|
||||
*
|
||||
* @param array<string, string>|null $data
|
||||
* @return $this
|
||||
*/
|
||||
public function data($data = null)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function name($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the default active URL state.
|
||||
*
|
||||
* @param (callable(\Illuminate\Http\Request, \Laravel\Nova\URL):bool)|bool $activeMenuCallback
|
||||
* @return $this
|
||||
*/
|
||||
public function activeWhen($activeMenuCallback)
|
||||
{
|
||||
$this->activeMenuCallback = $activeMenuCallback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the default active URL state.
|
||||
*
|
||||
* @param (callable(\Illuminate\Http\Request, \Laravel\Nova\URL):bool)|bool $activeMenuCallback
|
||||
* @return $this
|
||||
*/
|
||||
public function activeUnless($activeMenuCallback)
|
||||
{
|
||||
$this->activeMenuCallback = function ($request, $url) use ($activeMenuCallback) {
|
||||
return value($activeMenuCallback, $request, $url) === false;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
$url = URL::make($this->path, $this->external);
|
||||
|
||||
$activeMenuCallback = $this->activeMenuCallback ?? function ($request, URL $url) {
|
||||
return $url->active();
|
||||
};
|
||||
|
||||
return [
|
||||
'name' => Nova::__($this->name),
|
||||
'component' => $this->component,
|
||||
'path' => (string) $url,
|
||||
'external' => $this->external,
|
||||
'target' => $this->target,
|
||||
'method' => $this->method,
|
||||
'data' => $this->data,
|
||||
'headers' => $this->headers,
|
||||
'active' => value($activeMenuCallback, request(), $url),
|
||||
'badge' => $this->resolveBadge(),
|
||||
];
|
||||
}
|
||||
}
|
||||
68
nova/src/Menu/MenuList.php
Normal file
68
nova/src/Menu/MenuList.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use Laravel\Nova\AuthorizedToSee;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
|
||||
/**
|
||||
* @method static static make(array $items)
|
||||
*/
|
||||
class MenuList implements \JsonSerializable
|
||||
{
|
||||
use AuthorizedToSee;
|
||||
use Makeable;
|
||||
|
||||
/**
|
||||
* The menu's component.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $component = 'menu-list';
|
||||
|
||||
/**
|
||||
* The menu's items.
|
||||
*
|
||||
* @var \Laravel\Nova\Menu\MenuCollection
|
||||
*/
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* Construct a new Menu List instance.
|
||||
*
|
||||
* @param array $items
|
||||
*/
|
||||
public function __construct($items)
|
||||
{
|
||||
$this->items($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set menu's items.
|
||||
*
|
||||
* @param array $items
|
||||
* @return $this
|
||||
*/
|
||||
public function items($items = [])
|
||||
{
|
||||
$this->items = new MenuCollection($items);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
$request = app(NovaRequest::class);
|
||||
|
||||
return [
|
||||
'component' => $this->component,
|
||||
'items' => $this->items->authorized($request)->withoutEmptyItems()->all(),
|
||||
];
|
||||
}
|
||||
}
|
||||
191
nova/src/Menu/MenuSection.php
Normal file
191
nova/src/Menu/MenuSection.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Menu;
|
||||
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use JsonSerializable;
|
||||
use Laravel\Nova\AuthorizedToSee;
|
||||
use Laravel\Nova\Exceptions\NovaException;
|
||||
use Laravel\Nova\Fields\Collapsable;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Makeable;
|
||||
use Laravel\Nova\URL;
|
||||
use Laravel\Nova\WithBadge;
|
||||
use Laravel\Nova\WithIcon;
|
||||
|
||||
/**
|
||||
* @method static static make(string $name, array|iterable $items = [], string $icon = 'collection')
|
||||
*/
|
||||
class MenuSection implements JsonSerializable
|
||||
{
|
||||
use AuthorizedToSee;
|
||||
use Collapsable;
|
||||
use Macroable;
|
||||
use Makeable;
|
||||
use WithBadge;
|
||||
use WithIcon;
|
||||
|
||||
/**
|
||||
* The menu's component.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $component = 'menu-section';
|
||||
|
||||
/**
|
||||
* The menu's name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The menu's items.
|
||||
*
|
||||
* @var \Laravel\Nova\Menu\MenuCollection
|
||||
*/
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* The menu's path.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* Construct a new Menu Section instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array|iterable $items
|
||||
* @param string $icon
|
||||
*/
|
||||
public function __construct($name, $items = [], $icon = 'collection')
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->items = new MenuCollection($items);
|
||||
$this->withIcon($icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu from dashboard class.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Dashboard> $dashboard
|
||||
* @return static
|
||||
*/
|
||||
public static function dashboard($dashboard)
|
||||
{
|
||||
return with(new $dashboard(), function ($dashboard) {
|
||||
return static::make(
|
||||
$dashboard->label()
|
||||
)->path('/dashboards/'.$dashboard->uriKey())
|
||||
->canSee(function ($request) use ($dashboard) {
|
||||
return $dashboard->authorizedToSee($request);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu section from a resource class.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return static
|
||||
*/
|
||||
public static function resource($resourceClass)
|
||||
{
|
||||
return static::make(
|
||||
$resourceClass::label()
|
||||
)->path('/resources/'.$resourceClass::uriKey())
|
||||
->canSee(function ($request) use ($resourceClass) {
|
||||
return $resourceClass::availableForNavigation($request) && $resourceClass::authorizedToViewAny($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a menu section from a lens class.
|
||||
*
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @param class-string<\Laravel\Nova\Lenses\Lens> $lensClass
|
||||
* @return static
|
||||
*/
|
||||
public static function lens($resourceClass, $lensClass)
|
||||
{
|
||||
return with(new $lensClass, function ($lens) use ($resourceClass) {
|
||||
return static::make($lens->name())
|
||||
->path('/resources/'.$resourceClass::uriKey().'/lens/'.$lens->uriKey())
|
||||
->canSee(function ($request) use ($lens) {
|
||||
return $lens->authorizedToSee($request);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set path to the menu.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function path($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
if ($this->collapsable) {
|
||||
throw new NovaException('Link menu sections cannot also be collapsable.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the menu section as collapsable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function collapsable()
|
||||
{
|
||||
$this->collapsable = true;
|
||||
|
||||
if ($this->path) {
|
||||
throw new NovaException('Link menu sections cannot also be collapsable.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set icon to the menu.
|
||||
*
|
||||
* @param string $icon
|
||||
* @return $this
|
||||
*/
|
||||
public function icon($icon)
|
||||
{
|
||||
$this->icon = $icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the menu for JSON serialization.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
$request = app(NovaRequest::class);
|
||||
$url = ! empty($this->path) ? URL::make($this->path) : null;
|
||||
|
||||
return [
|
||||
'active' => optional($url)->active() ?? false,
|
||||
'badge' => $this->resolveBadge(),
|
||||
'collapsable' => $this->collapsable,
|
||||
'collapsedByDefault' => $this->collapsedByDefault,
|
||||
'component' => $this->component,
|
||||
'icon' => $this->icon,
|
||||
'items' => $this->items->authorized($request)->withoutEmptyItems()->all(),
|
||||
'key' => md5($this->name.'-'.$this->path),
|
||||
'name' => $this->name,
|
||||
'path' => (string) $url,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user