uteq / laravel-move
Laravel admin panel powered by Livewire and Jetstream
Requires
- php: ^8.0
- ext-exif: *
- ext-json: *
- intervention/image: ^2.7
- laravel/jetstream: ^2.6
- livewire/livewire: ^2.10
- maatwebsite/excel: ^3.1
- spatie/data-transfer-object: ^2.6|^3.7
- spatie/laravel-medialibrary: ^10.0
Requires (Dev)
- barryvdh/laravel-ide-helper: ^2.12
- friendsofphp/php-cs-fixer: ^3.6
- orchestra/testbench: ^7.0
- phpunit/phpunit: ^9.5
- spatie/laravel-ray: ^1.29
- vimeo/psalm: ^4.20
- dev-master
- v0.4.x-dev
- v0.4.1.x-dev
- 0.4.1
- 0.3.3
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.4
- 0.2.3
- 0.2.2
- 0.2.1
- 0.2.0
- 0.1.0
- dev-digipz
- dev-dependabot/npm_and_yarn/minimist-1.2.8
- dev-dependabot/npm_and_yarn/json5-1.0.2
- dev-dependabot/npm_and_yarn/express-4.18.2
- dev-dependabot/npm_and_yarn/qs-and-express-6.11.0
- dev-dependabot/npm_and_yarn/decode-uri-component-0.2.2
- dev-dependabot/npm_and_yarn/minimatch-3.1.2
- dev-dependabot/npm_and_yarn/terser-4.8.1
- dev-dependabot/npm_and_yarn/async-2.6.4
This package is auto-updated.
Last update: 2024-10-10 12:24:51 UTC
README
Laravel Move | An admin panel powered by Livewire and Jetstream
This package is still in development and does not have a complete test suite.
Move makes it very easy to create your own Admin Panel using Laravel and Livewire. This package was heavily inspired bij Laravel Nova. And works practically the same, except for some missing features.
Here is an example of how you can use it:
<?php namespace App\Move; use Uteq\Move\Fields\Id; use Uteq\Move\Fields\Text; use Uteq\Move\Resource; class User extends Resource { public static $model = \App\Models\User::class; public static string $title = 'name'; public function fields() { return [ Id::make(), Text::make('Name', 'name'), ]; } }
And this is a basic example with a user:
Todo
- Package dependencies
- Tests
Support us
To best support is by improving this package. There is still a lot work to be done. For example:
- Documentation -- Setup -- Fields (Also: Panel and Step) -- Search -- Actions -- Permissions -- Customizations -- Reuseable (Move re-usable in many ways)
- Test coverage
- Fields extension (adding all sorts of fields)
- Stubs and Class generators
- Cards (like Laravel Nova cards)
Installation
You can install the package via composer:
composer require uteq/laravel-move
Laravel Move will add Jetstream to your vendor folder, but will not install it automatically. So, for your convenience we tailor made a command that will install Jetstream and bootstrap the Move Admin Panel. Because Move uses Livewire as the preferred stack you do not have to supply the stack. In addition, you may use the --teams switch to enable team support:
php artisan move:install --team
To finalize your installation run:
php artisan migrate
Optional
Configure Jetstream
For more Jetstream related setup, please check: https://jetstream.laravel.com/2.x/installation.html#installing-jetstream
You can publish the config file with:
php artisan vendor:publish --provider="Uteq\Move\MoveServiceProvider" --tag="move-config"
You can publish the view files with:
php artisan vendor:publish --provider="Uteq\Move\MoveServiceProvider" --tag="move-views"
Usage
Creating your first resource
Start by creating your first Move Resource. You can generate it or use the example below:
Generate your resource
php artisan move:resource User --model=User
Use example resource
<?php namespace App\Move; use Uteq\Move\Fields\Id; use Uteq\Move\Fields\Text; use Uteq\Move\Resource; class User extends Resource { public static $model = \App\Models\User::class; public static string $title = 'name'; public function fields() { return [ Id::make(), Text::make('Naam', 'name') ->rules(['required', 'string', 'max:255']) ->required(), Text::make('E-mailadres', 'email') ->hideWhenUpdating() ->requiredOnCreateOnly() ->creationRules(['required', 'string', 'email', 'max:255', 'unique:users']), Status::make('E-mail bevestigd?', 'email_verified_at', fn ($value) => $value !== null) ->hideFromForm(), Panel::make('Wachtwoord wijzigen', [ Password::make('Wachtwoord', 'password', null) ->creationRules($this->passwordRules()) ->requiredOnCreateOnly(), Password::make('Wachtwoord bevestigen', 'password_confirmation') ->hideFromIndex() ->hideFromDetail() ->onlyForValidation(fn ($value, $field, $model) => $model->id) ->requiredOnCreateOnly(), ]) ->nameOnCreate('Wachtwoord') ->nameOnUpdate('Wachtwoord wijzigen'), Panel::make('Rol kiezen', [ Role::make('Rol', 'role'), ]), ]; } public function filters() { return []; } public function actions() { return []; } }
Route prefix
Move out of the box adds a prefix to your resources, that way it will never interfere with your own routes.
The default is move
.
You can change the default prefix by overwriting it at your local MoveServiceProvider at App\Providers\MoveServiceProvider
:
use Illuminate\Support\Facades\Route; function register() { Route::move('my-prefix'); }
Manually Registering Resource Namespaces
The default namespace for Move is App\Move
. You are also able to register the Move Resources wherever you like.
You can Bootstrap this namespace in the following way
use Uteq\Move\Facades\Move; public function register() { Move::resourceNamespace('App\\Resources', 'resources'); }
This will automatically create the namespace for the routes. The default route for this namespace will be:
https://move.test/move/resources/your-resource
The resource default name will than be:
resources.your-resource
Using a json field to store data
If you work a lot with data structures that cannot be clearly defined in a mysql database structure. You will probably opt for something like a json field.
First add your json field to your table.
$table->json('meta')->nullable();
Than make sure you cast it properly in you model
protected $casts ['meta' => 'json'];
At last, add a field to your resource
Text::make('My meta value', 'meta.my_value'),
Resources
Supported Field types
These are the currently supported fields in Move:
- Country
- Date
- Files
- Id
- Number
- Password
- Select (with filter search)
- Status
- Text
- Textarea
- Editor
Sidebar
Move automatically registers resources to the sidebar. By default there are two ways to show your sidebar resources. Grouped and flat. The default is grouped and is published with the \App\Providers\MoveServiceProvider.
Move::useSidebarGroups(true);
To use the flat display, just change to
Move::useSidebarGroups(false);
When you use the sidebar groups you should also set the resource property:
class User extends \Uteq\Move\Resource { public static string $group = 'admin'; }
Ordering sidebar items
Currently, this is not a supported feature, feel free to create a PR. Or you can simply overwrite the components/sidebar-menu.blade.php file.
Ordering sidebar by namespace
Whenever you would prefer to order your sidebar by the given namespace just use the grouped sidebar approach. If not you can always overwrite the components/sidebar-menu.blade.php file or create a PR.
Overwrite the sidebar menu logo
<x-move-sidebar> <x-slot name="logo"> <a class="text-center" href="/"> <h1 class="text-2xl text-white font-black">{{ config('app.name') }}</h1> </a> </x-slot> </x-move-sidebar>
Overwriting the sidebar menu items
You can completely overwrite the sidebar items. And the logo.
<x-move-sidebar :keep-not-custom="false" :with-padding="false"> <!-- You can also add you own html + css here, move just has a link component --> <x-move-sidebar.link href="{{ route('dashboard') }}" alt-active="admin/dashboard/*"> Dashboard </x-move-sidebar.link> </x-move-sidebar>
You can also keep the automatically generated sidebar items and add you own before the automatic created. This is the default behavior.
<x-move-sidebar> <x-move-sidebar.link href="{{ route('dashboard') }}" alt-active="admin/dashboard/*"> Dashboard </x-move-sidebar.link> </x-move-sidebar>
In depth
Resolving a resource
Resolving a resource means loading the concrete implementation of your Resource class. You can do this by providing the name of your resource:
use \Uteq\Move\Facades\Move; Move::resolveResource('resources.your-resource');
Overwriting the default $actionHandlers
Action handlers are classes that make it possible to store and delete your resources the way you prefer. By default Move will have its own default logic.
Move provides two default action handlers Uteq\Move\DomainActions\StoreResource
and Uteq\Move\DomainActions\DeleteResource
.
You are able to overwrite these handlers from your Resource and by default.
Creating your own Action handler
class StoreHandler { public function __invoke(Model $model, array $input = []) { //... Basic validation $model->fill($input)->save(); return $model; } }
You can also extend the default StoreResource, but this is not mandatory.
Overwriting the default $actionHandlers system wide
Overwrite the action handlers from a ServiceProvider.
use Uteq\Move\Resource; public function register() { Resource::$defaultActionHandlers = [ 'update' => StoreResource::class, 'create' => StoreResource::class, 'delete' => DeleteResource::class, ]; }
Overwriting the default $actionHandlers from your resource
Simply add the $actionHandlers to your resource:
use Uteq\Move\Resource; use App\Actions\CustomResource; class CustomResource extends Resource { public array $actionHandlers = [ 'create' => CustomResource\Create::class, 'update' => CustomResource\Update::class, 'delete' => CustomResource\Delete::class, ]; }
This will overwrite the resource specific action handlers.
Hooks
Model Before save
The preferred way to hook into the before save is using the default Laravel events https://laravel.com/docs/eloquent#events. You can also hook into the Store action by adding a beforeSave method that provides callables
public function beforeSave() { return [ fn($resource, $model, $data) => $data['rand'] = rand(1, 99), function($resource, $model, $data) { return $data['rand'] = rand(1, 99); }, new MyCustomBeforeSaveAction, ]; }
Model After save
The preferred way to hook into the after save is using the default Laravel events https://laravel.com/docs/eloquent#events. You can also hook into the Store action by adding a afterSave method that provides callables
public function afterSave() { return [ fn($resource, $model, $data) => $data['rand'] = rand(1, 99), function($resource, $model, $data) { return $data['rand'] = rand(1, 99); }, new MyCustomAfterSaveAction, ]; }
Field Before save
Whenever you need to change to way a field stores (creates or updates) it's data.
You can hook into the beforeStore
method.
Every field has this method.
Text::make('Name', 'name') ->beforeStore(function($value) { // ... Mutate the fields value to any given format. return $value; });
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.