| Install | |
|---|---|
composer require mark-villudo/laravel-admin-panel-inertia-vue |
|
| PHP: | ^8.2 |
Laravel package to create laravel admin panel using inertia vue
Require this package with composer.
composer require "mark-villudo/laravel-admin-panel-inertia-vue @dev"
Register Service Provider in bootstrap/providers.php
MarkVilludo\AdminPanelInertiaVue\CMSServicedProvider::class,
php artisan optimize
resources/assets and resources/js/Layouts php artisan vendor:publish --tag=cms-assets
#This command installs Jetstream with server-side rendering support for Inertia.js, enhancing performance and SEO.
php artisan jetstream:install inertia --ssr
#This command runs all pending database migrations, creating the necessary tables and columns in the database.
php artisan migrate
Open the resources/js/app.js to import the assets and add following VueSweetalert2, VueTippy and Toastr for dependencies
import './bootstrap';
import '@assets/css/bootstrap/bootstrap.min.css';
import '@assets/css/app.css';
import '@resources/css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
import VueSweetalert2 from 'vue-sweetalert2';
import 'sweetalert2/dist/sweetalert2.min.css';
import { plugin as VueTippy } from 'vue-tippy';
import 'tippy.js/dist/tippy.css';
// Toastr initialization
import toastr from 'toastr';
import 'toastr/build/toastr.css';
// Toastr does not have an install method, you might need to configure it differently.
toastr.options = {
closeButton: true,
progressBar: true,
positionClass: 'toast-top-right',
showDuration: '300',
hideDuration: '1000',
timeOut: '5000',
extendedTimeOut: '1000',
showEasing: 'swing',
hideEasing: 'linear',
showMethod: 'fadeIn',
hideMethod: 'fadeOut'
};
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, App, props, plugin }) {
const app = createApp({ render: () => h(App, props) });
app.use(plugin);
app.use(ZiggyVue);
app.use(VueSweetalert2); //additional
app.use(VueTippy); //additional
// Toastr does not have an install method. It should be configured globally.
app.config.globalProperties.$toastr = toastr;
app.mount(el);
return app;
},
progress: {
color: '#4B5563',
},
});
update package.json for toast in devDependencies block, and dependencies block for lodash, vue-sweetalert2 and vue-tippy
"devDependencies": {
"toastr": "^2.1.4",
},
"dependencies": {
"lodash": "^4.17.21",
"vue-sweetalert2": "^5.0.11",
"vue-tippy": "^6.4.1"
}
update vite.config.js and add/update the ff code
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
//additional
import vue from "@vitejs/plugin-vue";
import path from "path";
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
//additionals
vue(),
],
//additionals
resolve: {
alias: {
"@resources": path.resolve(__dirname, "resources"),
"@assets": path.resolve(__dirname, "resources/assets"),
"@public": path.resolve(__dirname, "public/assets"),
"@mixins": path.resolve(__dirname, "resources/js/Pages/Mixins"),
},
},
build: {
rollupOptions: {
output: {
assetFileNames: 'assets/[name]-[hash].[ext]',
},
},
},
});
Update the resources/js/Layouts/AppLayout.vue
<template>
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<SidebarLayout />
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<HeaderLayout :page_title="page_title" :page_icon="page_icon" />
<!-- End of Topbar -->
<!-- Begin Page Content -->
<slot />
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white shadow">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright © IMSupport 2024</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
</template>
<script>
import HeaderLayout from "./HeaderLayout.vue";
import SidebarLayout from "./SidebarLayout.vue";
export default {
props: {
page_title: String,
page_icon: String
},
components: {
HeaderLayout,
SidebarLayout,
},
};
</script>
Add css and js dependency in resources/views/app.blade.php
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
</head>
<body class="font-sans antialiased">
@inertia
<!-- additionals -->
@vite('resources/assets/js/jquery-3.7.1.min.js')
@vite('resources/assets/js/bootstrap/bootstrap.bundle.min.js')
@vite('resources/assets/js/bootstrap/main.js')
</body>
Open the resources/js/Pages/Dashboard.vue and update the AppLayout
from
<AppLayout title="Dashboard">
to
<AppLayout page_title="Dashboard" page_icon="fas fa-layer-group">
Run commands
npm install //This command installs all dependencies listed in the package.json file of your project.
npm run dev //runs a development server or build process specific to your project setup.
php artisan optimize //clear cache
php artisan serve //serve laravel application
Test it.

Publish all files from Spatie Service Provider
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
Then publish all files from our package for User Management
php artisan vendor:publish --tag=cms-usermanagement
Then run this command to clear cache for routes and others
php artisan optimize:clear
Include this in routes/web.php
// Include user management routes/web.php
include __DIR__.'/usermanagement.php';
Update the Models/User.php, add this following code for spatie and guard name
use Spatie\Permission\Traits\HasRoles;
use HasRoles;
public $guard_name = 'sanctum';
Then add this to database/DatabaseSeeder
$this->call(PermissionSeeder::class);
$this->call(RoleSeeder::class);
$this->call(UserSeeder::class);
Run migrate refresh and seed initial user, role, and permissions data
php artisan optimize:clear
php artisan migrate:fresh
php artisan db:seed
Update the app\Http\Middleware\HandleInertiaRequests.php
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'user.permissions' => function () use ($request) {
return ( $request->user() ? $request->user()->getAllPermissions()->pluck('name') : null );
},
'user.roles' => function () use ($request) {
return ( $request->user() ? $request->user()->roles()->pluck('name') : null );
},
'user.locale' => function () use ($request) {
return session('locale');
},
]);
}
Update the Resources/js/Pages/SidebarLayouts.vue to include the Users, Roles, and Permissions Module
<li class="nav-item" :class="{ 'active': ['user-management.index'].includes($page.component) }"
v-if="$page.props.user.permissions.includes('user_management')">
<Link class="nav-link" :href="'/user-management'">
<i class="fas fa-layer-group"></i>
<span>User Management</span></Link>
</li>
<li class="nav-item" :class="{ 'active': ['roles.index'].includes($page.component) }"
v-if="$page.props.user.permissions.includes('roles')">
<Link class="nav-link" :href="'/admin/dashboard'">
<i class="fas fa-layer-group"></i>
<span>Roles</span></Link>
</li>
<li class="nav-item" :class="{ 'active': ['permissions.index'].includes($page.component) }"
v-if="$page.props.user.permissions.includes('permissions')">
<Link class="nav-link" :href="'/admin/dashboard'">
<i class="fas fa-layer-group"></i>
<span>Permissions</span></Link>
</li>
Test it.
The MIT License (MIT). Please see License File for more information.