create user role and menu, create seeder for first user and create crud role, menu and user
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\ServiceSIMBG;
|
use App\Services\ServiceSIMBG;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use \Illuminate\Support\Facades\Log;
|
use \Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@@ -25,10 +25,16 @@ class ExecuteScraping extends Command
|
|||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
private $service_simbg;
|
||||||
|
|
||||||
|
public function __construct(ServiceSIMBG $service_simbg){
|
||||||
|
$this->service_simbg = $service_simbg;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
Log::info("running scheduler daily scraping");
|
Log::info("running scheduler daily scraping");
|
||||||
$service = new ServiceSIMBG();
|
$this->service_simbg->syncTaskList();
|
||||||
$service->syncTaskList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
app/Http/Controllers/Api/MenusController.php
Normal file
56
app/Http/Controllers/Api/MenusController.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Menu;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class MenusController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = Menu::query();
|
||||||
|
|
||||||
|
if($request->has("search") && !empty($request->get("search"))){
|
||||||
|
$query = $query->where("name", "like", "%".$request->get("search")."%");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($query->paginate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
56
app/Http/Controllers/Api/RolesController.php
Normal file
56
app/Http/Controllers/Api/RolesController.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Role;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class RolesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = Role::query();
|
||||||
|
|
||||||
|
if($request->has('search') && !empty($request->get('search'))){
|
||||||
|
$query = $query->where('name', 'like', '%'. $request->get('search') . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($query->paginate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,10 @@
|
|||||||
namespace App\Http\Controllers\Master;
|
namespace App\Http\Controllers\Master;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Role;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\Rules;
|
use Illuminate\Validation\Rules;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
@@ -22,7 +25,8 @@ class UsersController extends Controller
|
|||||||
return view('master.users.index', compact('users'));
|
return view('master.users.index', compact('users'));
|
||||||
}
|
}
|
||||||
public function create(){
|
public function create(){
|
||||||
return view('master.users.create');
|
$roles = Role::all();
|
||||||
|
return view('master.users.create', compact('roles'));
|
||||||
}
|
}
|
||||||
public function store(Request $request){
|
public function store(Request $request){
|
||||||
$request->validate([
|
$request->validate([
|
||||||
@@ -31,21 +35,29 @@ class UsersController extends Controller
|
|||||||
'password' => ['required', 'confirmed', 'max:255'],
|
'password' => ['required', 'confirmed', 'max:255'],
|
||||||
'firstname' => ['required', 'string', 'max:255'],
|
'firstname' => ['required', 'string', 'max:255'],
|
||||||
'lastname' => ['required', 'string', 'max:255'],
|
'lastname' => ['required', 'string', 'max:255'],
|
||||||
'position' => ['required', 'string', 'max:255']
|
'position' => ['required', 'string', 'max:255'],
|
||||||
|
'role_id' => 'required|exists:roles,id'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// dd($request);
|
DB::beginTransaction();
|
||||||
|
try{
|
||||||
|
$user = User::create([
|
||||||
|
'name' => $request->name,
|
||||||
|
'email' => $request->email,
|
||||||
|
'password' => Hash::make($request->password),
|
||||||
|
'firstname' => $request->firstname,
|
||||||
|
'lastname' => $request->lastname,
|
||||||
|
'position' => $request->position
|
||||||
|
]);
|
||||||
|
|
||||||
$user = User::create([
|
$user->roles()->attach($request->role_id);
|
||||||
'name' => $request->name,
|
|
||||||
'email' => $request->email,
|
|
||||||
'password' => Hash::make($request->password),
|
|
||||||
'firstname' => $request->firstname,
|
|
||||||
'lastname' => $request->lastname,
|
|
||||||
'position' => $request->position
|
|
||||||
]);
|
|
||||||
|
|
||||||
return redirect()->route('users.index')->with('success','Successfully registered');
|
DB::commit();
|
||||||
|
return redirect()->route('users.index')->with('success','Successfully registered');
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with("error", $e->getMessage());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
public function show($id){
|
public function show($id){
|
||||||
$user = User::find($id);
|
$user = User::find($id);
|
||||||
@@ -53,24 +65,40 @@ class UsersController extends Controller
|
|||||||
}
|
}
|
||||||
public function edit($id){
|
public function edit($id){
|
||||||
$user = User::find($id);
|
$user = User::find($id);
|
||||||
return view('master.users.edit', compact('user'));
|
$roles = Role::all();
|
||||||
|
return view('master.users.edit', compact('user', 'roles'));
|
||||||
}
|
}
|
||||||
public function update(Request $request, $id){
|
public function update(Request $request, $id){
|
||||||
$user = User::find($id);
|
$user = User::find($id);
|
||||||
$validate = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($id)],
|
||||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
|
||||||
'firstname' => ['required', 'string', 'max:255'],
|
'firstname' => ['required', 'string', 'max:255'],
|
||||||
'lastname' => ['required', 'string', 'max:255'],
|
'lastname' => ['required', 'string', 'max:255'],
|
||||||
'position' => ['required', 'string', 'max:255']
|
'position' => ['required', 'string', 'max:255'],
|
||||||
|
'role_id' => ['required', 'exists:roles,id'],
|
||||||
]);
|
]);
|
||||||
$user->update($validate);
|
try{
|
||||||
return redirect()->route('master.users')->with('success', 'Successfully');
|
DB::beginTransaction();
|
||||||
|
$updateData = [
|
||||||
|
'name' => $validatedData['name'],
|
||||||
|
'email' => $validatedData['email'],
|
||||||
|
'firstname' => $validatedData['firstname'],
|
||||||
|
'lastname' => $validatedData['lastname'],
|
||||||
|
'position' => $validatedData['position'],
|
||||||
|
];
|
||||||
|
$user->update($updateData);
|
||||||
|
$user->roles()->sync([$request->role_id]);
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->route('users.index')->with('success', 'Successfully');
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with("error", $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public function destroy($id){
|
public function destroy($id){
|
||||||
$user = User::find($id);
|
$user = User::find($id);
|
||||||
$user->delete();
|
$user->delete();
|
||||||
return redirect()->route('master.users')->with('success','Successfully deleted');
|
return redirect()->route('users.index')->with('success','Successfully deleted');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
136
app/Http/Controllers/MenusController.php
Normal file
136
app/Http/Controllers/MenusController.php
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Menu;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class MenusController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('menus.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$parent_menus = Menu::whereNull('parent_id')->get();
|
||||||
|
return view("menus.create", compact('parent_menus'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$request->validate([
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'url' => 'nullable|string|max:255',
|
||||||
|
'icon' => 'nullable|string|max:255',
|
||||||
|
'parent_id' => 'nullable|exists:menus,id', // Ensures it's either null or a valid menu ID
|
||||||
|
'sort_order' => 'required|integer',
|
||||||
|
]);
|
||||||
|
DB::beginTransaction();
|
||||||
|
Menu::create([
|
||||||
|
'name' => $request->name,
|
||||||
|
'url' => $request->url,
|
||||||
|
'icon' => $request->icon,
|
||||||
|
'parent_id' => $request->parent_id ?? null,
|
||||||
|
'sort_order' => $request->sort_order,
|
||||||
|
]);
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->route('menus.index')->with('success','Success created menu');
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
\Log::error('Menu creation failed: ' . $e->getMessage()); // Log the error for debugging
|
||||||
|
return redirect()->back()
|
||||||
|
->withInput()
|
||||||
|
->withErrors('Something went wrong! Please try again.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit(string $id)
|
||||||
|
{
|
||||||
|
$menu = Menu::findOrFail($id);
|
||||||
|
$parent_menus = Menu::whereNull('parent_id')->where('id','!=',$id)->get();
|
||||||
|
return view("menus.edit", compact('menu','parent_menus'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$validateData = $request->validate([
|
||||||
|
'name' => 'required',
|
||||||
|
'url'=> 'required',
|
||||||
|
'icon'=> 'nullable',
|
||||||
|
'parent_id' => 'nullable',
|
||||||
|
'sort_order' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$menu = Menu::findOrFail($id);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
$menu->update($validateData);
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->route('menus.index')->with('success','Successfully updated');
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
\Log::error('Menu update failed: '. $e->getMessage()); // Log the error for debugging
|
||||||
|
return redirect()->back()
|
||||||
|
->withInput()
|
||||||
|
->withErrors('Something went wrong! Please try again.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
DB::beginTransaction();
|
||||||
|
$menu = Menu::findOrFail($id);
|
||||||
|
$this->deleteChildren($menu);
|
||||||
|
$menu->roles()->detach();
|
||||||
|
$menu->delete();
|
||||||
|
DB::commit();
|
||||||
|
return response()->json(['success' => true, 'message' => 'Successfully deleted']);
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
\Log::error('failed delete menu'. $e->getMessage());
|
||||||
|
return response()->json(['success' => false, 'message' => 'Something went wrong! Please try again.']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteChildren($menu)
|
||||||
|
{
|
||||||
|
foreach ($menu->children as $child) {
|
||||||
|
$this->deleteChildren($child); // Recursively delete its children
|
||||||
|
$child->roles()->detach(); // Detach roles before deleting
|
||||||
|
$child->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
103
app/Http/Controllers/RolesController.php
Normal file
103
app/Http/Controllers/RolesController.php
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Role;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class RolesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view("roles.index");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view("roles.create");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$request->validate([
|
||||||
|
"name" => "required",
|
||||||
|
"description" => "nullable",
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
Role::create($request->all());
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->route("roles.index")->with('success','Succesfully Created');
|
||||||
|
}
|
||||||
|
catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with("error", $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit(string $id)
|
||||||
|
{
|
||||||
|
$role = Role::findOrFail($id);
|
||||||
|
return view("roles.edit", compact('role'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
$role = Role::findOrFail($id);
|
||||||
|
// Validate request data
|
||||||
|
$validatedData = $request->validate([
|
||||||
|
'name' => 'required|string|max:255|unique:roles,name,' . $id, // Ensure name is unique except for the current role
|
||||||
|
'description' => 'nullable|string|max:500',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
$role->update($validatedData);
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->route('roles.index')->with('success','Successfully updated');
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with("error", $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
DB::beginTransaction();
|
||||||
|
Role::findOrFail($id)->delete();
|
||||||
|
DB::commit();
|
||||||
|
}catch(\Exception $e){
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with("error", $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace App\Http\Controllers\Settings;
|
namespace App\Http\Controllers\Settings;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\ServiceSIMBG;
|
use App\Services\ServiceSIMBG;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Exception;
|
use Exception;
|
||||||
class SyncronizeController extends Controller
|
class SyncronizeController extends Controller
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class UserResource extends JsonResource
|
|||||||
'position' => $this->position,
|
'position' => $this->position,
|
||||||
'firstname' => $this->firstname,
|
'firstname' => $this->firstname,
|
||||||
'lastname' => $this->lastname,
|
'lastname' => $this->lastname,
|
||||||
|
'roles' => $this->roles->pluck('name'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
app/Models/Menu.php
Normal file
25
app/Models/Menu.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Menu extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'menus';
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'url',
|
||||||
|
'icon',
|
||||||
|
'parent_id',
|
||||||
|
'sort_order'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function roles(){
|
||||||
|
return $this->belongsToMany(Role::class, 'role_menu')->withTimestamps();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function children(){
|
||||||
|
return $this->hasMany(Menu::class,'parent_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Models/Role.php
Normal file
22
app/Models/Role.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Role extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'roles';
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'description'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function users(){
|
||||||
|
return $this->belongsToMany(User::class,'user_role')->withTimestamps();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function menus(){
|
||||||
|
return $this->belongsToMany(Menu::class,'role_menu')->withTimestamps();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,4 +49,8 @@ class User extends Authenticatable
|
|||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function roles(){
|
||||||
|
return $this->belongsToMany(Role::class, 'user_role')->withTimestamps();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Models\Menu;
|
||||||
use App\View\Components\Circle;
|
use App\View\Components\Circle;
|
||||||
|
use Auth;
|
||||||
use Illuminate\Support\Facades\Blade;
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
|
||||||
@@ -23,5 +26,22 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
Blade::component('circle', Circle::class);
|
Blade::component('circle', Circle::class);
|
||||||
|
|
||||||
|
View::composer('layouts.partials.sidebar', function ($view){
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if($user){
|
||||||
|
$menus = Menu::whereHas('roles', function ($query) use ($user){
|
||||||
|
$query->where('roles.id', $user->roles->pluck('id'));
|
||||||
|
})
|
||||||
|
->with('children')
|
||||||
|
->orderBy('sort_order', 'asc')
|
||||||
|
->get();
|
||||||
|
}else{
|
||||||
|
$menus = collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->with('menus', $menus);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App;
|
namespace App\Services;
|
||||||
use App\Traits\GlobalApiResponse;
|
use App\Traits\GlobalApiResponse;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use Exception;
|
use Exception;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Enums\ImportDatasourceStatus;
|
use App\Enums\ImportDatasourceStatus;
|
||||||
use App\Models\GlobalSetting;
|
use App\Models\GlobalSetting;
|
||||||
@@ -13,6 +13,7 @@ use App\Models\PbgTask;
|
|||||||
use App\Traits\GlobalApiResponse;
|
use App\Traits\GlobalApiResponse;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use App\Services\ServiceClient;
|
||||||
|
|
||||||
class ServiceSIMBG
|
class ServiceSIMBG
|
||||||
{
|
{
|
||||||
@@ -25,7 +26,7 @@ class ServiceSIMBG
|
|||||||
/**
|
/**
|
||||||
* Create a new class instance.
|
* Create a new class instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(ServiceClient $service_client)
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->email = trim((string) GlobalSetting::where('key','SIMBG_EMAIL')->first()->value);
|
$this->email = trim((string) GlobalSetting::where('key','SIMBG_EMAIL')->first()->value);
|
||||||
$this->password = trim((string) GlobalSetting::where('key','SIMBG_PASSWORD')->first()->value);
|
$this->password = trim((string) GlobalSetting::where('key','SIMBG_PASSWORD')->first()->value);
|
||||||
29
database/migrations/2025_02_10_104053_create_roles_table.php
Normal file
29
database/migrations/2025_02_10_104053_create_roles_table.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('roles', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name')->unique();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('roles');
|
||||||
|
}
|
||||||
|
};
|
||||||
33
database/migrations/2025_02_10_104254_create_menus_table.php
Normal file
33
database/migrations/2025_02_10_104254_create_menus_table.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('menus', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('url');
|
||||||
|
$table->string('icon')->nullable();
|
||||||
|
$table->unsignedBigInteger('parent_id')->nullable();
|
||||||
|
$table->integer('sort_order')->default(0);
|
||||||
|
$table->foreign('parent_id')->references('id')->on('menus')->onDelete('set null');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('menus');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('user_role', function (Blueprint $table) {
|
||||||
|
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
||||||
|
$table->foreignId('role_id')->constrained()->onDelete('cascade');
|
||||||
|
$table->primary(['user_id', 'role_id']);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('user_role');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('role_menu', function (Blueprint $table) {
|
||||||
|
$table->foreignId('role_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('menu_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->primary(['role_id', 'menu_id']);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('role_menu');
|
||||||
|
}
|
||||||
|
};
|
||||||
173
database/seeders/UsersRoleMenuSeeder.php
Normal file
173
database/seeders/UsersRoleMenuSeeder.php
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Menu;
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class UsersRoleMenuSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$roles = [
|
||||||
|
[
|
||||||
|
"name" => "superadmin",
|
||||||
|
"description" => "show all menus for super admins",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "admin",
|
||||||
|
"description" => "show only necessary menus for admins",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "operator",
|
||||||
|
"description" => "show only necessary menus for operators",
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
Role::upsert($roles, ['name']);
|
||||||
|
|
||||||
|
$parent_menus = [
|
||||||
|
[
|
||||||
|
"name" => "Dashboard",
|
||||||
|
"url" => "/dashboard",
|
||||||
|
"icon" => "mingcute:home-3-line",
|
||||||
|
"parent_id" => null,
|
||||||
|
"sort_order" => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Master",
|
||||||
|
"url" => "/master",
|
||||||
|
"icon" => "mingcute:cylinder-line",
|
||||||
|
"parent_id" => null,
|
||||||
|
"sort_order" => 2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Settings",
|
||||||
|
"url" => "/settings",
|
||||||
|
"icon" => "mingcute:settings-6-line",
|
||||||
|
"parent_id" => null,
|
||||||
|
"sort_order" => 3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Data Settings",
|
||||||
|
"url" => "/data-settings",
|
||||||
|
"icon" => "mingcute:settings-1-line",
|
||||||
|
"parent_id" => null,
|
||||||
|
"sort_order" => 4,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Data",
|
||||||
|
"url" => "/data",
|
||||||
|
"icon" => "mingcute:task-line",
|
||||||
|
"parent_id" => null,
|
||||||
|
"sort_order" => 5,
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($parent_menus as $parent_menu) {
|
||||||
|
Menu::create($parent_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach Menus to Roles
|
||||||
|
$superadmin = Role::where('name', 'superadmin')->first();
|
||||||
|
$admin = Role::where('name', 'admin')->first();
|
||||||
|
$operator = Role::where('name', 'operator')->first();
|
||||||
|
|
||||||
|
$dashboard = Menu::where('name', 'Dashboard')->first();
|
||||||
|
$master = Menu::where('name', 'Master')->first();
|
||||||
|
$settings = Menu::where('name', 'Settings')->first();
|
||||||
|
$dataSettings = Menu::where('name', 'Data Settings')->first();
|
||||||
|
$data = Menu::where('name', 'Data')->first();
|
||||||
|
|
||||||
|
// Superadmin gets all menus
|
||||||
|
$superadmin->menus()->attach([$dashboard->id, $master->id, $settings->id, $dataSettings->id, $data->id]);
|
||||||
|
|
||||||
|
// Admin gets limited menus
|
||||||
|
$admin->menus()->attach([$dashboard->id, $master->id, $settings->id]);
|
||||||
|
|
||||||
|
// Operator gets only basic menus
|
||||||
|
$operator->menus()->attach([$dashboard->id, $data->id]);
|
||||||
|
|
||||||
|
// Attach User to role super admin
|
||||||
|
User::findOrFail(1)->roles()->attach($superadmin->id);
|
||||||
|
|
||||||
|
// create children menu
|
||||||
|
|
||||||
|
// dashboard children
|
||||||
|
$children_menus = [
|
||||||
|
[
|
||||||
|
"name" => "Dashboard Pimpinan",
|
||||||
|
"url" => "dashboard.home",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $dashboard->id,
|
||||||
|
"sort_order" => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Dashboard PBG",
|
||||||
|
"url" => "dashboard.pbg",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $dashboard->id,
|
||||||
|
"sort_order" => 2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Users",
|
||||||
|
"url" => "users.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $master->id,
|
||||||
|
"sort_order" => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Syncronize",
|
||||||
|
"url" => "settings.syncronize",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $settings->id,
|
||||||
|
"sort_order" => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Menu",
|
||||||
|
"url" => "menus.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $settings->id,
|
||||||
|
"sort_order" => 2,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Role",
|
||||||
|
"url" => "roles.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $settings->id,
|
||||||
|
"sort_order" => 3,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Assign Role Menu",
|
||||||
|
"url" => "roles.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $settings->id,
|
||||||
|
"sort_order" => 4,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "Setting Dashboard",
|
||||||
|
"url" => "data-settings.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $dataSettings->id,
|
||||||
|
"sort_order" => 1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"name" => "PBG",
|
||||||
|
"url" => "pbg-task.index",
|
||||||
|
"icon" => null,
|
||||||
|
"parent_id" => $data->id,
|
||||||
|
"sort_order" => 1,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($children_menus as $child_menu) {
|
||||||
|
Menu::create($child_menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,15 @@ class UsersTable {
|
|||||||
"Firstname",
|
"Firstname",
|
||||||
"Lastname",
|
"Lastname",
|
||||||
"Position",
|
"Position",
|
||||||
|
"Roles",
|
||||||
|
{
|
||||||
|
name: "Action",
|
||||||
|
formatter: (cell) =>
|
||||||
|
gridjs.html(`
|
||||||
|
<div class="d-flex justify-content-end gap-x-2">
|
||||||
|
<a href="/master/users/${cell}/edit" class="btn btn-yellow me-2">Update</a>
|
||||||
|
`),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
pagination: {
|
pagination: {
|
||||||
limit: 15,
|
limit: 15,
|
||||||
@@ -42,15 +51,19 @@ class UsersTable {
|
|||||||
.getAttribute("content")}`,
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
then: (data) => {
|
||||||
data.data.map((item) => [
|
console.log(data.data);
|
||||||
|
return data.data.map((item) => [
|
||||||
item.id,
|
item.id,
|
||||||
item.name,
|
item.name,
|
||||||
item.email,
|
item.email,
|
||||||
item.firstname,
|
item.firstname,
|
||||||
item.lastname,
|
item.lastname,
|
||||||
item.position,
|
item.position,
|
||||||
]),
|
item.roles,
|
||||||
|
item.id,
|
||||||
|
]);
|
||||||
|
},
|
||||||
total: (data) => data.meta.total,
|
total: (data) => data.meta.total,
|
||||||
},
|
},
|
||||||
}).render(document.getElementById("table-users"));
|
}).render(document.getElementById("table-users"));
|
||||||
|
|||||||
109
resources/js/menus/index.js
Normal file
109
resources/js/menus/index.js
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import { Grid } from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
|
import GlobalConfig from "../global-config";
|
||||||
|
|
||||||
|
class Menus {
|
||||||
|
init() {
|
||||||
|
this.initTableMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
initTableMenus() {
|
||||||
|
new Grid({
|
||||||
|
columns: [
|
||||||
|
"ID",
|
||||||
|
"Name",
|
||||||
|
"Url",
|
||||||
|
"Icon",
|
||||||
|
"ParentID",
|
||||||
|
"Sort Order",
|
||||||
|
{
|
||||||
|
name: "Action",
|
||||||
|
formatter: (cell) =>
|
||||||
|
gridjs.html(`
|
||||||
|
<div class="d-flex justify-content-end gap-x-2">
|
||||||
|
<a href="/menus/${cell}/edit" class="btn btn-yellow me-2">Update</a>
|
||||||
|
<button class="btn btn-red btn-delete btn-delete-menu" data-id="${cell}">Delete</button>
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
limit: 15,
|
||||||
|
server: {
|
||||||
|
url: (prev, page) =>
|
||||||
|
`${prev}${prev.includes("?") ? "&" : "?"}page=${
|
||||||
|
page + 1
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sort: true,
|
||||||
|
search: {
|
||||||
|
server: {
|
||||||
|
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
url: `${GlobalConfig.apiHost}/api/api-menus`,
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
then: (data) =>
|
||||||
|
data.data.map((item) => [
|
||||||
|
item.id,
|
||||||
|
item.name,
|
||||||
|
item.url,
|
||||||
|
item.icon,
|
||||||
|
item.parent_id,
|
||||||
|
item.sort_order,
|
||||||
|
item.id,
|
||||||
|
]),
|
||||||
|
total: (data) => data.total,
|
||||||
|
},
|
||||||
|
}).render(document.getElementById("table-menus"));
|
||||||
|
|
||||||
|
document.addEventListener("click", this.handleDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDelete(event) {
|
||||||
|
if (event.target.classList.contains("btn-delete-menu")) {
|
||||||
|
event.preventDefault();
|
||||||
|
const id = event.target.getAttribute("data-id");
|
||||||
|
|
||||||
|
if (confirm("Are you sure you want to delete this item?")) {
|
||||||
|
fetch(`/menus/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"X-CSRF-TOKEN": document
|
||||||
|
.querySelector('meta[name="csrf-token"]')
|
||||||
|
.getAttribute("content"),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
alert("Item deleted successfully!");
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
return response.json().then((error) => {
|
||||||
|
throw new Error(
|
||||||
|
error.message || "Failed to delete item."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
alert("Something went wrong. Please try again.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new Menus().init();
|
||||||
|
});
|
||||||
103
resources/js/roles/index.js
Normal file
103
resources/js/roles/index.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import { Grid } from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import gridjs from "gridjs/dist/gridjs.umd.js";
|
||||||
|
import "gridjs/dist/gridjs.umd.js";
|
||||||
|
import GlobalConfig from "../global-config";
|
||||||
|
|
||||||
|
class Roles {
|
||||||
|
init() {
|
||||||
|
this.initTableRoles();
|
||||||
|
}
|
||||||
|
|
||||||
|
initTableRoles() {
|
||||||
|
new Grid({
|
||||||
|
columns: [
|
||||||
|
"ID",
|
||||||
|
"Name",
|
||||||
|
"Description",
|
||||||
|
{
|
||||||
|
name: "Action",
|
||||||
|
formatter: (cell) =>
|
||||||
|
gridjs.html(`
|
||||||
|
<div class="d-flex justify-content-end gap-x-2">
|
||||||
|
<a href="/roles/${cell}/edit" class="btn btn-yellow me-2">Update</a>
|
||||||
|
<button class="btn btn-red btn-delete btn-delete-role" data-id="${cell}">Delete</button>
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
limit: 15,
|
||||||
|
server: {
|
||||||
|
url: (prev, page) =>
|
||||||
|
`${prev}${prev.includes("?") ? "&" : "?"}page=${
|
||||||
|
page + 1
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sort: true,
|
||||||
|
search: {
|
||||||
|
server: {
|
||||||
|
url: (prev, keyword) => `${prev}?search=${keyword}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
url: `${GlobalConfig.apiHost}/api/api-roles`,
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
then: (data) =>
|
||||||
|
data.data.map((item) => [
|
||||||
|
item.id,
|
||||||
|
item.name,
|
||||||
|
item.description,
|
||||||
|
item.id,
|
||||||
|
]),
|
||||||
|
total: (data) => data.total,
|
||||||
|
},
|
||||||
|
}).render(document.getElementById("table-roles"));
|
||||||
|
|
||||||
|
document.addEventListener("click", this.handleDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDelete(event) {
|
||||||
|
if (event.target.classList.contains("btn-delete-role")) {
|
||||||
|
event.preventDefault();
|
||||||
|
const id = event.target.getAttribute("data-id");
|
||||||
|
|
||||||
|
if (confirm("Are you sure you want to delete this item?")) {
|
||||||
|
fetch(`/roles/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"X-CSRF-TOKEN": document
|
||||||
|
.querySelector('meta[name="csrf-token"]')
|
||||||
|
.getAttribute("content"),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
alert("Item deleted successfully!");
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
return response.json().then((error) => {
|
||||||
|
throw new Error(
|
||||||
|
error.message || "Failed to delete item."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error deleting item:", error);
|
||||||
|
alert("Something went wrong. Please try again.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
new Roles().init();
|
||||||
|
});
|
||||||
@@ -13,11 +13,11 @@ class="authentication-bg"
|
|||||||
<div class="card-body p-5">
|
<div class="card-body p-5">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<div class="mx-auto mb-4 text-center auth-logo">
|
<div class="mx-auto mb-4 text-center auth-logo">
|
||||||
<a href="{{ route('home') }}" class="logo-dark">
|
<a href="{{ route('dashboard.home') }}" class="logo-dark">
|
||||||
<img src="/images/dputr-kab-bandung.png" height="auto" width="100%" alt="logo dark">
|
<img src="/images/dputr-kab-bandung.png" height="auto" width="100%" alt="logo dark">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('home') }}" class="logo-light">
|
<a href="{{ route('dashboard.home') }}" class="logo-light">
|
||||||
<img src="/images/dputr-kab-bandung.png" height="auto" width="100%" alt="logo light">
|
<img src="/images/dputr-kab-bandung.png" height="auto" width="100%" alt="logo light">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,114 +1,47 @@
|
|||||||
<div class="app-sidebar">
|
<div class="app-sidebar">
|
||||||
<!-- Sidebar Logo -->
|
<!-- Sidebar Logo -->
|
||||||
<div class="logo-box">
|
<div class="logo-box">
|
||||||
<a href="{{ route('home') }}" class="logo-dark">
|
<a href="{{ route('dashboard.home') }}" class="logo-dark">
|
||||||
<img src="/images/dputr-kab-bandung.png" class="logo-sm" alt="logo sm">
|
<img src="/images/dputr-kab-bandung.png" class="logo-sm" alt="logo sm">
|
||||||
<img src="/images/dputr-kab-bandung.png" class="logo-lg" alt="logo dark">
|
<img src="/images/dputr-kab-bandung.png" class="logo-lg" alt="logo dark">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('home') }}" class="logo-light">
|
<a href="{{ route('dashboard.home') }}" class="logo-light">
|
||||||
<img src="/images/dputr-kab-bandung.png" class="logo-sm" alt="logo sm">
|
<img src="/images/dputr-kab-bandung.png" class="logo-sm" alt="logo sm">
|
||||||
<img src="/images/dputr-kab-bandung.png" class="logo-lg" alt="logo light">
|
<img src="/images/dputr-kab-bandung.png" class="logo-lg" alt="logo light">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="scrollbar" data-simplebar>
|
<div class="scrollbar" data-simplebar>
|
||||||
|
|
||||||
<ul class="navbar-nav" id="navbar-nav">
|
<ul class="navbar-nav" id="navbar-nav">
|
||||||
|
|
||||||
<li class="menu-title">Menu</li>
|
<li class="menu-title">Menu</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
@foreach ($menus as $menu)
|
||||||
<a class="nav-link menu-arrow" href="#sidebarDashboard" data-bs-toggle="collapse" role="button"
|
<li class="nav-item">
|
||||||
aria-expanded="false" aria-controls="sidebarDashboard">
|
<!-- parent menu -->
|
||||||
<span class="nav-icon">
|
<a class="nav-link menu-arrow" href="#sidebar-{{$menu->id}}" data-bs-toggle="collapse" role="button"
|
||||||
<iconify-icon icon="mingcute:home-3-line"></iconify-icon>
|
aria-expanded="true" aria-controls="sidebar-{{$menu->id}}">
|
||||||
</span>
|
<span class="nav-icon">
|
||||||
<span class="nav-text"> Dashboards</span>
|
<iconify-icon icon="{{$menu->icon}}"></iconify-icon>
|
||||||
</a>
|
</span>
|
||||||
<div class="collapse" id="sidebarDashboard">
|
<span class="nav-text">{{$menu->name}}</span>
|
||||||
<ul class="nav sub-navbar-nav">
|
</a>
|
||||||
<li class="sub-nav-item">
|
<!-- children menu foreach -->
|
||||||
<a class="sub-nav-link" href="{{ route ('home' ) }}">Dashboard Pimpinan</a>
|
@if ($menu->children->count() > 0)
|
||||||
|
<div class="collapse" id="sidebar-{{$menu->id}}">
|
||||||
</li>
|
<ul class="nav sub-navbar-nav">
|
||||||
<li class="sub-nav-item">
|
@foreach ( $menu->children as $child)
|
||||||
<a class="sub-nav-link" href="{{ route ('dashboards.pbg' ) }}">Dashboard PBG</a>
|
<li class="sub-nav-item">
|
||||||
</li>
|
<a class="sub-nav-link" href="{{ $child->url ? (Route::has($child->url) ? route($child->url) : $child->url) : '#' }}">
|
||||||
</ul>
|
{{ $child->name }}
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@endforeach
|
||||||
<li class="nav-item">
|
</ul>
|
||||||
<a class="nav-link menu-arrow" href="#sidebarDataMaster" data-bs-toggle="collapse" role="button"
|
</div>
|
||||||
aria-expanded="false" aria-controls="sidebarDataMaster">
|
@endif
|
||||||
<span class="nav-icon">
|
</li>
|
||||||
<iconify-icon icon="mingcute:cylinder-line"></iconify-icon>
|
@endforeach
|
||||||
</span>
|
|
||||||
<span class="nav-text">Master</span>
|
|
||||||
</a>
|
|
||||||
<div class="collapse" id="sidebarDataMaster">
|
|
||||||
<ul class="nav sub-navbar-nav">
|
|
||||||
<li class="sub-nav-item">
|
|
||||||
<a class="sub-nav-link" href="{{ route ('users.index' ) }}">Users</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link menu-arrow" href="#sidebarSettings" data-bs-toggle="collapse" role="button"
|
|
||||||
aria-expanded="false" aria-controls="sidebarSettings">
|
|
||||||
<span class="nav-icon">
|
|
||||||
<iconify-icon icon="mingcute:settings-6-line"></iconify-icon>
|
|
||||||
</span>
|
|
||||||
<span class="nav-text">Settings</span>
|
|
||||||
</a>
|
|
||||||
<div class="collapse" id="sidebarSettings">
|
|
||||||
<ul class="nav sub-navbar-nav">
|
|
||||||
<li class="sub-nav-item d-none">
|
|
||||||
<a class="sub-nav-link" href="{{ route ('general.index' ) }}">General</a>
|
|
||||||
</li>
|
|
||||||
<li class="sub-nav-item">
|
|
||||||
<a class="sub-nav-link" href="{{ route ('settings.syncronize' ) }}">Syncronize</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link menu-arrow" href="#dataSettings" data-bs-toggle="collapse" role="button"
|
|
||||||
aria-expanded="false" aria-controls="dataSettings">
|
|
||||||
<span class="nav-icon">
|
|
||||||
<iconify-icon icon="mingcute:settings-1-line"></iconify-icon>
|
|
||||||
</span>
|
|
||||||
<span class="nav-text">Data Settings</span>
|
|
||||||
</a>
|
|
||||||
<div class="collapse" id="dataSettings">
|
|
||||||
<ul class="nav sub-navbar-nav">
|
|
||||||
<li class="sub-nav-item">
|
|
||||||
<a class="sub-nav-link" href="{{ route ('data-settings.index' ) }}">Setting Dashboard</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link menu-arrow" href="#data" data-bs-toggle="collapse" role="button"
|
|
||||||
aria-expanded="false" aria-controls="data">
|
|
||||||
<span class="nav-icon">
|
|
||||||
<iconify-icon icon="mingcute:task-line"></iconify-icon>
|
|
||||||
</span>
|
|
||||||
<span class="nav-text">Data</span>
|
|
||||||
</a>
|
|
||||||
<div class="collapse" id="data">
|
|
||||||
<ul class="nav sub-navbar-nav">
|
|
||||||
<li class="sub-nav-item">
|
|
||||||
<a class="sub-nav-link" href="{{ route ('pbg-task.index' ) }}">PBG</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -172,7 +172,7 @@
|
|||||||
class="align-middle me-2 fs-18"></iconify-icon><span
|
class="align-middle me-2 fs-18"></iconify-icon><span
|
||||||
class="align-middle">Help</span>
|
class="align-middle">Help</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="dropdown-item" href="auth-{{ route ('home') }}">
|
<a class="dropdown-item" href="auth-{{ route ('dashboard.home') }}">
|
||||||
<iconify-icon icon="solar:lock-keyhole-outline"
|
<iconify-icon icon="solar:lock-keyhole-outline"
|
||||||
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">Lock
|
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">Lock
|
||||||
screen</span>
|
screen</span>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
placeholder="Enter your password" required>
|
placeholder="Enter your password" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="password_confirmation">Password</label>
|
<label class="form-label" for="password_confirmation">Password Confirmation</label>
|
||||||
<input type="password" id="password_confirmation" class="form-control" name="password_confirmation"
|
<input type="password" id="password_confirmation" class="form-control" name="password_confirmation"
|
||||||
placeholder="Enter your password confirmation" required>
|
placeholder="Enter your password confirmation" required>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,6 +45,15 @@
|
|||||||
<input type="text" id="position" class="form-control" name="position"
|
<input type="text" id="position" class="form-control" name="position"
|
||||||
placeholder="Enter your position" required>
|
placeholder="Enter your position" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="role">Role</label>
|
||||||
|
<select name="role_id" id="role" class="form-control">
|
||||||
|
<option value="">Select Role</option>
|
||||||
|
@foreach ($roles as $role)
|
||||||
|
<option value="{{$role->id}}">{{$role->name}}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<!-- username, firstname, lastname, position -->
|
<!-- username, firstname, lastname, position -->
|
||||||
<button type="submit" class="btn btn-success width-lg">Create</button>
|
<button type="submit" class="btn btn-success width-lg">Create</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -8,40 +8,47 @@
|
|||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="{{ route('master.users.update')}}">
|
<form action="{{ route('users.update', $user->id)}}" method="post">
|
||||||
@csrf
|
@csrf
|
||||||
|
@method("put")
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="name">Name</label>
|
<label class="form-label" for="name">Name</label>
|
||||||
<input type="name" id="name" name="name"
|
<input type="name" id="name" name="name"
|
||||||
class="form-control" placeholder="Enter your name" required>
|
class="form-control" placeholder="Enter your name" value="{{$user->name}}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="email">Email</label>
|
<label class="form-label" for="email">Email</label>
|
||||||
<input type="email" id="email" name="email"
|
<input type="email" id="email" name="email"
|
||||||
class="form-control" placeholder="Enter your email" required>
|
class="form-control" placeholder="Enter your email" value="{{$user->email}}" required>
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label" for="password">Password</label>
|
|
||||||
<input type="text" id="password" class="form-control" name="password"
|
|
||||||
placeholder="Enter your password" required>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="firstname">Firstname</label>
|
<label class="form-label" for="firstname">Firstname</label>
|
||||||
<input type="text" id="firstname" class="form-control" name="firstname"
|
<input type="text" id="firstname" class="form-control" name="firstname"
|
||||||
placeholder="Enter your firstname" required>
|
placeholder="Enter your firstname" value="{{$user->firstname}}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="lastname">Lastname</label>
|
<label class="form-label" for="lastname">Lastname</label>
|
||||||
<input type="text" id="lastname" class="form-control" name="lastname"
|
<input type="text" id="lastname" class="form-control" name="lastname"
|
||||||
placeholder="Enter your lastname" required>
|
placeholder="Enter your lastname" value="{{$user->lastname}}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label" for="position">Position</label>
|
<label class="form-label" for="position">Position</label>
|
||||||
<input type="text" id="position" class="form-control" name="position"
|
<input type="text" id="position" class="form-control" name="position"
|
||||||
placeholder="Enter your position" required>
|
placeholder="Enter your position" value="{{$user->position}}" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="role">Role</label>
|
||||||
|
<select name="role_id" id="role" class="form-control">
|
||||||
|
<option value="">Select Role</option>
|
||||||
|
@foreach($roles as $role)
|
||||||
|
<option value="{{ $role->id }}" {{ $user->roles->contains($role->id) ? 'selected' : '' }}>
|
||||||
|
{{ $role->name }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<!-- username, firstname, lastname, position -->
|
<!-- username, firstname, lastname, position -->
|
||||||
<button type="submit" class="btn btn-outline-success width-lg">Update</button>
|
<button type="submit" class="btn btn-success width-lg">Update</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
56
resources/views/menus/create.blade.php
Normal file
56
resources/views/menus/create.blade.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
@extends('layouts.vertical', ['subtitle' => 'Menu'])
|
||||||
|
|
||||||
|
@section('css')
|
||||||
|
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Menu'])
|
||||||
|
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{route("menus.store")}}" method="post">
|
||||||
|
@csrf
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="name">Name</label>
|
||||||
|
<input type="text" id="name" name="name"
|
||||||
|
class="form-control" placeholder="Enter menu name" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="url">URL</label>
|
||||||
|
<input type="text" id="url" name="url"
|
||||||
|
class="form-control" placeholder="Enter menu url" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="icon">Icon</label>
|
||||||
|
<input type="text" id="icon" name="icon"
|
||||||
|
class="form-control" placeholder="Enter menu icon" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="parent_id">Parent Menu</label>
|
||||||
|
<select name="parent_id" class="form-control">
|
||||||
|
<option value="">Select parent menu</option>
|
||||||
|
@foreach($parent_menus as $menu)
|
||||||
|
<option value="{{ $menu->id }}">{{ $menu->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="sort_order">Sort Order</label>
|
||||||
|
<input type="number" id="sort_order" name="sort_order"
|
||||||
|
class="form-control" placeholder="Enter sort order" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@endsection
|
||||||
57
resources/views/menus/edit.blade.php
Normal file
57
resources/views/menus/edit.blade.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
@extends('layouts.vertical', ['subtitle' => 'Menu'])
|
||||||
|
|
||||||
|
@section('css')
|
||||||
|
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Menu'])
|
||||||
|
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{route("menus.update", $menu->id)}}" method="post">
|
||||||
|
@csrf
|
||||||
|
@method("put")
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="name">Name</label>
|
||||||
|
<input type="text" id="name" name="name"
|
||||||
|
class="form-control" placeholder="Enter menu name" value="{{$menu->name}}" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="url">URL</label>
|
||||||
|
<input type="text" id="url" name="url"
|
||||||
|
class="form-control" placeholder="Enter menu url" value="{{$menu->url}}" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="icon">Icon</label>
|
||||||
|
<input type="text" id="icon" name="icon"
|
||||||
|
class="form-control" placeholder="Enter menu icon" value="{{$menu->icon}}" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="parent_id">Parent Menu</label>
|
||||||
|
<select name="parent_id" class="form-control">
|
||||||
|
<option value="">Select parent menu (Leave blank for parent)</option>
|
||||||
|
@foreach($parent_menus as $parent)
|
||||||
|
<option value="{{$parent->id}}"{{ $menu->parent_id == $parent->id ? 'selected' : '' }}>{{ $parent->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="sort_order">Sort Order</label>
|
||||||
|
<input type="number" id="sort_order" name="sort_order"
|
||||||
|
class="form-control" placeholder="Enter sort order" value="{{$menu->sort_order}}" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Update</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@endsection
|
||||||
24
resources/views/menus/index.blade.php
Normal file
24
resources/views/menus/index.blade.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
@extends('layouts.vertical', ['subtitle' => 'Menu'])
|
||||||
|
|
||||||
|
@section('css')
|
||||||
|
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Menu'])
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="d-flex justify-content-end pb-3">
|
||||||
|
<a href="{{ route('menus.create')}}" class="btn btn-success width-lg">Create</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id="table-menus"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@vite(['resources/js/menus/index.js'])
|
||||||
|
@endsection
|
||||||
@@ -17,11 +17,11 @@ class="authentication-bg"
|
|||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<div class="mx-auto mb-4 text-center">
|
<div class="mx-auto mb-4 text-center">
|
||||||
<div class="mx-auto text-center auth-logo">
|
<div class="mx-auto text-center auth-logo">
|
||||||
<!-- <a href="{{ route('home') }}" class="logo-dark">
|
<!-- <a href="{{ route('dashboard.home') }}" class="logo-dark">
|
||||||
<img src="/images/simbg-dputr.png" height="200" width="100%" alt="dputr logo">
|
<img src="/images/simbg-dputr.png" height="200" width="100%" alt="dputr logo">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('home') }}" class="logo-light">
|
<a href="{{ route('dashboard.home') }}" class="logo-light">
|
||||||
<img src="/images/simbg-dputr.png" height="200" width="100%" alt="dputr light">
|
<img src="/images/simbg-dputr.png" height="200" width="100%" alt="dputr light">
|
||||||
</a> -->
|
</a> -->
|
||||||
</div>
|
</div>
|
||||||
@@ -32,7 +32,7 @@ class="authentication-bg"
|
|||||||
<p class="text-muted mt-1 mb-4">The page you're trying to reach seems to have gone <br /> missing in the digital wilderness.</p>
|
<p class="text-muted mt-1 mb-4">The page you're trying to reach seems to have gone <br /> missing in the digital wilderness.</p>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<a href="{{ route('home') }}" class="btn btn-danger">Back to Home</a>
|
<a href="{{ route('dashboard.home') }}" class="btn btn-danger">Back to Home</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
37
resources/views/roles/create.blade.php
Normal file
37
resources/views/roles/create.blade.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
@extends('layouts.vertical', ['subtitle' => 'Role'])
|
||||||
|
|
||||||
|
@section('css')
|
||||||
|
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Role'])
|
||||||
|
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{route("roles.store")}}" method="post">
|
||||||
|
@csrf
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="name">Name</label>
|
||||||
|
<input type="text" id="name" name="name"
|
||||||
|
class="form-control" placeholder="Enter role name" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="description">Description</label>
|
||||||
|
<input type="text" id="description" name="description"
|
||||||
|
class="form-control" placeholder="Enter description">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@endsection
|
||||||
38
resources/views/roles/edit.blade.php
Normal file
38
resources/views/roles/edit.blade.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
@extends('layouts.vertical', ['subtitle' => 'Role'])
|
||||||
|
|
||||||
|
@section('css')
|
||||||
|
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Role'])
|
||||||
|
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{route("roles.update", $role->id)}}" method="post">
|
||||||
|
@csrf
|
||||||
|
@method("put")
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="name">Name</label>
|
||||||
|
<input type="text" id="name" name="name"
|
||||||
|
class="form-control" placeholder="Enter role name" value="{{$role->name}}" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="description">Description</label>
|
||||||
|
<input type="text" id="description" name="description"
|
||||||
|
class="form-control" placeholder="Enter description" value="{{$role->description}}">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success">Update</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@endsection
|
||||||
24
resources/views/roles/index.blade.php
Normal file
24
resources/views/roles/index.blade.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
@extends('layouts.vertical', ['subtitle' => 'Role'])
|
||||||
|
|
||||||
|
@section('css')
|
||||||
|
@vite(['node_modules/gridjs/dist/theme/mermaid.min.css'])
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('layouts.partials/page-title', ['title' => 'Settings', 'subtitle' => 'Role'])
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="d-flex justify-content-end pb-3">
|
||||||
|
<a href="{{ route('roles.create')}}" class="btn btn-success width-lg">Create</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id="table-roles"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@vite(['resources/js/roles/index.js'])
|
||||||
|
@endsection
|
||||||
@@ -5,8 +5,10 @@ use App\Http\Controllers\Api\DataSettingController;
|
|||||||
use App\Http\Controllers\Api\GlobalSettingsController;
|
use App\Http\Controllers\Api\GlobalSettingsController;
|
||||||
use App\Http\Controllers\Api\GoogleSheetController;
|
use App\Http\Controllers\Api\GoogleSheetController;
|
||||||
use App\Http\Controllers\Api\ImportDatasourceController;
|
use App\Http\Controllers\Api\ImportDatasourceController;
|
||||||
|
use App\Http\Controllers\Api\MenusController;
|
||||||
use App\Http\Controllers\Api\PbgTaskController;
|
use App\Http\Controllers\Api\PbgTaskController;
|
||||||
use App\Http\Controllers\Api\RequestAssignmentController;
|
use App\Http\Controllers\Api\RequestAssignmentController;
|
||||||
|
use App\Http\Controllers\Api\RolesController;
|
||||||
use App\Http\Controllers\Api\ScrapingController;
|
use App\Http\Controllers\Api\ScrapingController;
|
||||||
use App\Http\Controllers\Api\UsersController;
|
use App\Http\Controllers\Api\UsersController;
|
||||||
use App\Http\Controllers\Settings\SyncronizeController;
|
use App\Http\Controllers\Settings\SyncronizeController;
|
||||||
@@ -57,6 +59,12 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
|
|||||||
Route::get('/get-user-token', [SyncronizeController::class, 'getUserToken'])->name('api.task.token');
|
Route::get('/get-user-token', [SyncronizeController::class, 'getUserToken'])->name('api.task.token');
|
||||||
Route::get('/get-index-integration-retribution/{uuid}', [SyncronizeController::class, 'syncIndexIntegration'])->name('api.task.inntegration');
|
Route::get('/get-index-integration-retribution/{uuid}', [SyncronizeController::class, 'syncIndexIntegration'])->name('api.task.inntegration');
|
||||||
Route::get('/sync-task-submit/{uuid}', [SyncronizeController::class, 'syncTaskDetailSubmit'])->name('api.task.submit');
|
Route::get('/sync-task-submit/{uuid}', [SyncronizeController::class, 'syncTaskDetailSubmit'])->name('api.task.submit');
|
||||||
|
|
||||||
|
// menus api
|
||||||
|
Route::apiResource('api-menus', MenusController::class);
|
||||||
|
|
||||||
|
// roles api
|
||||||
|
Route::apiResource('api-roles', RolesController::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ use App\Http\Controllers\DataSettingController;
|
|||||||
use App\Http\Controllers\Dashboards\BigDataController;
|
use App\Http\Controllers\Dashboards\BigDataController;
|
||||||
use App\Http\Controllers\Home\HomeController;
|
use App\Http\Controllers\Home\HomeController;
|
||||||
use App\Http\Controllers\Master\UsersController;
|
use App\Http\Controllers\Master\UsersController;
|
||||||
|
use App\Http\Controllers\MenusController;
|
||||||
use App\Http\Controllers\RequestAssignment\PbgTaskController;
|
use App\Http\Controllers\RequestAssignment\PbgTaskController;
|
||||||
|
use App\Http\Controllers\RolesController;
|
||||||
use App\Http\Controllers\Settings\SettingsController;
|
use App\Http\Controllers\Settings\SettingsController;
|
||||||
use App\Http\Controllers\Settings\SyncronizeController;
|
use App\Http\Controllers\Settings\SyncronizeController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
@@ -18,12 +20,9 @@ Route::group(['middleware' => 'auth'], function(){
|
|||||||
|
|
||||||
//dashboards
|
//dashboards
|
||||||
Route::group(['prefix' => '/dashboards'], function(){
|
Route::group(['prefix' => '/dashboards'], function(){
|
||||||
Route::get('/bigdata', [BigDataController::class, 'index'])->name('home');
|
Route::get('/bigdata', [BigDataController::class, 'index'])->name('dashboard.home');
|
||||||
|
Route::get('/dashboard-pbg', [BigDataController::class, 'pbg'])->name('dashboard.pbg');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['prefix' => '/dashboards'], function(){
|
|
||||||
Route::get('/dashboard-pbg', [BigDataController::class, 'pbg'])->name('dashboards.pbg');
|
|
||||||
});
|
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
Route::group(['prefix' => '/settings'], function(){
|
Route::group(['prefix' => '/settings'], function(){
|
||||||
@@ -43,4 +42,10 @@ Route::group(['middleware' => 'auth'], function(){
|
|||||||
|
|
||||||
// data settings
|
// data settings
|
||||||
Route::resource('/data-settings', DataSettingController::class);
|
Route::resource('/data-settings', DataSettingController::class);
|
||||||
|
|
||||||
|
// menus
|
||||||
|
Route::resource('/menus', MenusController::class);
|
||||||
|
|
||||||
|
// roles
|
||||||
|
Route::resource('/roles', RolesController::class);
|
||||||
});
|
});
|
||||||
@@ -6,7 +6,6 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
outDir: "public/build",
|
outDir: "public/build",
|
||||||
manifest: true, // Menghasilkan manifest.json untuk Laravel
|
manifest: true, // Menghasilkan manifest.json untuk Laravel
|
||||||
|
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@@ -52,7 +51,9 @@ export default defineConfig({
|
|||||||
"resources/js/data-settings/index.js",
|
"resources/js/data-settings/index.js",
|
||||||
"resources/js/pbg-task/index.js",
|
"resources/js/pbg-task/index.js",
|
||||||
"resources/js/settings/general/general-settings.js",
|
"resources/js/settings/general/general-settings.js",
|
||||||
"resources/js/tables/common-table.js"
|
"resources/js/tables/common-table.js",
|
||||||
|
"resources/js/menus/index.js",
|
||||||
|
"resources/js/roles/index.js",
|
||||||
],
|
],
|
||||||
refresh: true,
|
refresh: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user