create user role and menu, create seeder for first user and create crud role, menu and user

This commit is contained in:
arifal
2025-02-11 02:35:53 +07:00
parent 6307417ae3
commit cb90f69d1e
37 changed files with 1326 additions and 151 deletions

View File

@@ -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();
} }
} }

View 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)
{
//
}
}

View 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)
{
//
}
}

View File

@@ -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');
} }
} }

View 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();
}
}
}

View 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());
}
}
}

View File

@@ -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

View File

@@ -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
View 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
View 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();
}
}

View File

@@ -49,4 +49,8 @@ class User extends Authenticatable
'password' => 'hashed', 'password' => 'hashed',
]; ];
} }
public function roles(){
return $this->belongsToMany(Role::class, 'user_role')->withTimestamps();
}
} }

View File

@@ -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);
});
} }
} }

View File

@@ -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;

View File

@@ -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);

View 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');
}
};

View 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');
}
};

View 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('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');
}
};

View 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('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');
}
};

View 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);
}
}
}

View File

@@ -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
View 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
View 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();
});

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View 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

View 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

View 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

View File

@@ -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>

View 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

View 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

View 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

View File

@@ -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);
}); });

View File

@@ -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);
}); });

View File

@@ -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,
}), }),