From 47b0beb0d03735e743dd769e5b1433810e49dafc Mon Sep 17 00:00:00 2001 From: ilhm344 <117576293+ilhm344@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:58:37 +0500 Subject: [PATCH] added translation of advanced folder --- .../en/advanced/authentication.blade.php | 124 ++++++ .../pages/en/advanced/authorization.blade.php | 142 +++++++ .../pages/en/advanced/commands.blade.php | 315 ++++++++++++++ .../pages/en/advanced/controller.blade.php | 136 ++++++ .../pages/en/advanced/form_builder.blade.php | 301 +++++++++++++ .../views/pages/en/advanced/helpers.blade.php | 80 ++++ .../pages/en/advanced/localization.blade.php | 8 + .../views/pages/en/advanced/menu.blade.php | 252 +++++++++++ .../pages/en/advanced/notifications.blade.php | 25 ++ .../pages/en/advanced/socialite.blade.php | 34 ++ .../pages/en/advanced/table_builder.blade.php | 398 ++++++++++++++++++ .../pages/en/advanced/type_casts.blade.php | 88 ++++ .../pages/ru/advanced/authorization.blade.php | 2 +- 13 files changed, 1904 insertions(+), 1 deletion(-) create mode 100644 resources/views/pages/en/advanced/authentication.blade.php create mode 100644 resources/views/pages/en/advanced/authorization.blade.php create mode 100644 resources/views/pages/en/advanced/commands.blade.php create mode 100644 resources/views/pages/en/advanced/controller.blade.php create mode 100644 resources/views/pages/en/advanced/form_builder.blade.php create mode 100644 resources/views/pages/en/advanced/helpers.blade.php create mode 100644 resources/views/pages/en/advanced/localization.blade.php create mode 100644 resources/views/pages/en/advanced/menu.blade.php create mode 100644 resources/views/pages/en/advanced/notifications.blade.php create mode 100644 resources/views/pages/en/advanced/socialite.blade.php create mode 100644 resources/views/pages/en/advanced/table_builder.blade.php create mode 100644 resources/views/pages/en/advanced/type_casts.blade.php diff --git a/resources/views/pages/en/advanced/authentication.blade.php b/resources/views/pages/en/advanced/authentication.blade.php new file mode 100644 index 00000000..b427b67f --- /dev/null +++ b/resources/views/pages/en/advanced/authentication.blade.php @@ -0,0 +1,124 @@ + + +Basics + + + The MoonShine admin panel has an authentication system. By default it is enabled + but if you need to allow access for all users, + then it can be disabled in the configuration file config/moonshine.php. + + + +return [ + // ... + 'auth' => [ + 'enable' => true, // [tl! focus] + // ... + ], + // ... +]; + + + + + +Empowerment + + + If you use your own guard, provider, then they can be overridden in the configuration, + as well as the MoonshineUser model. + + + +return [ + // ... + 'auth' => [ + // ... + 'middleware' => Authenticate::class, // [tl! focus:start] + 'guard' => 'moonshine', + 'guards' => [ + 'moonshine' => [ + 'driver' => 'session', + 'provider' => 'moonshine', + ], + ], + 'providers' => [ + 'moonshine' => [ + 'driver' => 'eloquent', + 'model' => MoonshineUser::class, + ], + ], // [tl! focus:end] + // ... + ], + // ... +]; + + +Login form + + + You can completely replace the login form with your own, just replace the class in the config with yours, + and inside implement FormBuilder + + + +return [ + // ... + 'forms' => [ + 'login' => LoginForm::class + ], + // ... +]; + + +Profile + + + You can completely replace the profile page with your own, just replace the page class in the config with yours + + + +return [ + // ... + 'pages' => [ + // ... + 'profile' => ProfilePage::class + ], + // ... +]; + + + + You can override profile fields in the configuration file config/moonshine.php. + + + +return [ + // ... + 'auth' => [ + 'enable' => true, + 'fields' => [ // [tl! focus:start] + 'username' => 'email', + 'password' => 'password', + 'name' => 'name', + 'avatar' => 'avatar' + ], // [tl! focus:end] + 'guard' => 'moonshine', + // ... + ], + // ... +]; + + + + If you don't want to use an avatar, + then specify 'avatar'=>'' or 'avatar'=>false. + + diff --git a/resources/views/pages/en/advanced/authorization.blade.php b/resources/views/pages/en/advanced/authorization.blade.php new file mode 100644 index 00000000..6e1fa16c --- /dev/null +++ b/resources/views/pages/en/advanced/authorization.blade.php @@ -0,0 +1,142 @@ + + +Basics + + + The MoonShine admin panel does not depart from Laravel concepts + and also using Laravel policy can work with access rights. + + + + In MoonShine resource controllers, each method will be checked for permissions. + If you have any difficulties, check out the official documentation + Laravel. + + + + By default, permissions checking is disabled for resources. To enable, you need to add the property + withPolicy. + + + +namespace App\MoonShine\Resources; + +use App\Models\Post; +use MoonShine\Resources\ModelResource; + +class PostResource extends ModelResource +{ + protected string $model = Post::class; + + protected bool $withPolicy = true; // [tl! focus] + + //... +} + + + + To create a Policy with an admin panel user binding, you can use the console command: + + + + php artisan moonshine:policy + + + + Available Policy methods: + + + + +namespace App\Policies; + +use Illuminate\Auth\Access\HandlesAuthorization; +use App\Models\Post; +use MoonShine\Models\MoonshineUser; + +class PostPolicy +{ + use HandlesAuthorization; + + public function viewAny(MoonshineUser $user) // [tl! focus] + { + return true; + } + + public function view(MoonshineUser $user, Post $item) // [tl! focus] + { + return true; + } + + public function create(MoonshineUser $user) // [tl! focus] + { + return true; + } + + public function update(MoonshineUser $user, Post $item) // [tl! focus] + { + return true; + } + + public function delete(MoonshineUser $user, Post $item) // [tl! focus] + { + return true; + } + + public function restore(MoonshineUser $user, Post $item) // [tl! focus] + { + return true; + } + + public function forceDelete(MoonshineUser $user, Post $item) // [tl! focus] + { + return true; + } + + public function massDelete(MoonshineUser $user) // [tl! focus] + { + return true; + } +} + + +Additional logic + + + If you need to add additional authorization logic to your application or external package, + then use the defineAuthorization method in the AuthServiceProvider. + + + +use Illuminate\Database\Eloquent\Model; +use MoonShine\Contracts\Resources\ResourceContract; +use MoonShine\MoonShine; + +public function boot(): void +{ + MoonShine::defineAuthorization( + static function (ResourceContract $resource, Model $user, string $ability): bool { + return true; + } + ); // [tl! focus:-4] +} + + + diff --git a/resources/views/pages/en/advanced/commands.blade.php b/resources/views/pages/en/advanced/commands.blade.php new file mode 100644 index 00000000..cce3b294 --- /dev/null +++ b/resources/views/pages/en/advanced/commands.blade.php @@ -0,0 +1,315 @@ + + +Install + + + Command to install the MoonShine package in your Laravel project: + + + + php artisan moonshine:install + + + + Available options: + + + + + + For more detailed information, please refer to the section + Installation. + + +Apply + + + The command to create the apply class is: + + + + php artisan moonshine:apply + + + + After executing the command, a file will be created in the app/MoonShine/Applies directory. + The created class must be registered with the service provider. + + +Component + + + The command creates a custom component: + + + + php artisan moonshine:component + + + + After executing the command, a class for the component will be created in the app/MoonShine/Components directory + and Blade file in the resources/views/admin/components directory. + + + + For more detailed information, please refer to the section + Components. + + +Controller + + + Command to create a controller: + + + + php artisan moonshine:controller + + + + After executing the command, a controller class will be created in the app/MoonShine/Controllers directory. + Which can be used in admin panel routes. + + + + For more detailed information, please refer to the section + Controllers. + + +Field + + + The command allows you to create a custom field: + + + + php artisan moonshine:field + + + + When executing the command, you can specify whether the field will extend the base class or another field. + + + + After executing the command, a field class will be created in the app/MoonShine/Fields directory + and Blade file in the directory /resources/views/admin/fields. + + + + For more detailed information, please refer to the section + Fields. + + +Handler + + + The command creates a Handler class for its import and export implementations: + + + + php artisan moonshine:handler + + + + After executing the command, the handler class will be created in the directory app/MoonShine/Handlers. + + + + For more detailed information, please refer to the section + Import/Export. + + +Page + + + The command creates a page for the admin panel: + + + + php artisan moonshine:page + + + + Available options: + + + + + + After executing the command, a default page (or group of pages) will be created in the directory + app/MoonShine/Pages. + + + + For more detailed information, please refer to the section + Page. + + +Policy + + + The command creates a Policy bound to the admin panel user: + + + + php artisan moonshine:policy + + + + After executing the command, a class will be created in the app/Policies directory. + + + + For more detailed information, please refer to the section + Authorization. + + +Resource + + + Command to create resources: + + + + php artisan moonshine:resource + + + + Available options: + + + + + + There are several options available when creating a Resource: + + + + + After executing the command, a resource file will be created in the app/MoonShine/Resources/ directory.
+ If a model resource with pages is created, additional pages will be created in the directory + app/MoonShine/Pages. +
+ + + For more detailed information, please refer to the section + Models Resources. + + +Type Cast + + + The command creates a TypeCast class for working with data: + + + + php artisan moonshine:type-cast + + + + After executing the command, a file will be created in the app/MoonShine/TypeCasts directory. + + + + For more detailed information, please refer to the section + TypeCasts. + + +User + + + The command that allows you to create a super user: + + + + php artisan moonshine:user + + + + Available options: + + + + +Publish + + + Posting team: + + + + php artisan moonshine:publish + + + + There are several options available for publishing: + + + +
diff --git a/resources/views/pages/en/advanced/controller.blade.php b/resources/views/pages/en/advanced/controller.blade.php new file mode 100644 index 00000000..b91d864b --- /dev/null +++ b/resources/views/pages/en/advanced/controller.blade.php @@ -0,0 +1,136 @@ + + + MoonShine allows you to work in a familiar manner using controllers + + + + We provide you with our basic controller, which helps you conveniently work with the UI and + render your views with MoonShine layout + + + + Useful for displaying your complex solutions or writing additional handlers + + +Generate controller + + +php artisan moonshine:controller + + +Show blade view + + +namespace App\MoonShine\Controllers; + +use MoonShine\MoonShineRequest; +use MoonShine\Http\Controllers\MoonshineController; +use Symfony\Component\HttpFoundation\Response; + +final class CustomViewController extends MoonshineController +{ + public function __invoke(MoonShineRequest $request): Response + { + return $this + ->view('path_to_blade', ['param' => 'value']) + //->setLayout('custom_layout') + ->render(); + } +} + + +Display page + + +namespace App\MoonShine\Controllers; + +use MoonShine\MoonShineRequest; +use MoonShine\Http\Controllers\MoonshineController; +use MoonShine\Pages\Page; + +final class CustomViewController extends MoonshineController +{ + public function __invoke(MoonShineRequest $request): Page + { + return MyPage::make(); + } +} + + +Show notification + + +namespace App\MoonShine\Controllers; + +use MoonShine\MoonShineRequest; +use MoonShine\Http\Controllers\MoonshineController; +use Symfony\Component\HttpFoundation\Response; + +final class CustomViewController extends MoonshineController +{ + public function __invoke(MoonShineRequest $request): Response + { + $this->toast('Hello world'); + + return back(); + } +} + + +Send notification + + +namespace App\MoonShine\Controllers; + +use MoonShine\MoonShineRequest; +use MoonShine\Http\Controllers\MoonshineController; +use Symfony\Component\HttpFoundation\Response; + +final class CustomViewController extends MoonshineController +{ + public function __invoke(MoonShineRequest $request): Response + { + $this->notification('Message'); + + return back(); + } +} + + +Access a page or resource + + +namespace App\MoonShine\Controllers; + +use MoonShine\MoonShineRequest; +use MoonShine\Http\Controllers\MoonshineController; +use Symfony\Component\HttpFoundation\Response; + +final class CustomViewController extends MoonshineController +{ + public function __invoke(MoonShineRequest $request): Response + { + // $request->getPage(); + // $request->getResource(); + } +} + + +Json response + + +namespace App\MoonShine\Controllers; + +use MoonShine\MoonShineRequest; +use MoonShine\Http\Controllers\MoonshineController; +use Symfony\Component\HttpFoundation\Response; + +final class CustomViewController extends MoonshineController +{ + public function __invoke(MoonShineRequest $request): Response + { + return $this->json(message: 'Message', data: [], redirect: null); + } +} + + diff --git a/resources/views/pages/en/advanced/form_builder.blade.php b/resources/views/pages/en/advanced/form_builder.blade.php new file mode 100644 index 00000000..c4acf44c --- /dev/null +++ b/resources/views/pages/en/advanced/form_builder.blade.php @@ -0,0 +1,301 @@ +@php use MoonShine\Fields\Text; @endphp + + +Basics + + + Fields and decorations in MoonShine are used inside forms, which are handled by FormBuilder. + Thanks to FormBuilder, fields are displayed and filled with data. + You can also use FormBuilder on your own pages or even outside of MoonShine. + + + +make( + string $action = '', + string $method = 'POST', + Fields|array $fields = [], + array $values = [] +) + + + + + +FormBuilder::make('/crud/update', 'PUT') + ->fields([ + Text::make('Text') + ]) + ->fill(['text' => 'Value']) + + + + Same thing through methods: + + + +FormBuilder::make() + ->action('/crud/update') + ->method('PUT') + ->fields([ + Text::make('Text') + ]) + ->fill(['text' => 'Value']) + + + + Helper is also available: + + + +@{!! form(request()->url(), 'GET') + ->fields([ + Text::make('Text') + ]) + ->fill(['text' => 'Value']) +!!} + + +{!! + form(request()->url(), 'GET') + ->fields([ + Text::make('Text') + ]) + ->fill(['text' => 'Value']) +!!} + + +Methods + + + + + The fields method for declaring form fields and decorations: + + + +FormBuilder::make('/crud/update', 'PUT') + ->fields([ + Heading::make('Title'), + Text::make('Text'), + ]) + + + + + + fill method for filling fields with values: + + + +FormBuilder::make('/crud/update', 'PUT') + ->fields([ + Heading::make('Title'), + Text::make('Text'), + ]) + ->fill(['text' => 'value']) + + + + + + The cast method for casting form values to a specific type. + Since by default fields work with primitive types: + + + +use MoonShine\TypeCasts\ModelCast; + +FormBuilder::make('/crud/update', 'PUT') + ->fields([ + Heading::make('Title'), + Text::make('Text'), + ]) + ->fillCast(['text' => 'value'], ModelCast::make(User::class)) + + + + use MoonShine\TypeCasts\ModelCast; + + FormBuilder::make('/crud/update', 'PUT') + ->fields([ + Heading::make('Title'), + Text::make('Text'), + ]) + ->fillCast(User::query()->first(), ModelCast::make(User::class)) + + + + In this example, we cast the data to the User model format using ModelCast. + + + + + Read more about TypeCasts in the section of the same name + + + + + + + Form buttons can be modified and added. + + + + To customize the "submit" button, use the submit method + + + +FormBuilder::make('/crud/update', 'PUT') + ->submit(label: 'Click me', attributes: ['class' => 'btn-primary']) + + + + To add new buttons based on ActionButton, use the buttons method + + + +FormBuilder::make('/crud/update', 'PUT') + ->buttons([ + ActionButton::make('Delete', route('name.delete')) + ]) + + + + + + You can set any html attributes for the form using the customAttributes method. + + + +FormBuilder::make()->customAttributes(['class' => 'custom-form']), + + +Asynchronous mode + + + If you need to submit the form asynchronously, use the async method. + + + +FormBuilder::make('/crud/update', 'PUT') + ->async() + + + + After a successful request, you can raise events by adding the asyncEvents parameter. + + + + FormBuilder::make('/crud/update', 'PUT') + ->name('main-form') + ->async(asyncEvents: ['table-updated-crud', 'form-reset-main-form']) + + + + MoonShine already has a set of ready-made events + + +
    +
  • table-updated-{name} - Updating an asynchronous table by its name
  • +
  • form-reset-{name} - Reset form values by its name
  • +
  • fragment-updated-{name} - Updates a blade fragment by its name
  • +
+ + + If you need to perform precognition validation first, you need the precognitive method. + + + +FormBuilder::make('/crud/update', 'PUT') + ->precognitive() + + +@include('recipes.form-with-events') + +Apply + + + The apply() method in FormBuilder iterates through all form fields and calls their apply methods. + + + +apply( + Closure $apply, + ?Closure $default = null, + ?Closure $before = null, + ?Closure $after = null, + bool $throw = false, +) + + +
    +
  • $apply - callback function;
  • +
  • $default - apply for the default field;
  • +
  • $before - callback function before apply;
  • +
  • $after - callback function after apply;
  • +
  • $throw - throw exceptions.
  • +
+ + + + + It is necessary to save the data of all FormBuilder fields in the controller: + + + +$form->apply(fn(Model $item) => $item->save()); + + + + A more complex option, indicating events before and after saving: + + + +$form->apply( + static fn(Model $item) => $item->save(), + before: function (Model $item) { + if (! $item->exists) { + $item = $this->beforeCreating($item); + } + + if ($item->exists) { + $item = $this->beforeUpdating($item); + } + + return $item; + }, + after: function (Model $item) { + $wasRecentlyCreated = $item->wasRecentlyCreated; + + $item->save(); + + if ($wasRecentlyCreated) { + $item = $this->afterCreated($item); + } + + if (! $wasRecentlyCreated) { + $item = $this->afterUpdated($item); + } + + return $item; + }, + throw: true +); + + +
diff --git a/resources/views/pages/en/advanced/helpers.blade.php b/resources/views/pages/en/advanced/helpers.blade.php new file mode 100644 index 00000000..4c3fae87 --- /dev/null +++ b/resources/views/pages/en/advanced/helpers.blade.php @@ -0,0 +1,80 @@ + +Basic + + +moonshine() // MoonShine instance +moonshineRegister() // To register apply classes +moonshineRequest() // With access to resource, pages, posts and components +moonshineAssets() // Working with assets (MoonShineAssets instance) +moonshineMenu() // Get menu list +moonshineLayout() // Render template contents + + +Link to page to_page + + + $page - Page or page alias (Optional)
+ $resource - Resource or resource alias (Optional)
+ $params - Additional query
+ $redirect - If necessary, perform a redirect immediately
+ $fragment - URL will be used for Fragment loading +
+ + +to_page(page: 'form-page'); +to_page(page: IndexPage::class); +to_page(page: IndexPage::class, resource: PostResource::class); +to_page(page: new IndexPage(), resource: new PostResource()); +to_page(page: 'form-page', redirect: true); +to_page(page: 'form-page', fragment: true); + + +FormBuilder + + +form( + string $action = '', + string $method = 'POST', + Fields|array $fields = [], + array $values = [] +) + + +TableBuilder + + +form( + Fields|array $fields = [], + iterable $items = [], + ?LengthAwarePaginator $paginator = null +) + + +TableBuilder + + +actionBtn( + Closure|string $label, + Closure|string|null $url = null, + mixed $item = null +) + + +Find apply field (filter) class + + +findFieldApply( + Field $field, + string $type, + string $for +); + +findFieldApply($field, 'filters', ModelResource::class); + + +Display 404 + + +oops404() + +
diff --git a/resources/views/pages/en/advanced/localization.blade.php b/resources/views/pages/en/advanced/localization.blade.php new file mode 100644 index 00000000..97b1f6b6 --- /dev/null +++ b/resources/views/pages/en/advanced/localization.blade.php @@ -0,0 +1,8 @@ + + + + After installing MoonShine, a directory with translations will also appear in the directory with translations + MoonShine, where you can add support for a new language or change current ones. + + + diff --git a/resources/views/pages/en/advanced/menu.blade.php b/resources/views/pages/en/advanced/menu.blade.php new file mode 100644 index 00000000..cc064f1d --- /dev/null +++ b/resources/views/pages/en/advanced/menu.blade.php @@ -0,0 +1,252 @@ + + +Registration + + + In the resource study section, we have already figured out how to register sections of the admin panel, + after which they also appear in the menu. + + + +namespace App\Providers; + +use Illuminate\Support\ServiceProvider; +use MoonShine\Menu\MenuItem; // [tl! focus] +use MoonShine\MoonShine; // [tl! focus] +use MoonShine\Resources\MoonShineUserResource; +use MoonShine\Resources\MoonShineUserRoleResource; + +class MoonShineServiceProvider extends ServiceProvider +{ + //... + + public function boot() + { + app(MoonShine::class)->menu([ // [tl! focus:start] + MenuItem::make('Admins', new MoonShineUserResource()), + MenuItem::make('Roles', new MoonShineUserRoleResource()), + ]); // [tl! focus:end] + } +} + + + + But for the convenience of the interface, we can also group menu items. + + + +namespace App\Providers; + +use Illuminate\Support\ServiceProvider; +use MoonShine\Menu\MenuItem; +use MoonShine\Menu\MenuGroup; // [tl! focus] +use MoonShine\MoonShine; +use MoonShine\Resources\MoonShineUserResource; +use MoonShine\Resources\MoonShineUserRoleResource; + +class MoonShineServiceProvider extends ServiceProvider +{ + //... + + public function boot() + { + app(MoonShine::class)->menu([ + MenuGroup::make('System', [ // [tl! focus] + MenuItem::make('Admins', new MoonShineUserResource()), + MenuItem::make('Roles', new MoonShineUserRoleResource()), + ]) // [tl! focus] + ]); + } +} + + + + You just need to add resources as the second parameter to the MoonShine\Menu\MenuGroup class. + Well, the first parameter is the name of the group! + + + + + +Display condition + + + Display menus based on condition. + + + +//... +app(MoonShine::class)->menu([ + MenuGroup::make('System', [ + MenuItem::make('Admins', new MoonShineUserResource()), + MenuItem::make('Roles', new MoonShineUserRoleResource()), + ])->canSee(function(Request $request) { // [tl! focus:start] + return $request->user('moonshine')?->id === 1; + }) // [tl! focus:end] +]); +//... + + +External reference + + + Ability to add a custom link: + + + +//... +app(MoonShine::class)->menu([ + MenuItem::make('Laravel Documentation', 'https://laravel.com') // [tl! focus] +]); +//... + + + + Links can be passed through the function. + + + +//... +app(MoonShine::class)->menu([ + MenuItem::make('Admins', function () { // [tl! focus:start] + return (new MoonShineUserResource())->route('index'); + }), + MenuItem::make('Home', fn() => route('home')) // [tl! focus:end] +]); +//... + + +Icon + + + It is also possible to change the icon of a menu item. + + + +//... +app(MoonShine::class)->menu([ + MenuGroup::make('System', [ // [tl! focus:start] + MenuItem::make('Admins', new MoonShineUserResource())->icon('heroicons.hashtag'), + MenuItem::make('Roles', new MoonShineUserRoleResource())->icon('heroicons.hashtag'), + ])->icon('app') // [tl! focus:end] + // or + MenuGroup::make('Blog', [ // [tl! focus:start] + MenuItem::make('Comments', new CommentResource(), 'heroicons.chat-bubble-left') + ], 'heroicons.newspaper') // [tl! focus:end] +]); +//... + + + + For more detailed information, please refer to the section Icons. + + +Label + + + It is also possible to add a counter to a menu item. + + + +//... +app(MoonShine::class)->menu([ + MenuItem::make('Comments', new CommentResource()) + ->badge(fn() => Comment::query()->count()), // [tl! focus] +]); +//... + + + + + +Translation + + + To translate menu items, you need to pass the translation key as the name + and add the translatable() method. + + + +//... +app(MoonShine::class)->menu([ + MenuItem::make('menu.Comments', new CommentResource()) + ->translatable() // [tl! focus] + // or + MenuItem::make('Comments', new CommentResource()) + ->translatable('menu') // [tl! focus] +]); +//... + + + +// lang/ru/menu.php + +return [ + 'Comments' => 'Comments', +]; + + + + You can use Laravel's translation tools to translate menu labels. + + + +//... +app(MoonShine::class)->menu([ + MenuItem::make('Comments', new CommentResource()) + ->badge(fn() => __('menu.badge.new')) // [tl! focus] +]); +//... + + +Delimiter + + + Menu items can be visually divided using MenuDivider + + + +use MoonShine\Menu\MenuDivider; // [tl! focus] + +//... +app(MoonShine::class)->menu([ + MenuItem::make('Categories', new CategoryResource()), + MenuDivider::make(), // [tl! focus] + MenuItem::make('Articles', new ArticleResource()), +]); +//... + + + + + + + You can use text as a separator. To do this, you need to pass it to the make() method. + + + +use MoonShine\Menu\MenuDivider; // [tl! focus] + +//... +app(MoonShine::class)->menu([ + MenuItem::make('Categories', new CategoryResource()), + MenuDivider::make('Divider'), // [tl! focus] + MenuItem::make('Articles', new ArticleResource()), +]); +//... + + + + + + diff --git a/resources/views/pages/en/advanced/notifications.blade.php b/resources/views/pages/en/advanced/notifications.blade.php new file mode 100644 index 00000000..f17aa5b2 --- /dev/null +++ b/resources/views/pages/en/advanced/notifications.blade.php @@ -0,0 +1,25 @@ + + + + If there is a need to add notifications to the MoonShine notification center, then + use the MoonShine\Notifications\MoonShineNotification class. + + + +use MoonShine\Notifications\MoonShineNotification; + +MoonShineNotification::send( + message: 'Notification message', + // Optional button + button: ['link' => 'https://moonshine.cutcode.dev', 'label' => 'Click me'], + // Optional id of administrators (default to all) + ids: [1,2,3], + // Optional icon color (purple, pink, blue, green, yellow, red, gray) + color: 'green' +); + + + + + + diff --git a/resources/views/pages/en/advanced/socialite.blade.php b/resources/views/pages/en/advanced/socialite.blade.php new file mode 100644 index 00000000..29757f9a --- /dev/null +++ b/resources/views/pages/en/advanced/socialite.blade.php @@ -0,0 +1,34 @@ + + + + For convenience, you can link your account to social networks and simplify the authentication process. + + + + This functionality is based on the Laravel Socialite package. + + + + Make sure you have it installed and configured. + + + + Next, in the MoonShine config config/moonshine.php install the available drivers (you should already have them configured) and the image for the button + + + +return [ + // + 'socialite' => [ + 'github' => '/images/github.png', + 'facebook' => '/images/facebook.svg' + ] + // +]; + + + + If you use your model for authentication, then you need to add the HasMoonShineSocialite trait to it. + + + diff --git a/resources/views/pages/en/advanced/table_builder.blade.php b/resources/views/pages/en/advanced/table_builder.blade.php new file mode 100644 index 00000000..87db7879 --- /dev/null +++ b/resources/views/pages/en/advanced/table_builder.blade.php @@ -0,0 +1,398 @@ +@php use MoonShine\Fields\Text; @endphp + + +Basics + + + Fields and decorations in MoonShine are used inside tables in preview mode. TableBuilder is responsible for tables. + Using TableBuilder, tables are displayed and filled with data. + You can also use TableBuilder on your own pages or even outside of MoonShine. + + + +make( + Fields|array $fields = [], + protected iterable $items = [], + protected ?Paginator $paginator = null +) + + + + + +TableBuilder::make([Text::make('Text')], [['text' => 'Value']]) + + + + Same thing through methods: + + + +TableBuilder::make() + ->fields([ + Text::make('Text') + ]) + ->items([['text' => 'Value']]) + + + + Helper is also available: + + + +@{!! table() + ->fields([ + Text::make('Text') + ]) + ->items([ + ['text' => 'Value'] + ]) +!!} + + +{!! + table() + ->fields([ + Text::make('Text') + ]) + ->items([ + ['text' => 'Value'] + ]) +!!} + +Methods + + + + + The fields method for declaring fields: + + + +TableBuilder::make() + ->fields([ + Text::make('Text'), + ]) + + + + + + items method for filling the table with data: + + + +TableBuilder::make() + ->fields([ + Text::make('Text'), + ]) + ->items([['text' => 'Value']]) + + + + The paginator method for the table to work with pagination: + + + +$paginator = Article::paginate(); + +TableBuilder::make() + ->fields([ + Text::make('Text'), + ]) + ->items($paginator->items()) + ->paginator($paginator) + +// or simple + +TableBuilder::make(items: Article::paginate()) + ->fields([ + Text::make('Text'), + ]) + + + + + + The cast method for casting table values to a specific type. + Since by default fields work with primitive types: + + + +use MoonShine\TypeCasts\ModelCast; + +TableBuilder::make(items: User::paginate()) + ->fields([ + Text::make('Email'), + ]) + ->cast(ModelCast::make(User::class)) + + + + In this example, we cast the data to the User model format using ModelCast. + + + + + Read more about TypeCasts in the section of the same name. + + + + + + To add new buttons based on ActionButton, use the buttons method. + Buttons will be added for each row, and when bulk mode is enabled, they will be displayed in the footer for bulk actions: + + + +TableBuilder::make(items: Article::paginate()) + ->fields([ID::make(), Switcher::make('Active')]) + ->cast(ModelCast::make(Article::class)) + ->buttons([ + ActionButton::make('Delete', route('name.delete')), + ActionButton::make('Edit', route('name.edit'))->showInDropdown(), + ActionButton::make('Go to home', route('home'))->blank()->canSee(fn($data) => $data->active), + ActionButton::make('Mass Delete', route('name.mass_delete'))->bulk() + ]) + + + + + + If you need to receive data from the table asynchronously (during pagination, sorting), then use the async method: + + + +TableBuilder::make() + ->async('/async_url') + + + + + + You can set any html attributes for the table using the customAttributes method: + + + +TableBuilder::make()->customAttributes(['class' => 'custom-form']), + + + + You can set any html attributes for table rows and cells: + + + +TableBuilder::make()->trAttributes(function(mixed $data, int $row, ComponentAttributeBag $attributes): ComponentAttributeBag { + return $attributes->merge(['class' => 'bgc-green']); +}), + + +{!! + table() + ->simple() + ->fields([ + Text::make('Text') + ]) + ->items([ + ['text' => 'Value'] + ])->trAttributes(function(mixed $data, int $row, $attributes) { + return $attributes->merge(['class' => 'bgc-green']); + }) +!!} + + +TableBuilder::make()->tdAttributes(function(mixed $data, int $row, int $cell, ComponentAttributeBag $attributes): ComponentAttributeBag { + return $attributes->merge(['class' => 'bgc-red']); +}), + + +{!! + table() + ->simple() + ->fields([ + Text::make('Text') + ]) + ->items([ + ['text' => 'Value'] + ])->trAttributes(function(mixed $data, int $row, $attributes) { + return $attributes->merge(['class' => 'bgc-red']); + }) +!!} + + + + + By default, if the table has no data, it will be empty, but you can display the message “No records yet.” + To do this, use the withNotFound method: + + + +TableBuilder::make()->withNotFound(), + + +{!! + table() + ->fields([ + Text::make('Text') + ])->withNotFound() +!!} + + + + + By default, the table is styled as MoonShine, but using the simple method you can display the table in a simplified style: + + + +TableBuilder::make()->simple(), + + +{!! + table() + ->simple() + ->fields([ + Text::make('Text') + ])->items([['text' => 'Value']]) +!!} + + + + + The preview method disables the display of buttons and sorts for the table: + + + +TableBuilder::make()->preview(), + + + + + + Using the vertical method you can display the table in vertical mode: + + + +TableBuilder::make()->vertical(), + + +{!! + table() + //->vertical() broken in alpha3, all done in repo + ->fields([ + Text::make('Text'), + Text::make('Text 2') + ])->items([['text' => 'Value']]) +!!} + + + + + Using the creatable() method, you can create an "Add" button to generate new records in the table: + + + +TableBuilder::make()->creatable(), + + + + If the table contains fields in edit mode with a dynamic name, + then you need to add a method or parameter reindex: + + + + TableBuilder::make()->creatable(reindex: true), + // or + TableBuilder::make()->creatable()->reindex(), + + + + If you want to limit the number of records that can be added, you must specify the limit parameter: + + + + TableBuilder::make()->creatable(limit: 6), + + +{!! + table() + ->creatable() + ->fields([ + Text::make('Text'), + Text::make('Text 2') + ])->items([['text' => 'Value']]) +!!} + + + + + By default, fields in the table are displayed in preview() mode, + but if you want to display them as editable form elements, + then you need to use the editable() method: + + + +TableBuilder::make()->editable(), + + +{!! + table(items: [['text' => 'Value', 'field' => 'Value'], ['text' => '', 'field' => '']]) + ->creatable()->reindex()->editable() + ->fields([ + Text::make('Text'), + Text::make('Field') + ]) +!!} + + + + In append mode, the last element must be empty (the skeleton of the new entry): + + + + + + + To sort rows in a table, use the sortable() method: + + + +sortable( + ?string $url = null, + string $key = 'id', + ?string $group = null +) + + +
    +
  • url - url handler
  • +
  • key - element key
  • +
  • group - grouping.
  • +
+ + +TableBuilder::make() + ->sortable(url: '/update_indexes_endpoint', key: 'id', group: 'nested'), + + +{!! + table(items: [['text' => 'Value 1', 'field' => 'Value 1'], ['text' => 'Value 2', 'field' => 'Value 2']]) + ->sortable() + ->fields([ + Text::make('Text'), + Text::make('Field') + ]) +!!} + +
diff --git a/resources/views/pages/en/advanced/type_casts.blade.php b/resources/views/pages/en/advanced/type_casts.blade.php new file mode 100644 index 00000000..28fecfdb --- /dev/null +++ b/resources/views/pages/en/advanced/type_casts.blade.php @@ -0,0 +1,88 @@ +@php use MoonShine\Fields\Text; @endphp + + + + By default in MoonShine, fields operate on primitive types and do not know anything about models. + This was done so that the system was not tied only to models, and the fields could, depending on the situation + have access to both raw data and typed data + + + + TypeCast for models is already included in the MoonShine box, but if you need + work with another data type, you will need an object that implements the MoonShineDataCast interface + + + +namespace MoonShine\Contracts; + +interface MoonShineDataCast +{ + public function getClass(): string; + + public function hydrate(array $data): mixed; + + public function dehydrate(mixed $data): array; +} + + + + Let's take a look at the TypeCast example for models + + + +namespace MoonShine\TypeCasts; + +use Illuminate\Database\Eloquent\Model; +use MoonShine\Contracts\MoonShineDataCast; + +final class ModelCast implements MoonShineDataCast +{ + public function __construct( + protected string $class + ) { + } + + public function getClass(): string + { + return $this->class; + } + + public function hydrate(array $data): mixed + { + return (new ($this->getClass())($data)); + } + + public function dehydrate(mixed $data): array + { + return $data->attributesToArray(); + } +} + + + + Well, its application in FormBuilder/TableBuilder + + + +use MoonShine\TypeCasts\ModelCast; + +TableBuilder::make(items: User::paginate()) + ->fields([ + Text::make('Email'), + ]) + ->cast(ModelCast::make(User::class)) + + + +use MoonShine\TypeCasts\ModelCast; + +FormBuilder::make() + ->fields([ + Text::make('Email'), + ]) + ->fillCast(User::query()->first(), ModelCast::make(User::class)) + + + \ No newline at end of file diff --git a/resources/views/pages/ru/advanced/authorization.blade.php b/resources/views/pages/ru/advanced/authorization.blade.php index 1f407d9f..e5daf74e 100644 --- a/resources/views/pages/ru/advanced/authorization.blade.php +++ b/resources/views/pages/ru/advanced/authorization.blade.php @@ -17,7 +17,7 @@ В ресурс-контроллерах MoonShine каждый метод будет проверяться на наличие прав. - Если возникают трудности, то ознакомьтесь с официально документацией + Если возникают трудности, то ознакомьтесь с официальной документацией Laravel.