11
Kustomisasi dan Plugin
Badaso memisahkan kode paket dari kode aplikasi. Direktori src/resources/customization/ dipublikasikan ke resources/js/badaso pada tag publish Badaso src/Providers/BadasoServiceProvider.php:591, dan pemetaan yang sama diulang pada tag BadasoResource bersama aset gambar serta view src/Providers/BadasoServiceProvider.php:91-962. Karena tujuannya berada di resources/, hasil publish menjadi bagian dari aplikasi, bukan bagian dari vendor, sehingga penimpaan tidak hilang ketika paket diperbarui.
graph TD
PKG["src/resources/customization/"] -->|"vendor:publish tag BadasoResource"| OUT["resources/js/badaso/"]
OUT --> COMP["components/*.vue"]
OUT --> PAGE["pages/**/*.vue"]
OUT --> ROUTE["routers/**/*.js"]
OUT --> STORE["stores/*.js"]
OUT --> APIF["api/*.js"]
OUT --> SCSSF["scss/custom.scss"]
OUT --> LANGF["lang/*.js"]
COMP --> APPJS["app.js"]
PAGE --> APPJS
STORE --> STOREJS["store/store.js"]
APIF --> APIJS["api/index.js"]
ROUTE --> ROUTERJS["router/router.js"]
LANGF --> LANGJS["lang/index.js"]
SCSSF --> STYLE["assets/scss/style.scss"]
ROUTERJS --> EXCL["router/excludeRouter.js"]
style PKG fill:#f59e0b,color:#000
style OUT fill:#8b5cf6,color:#fff
style SCSSF fill:#2d7d46,color:#fff
style EXCL fill:#dc2626,color:#fff
%% fig: Publikasi customization ke resources/js/badaso
%% desc: Direktori customization disalin ke resources/js/badaso, lalu tiap folder dimuat oleh glob importer di frontend dan scss/custom.scss diimpor oleh style.scss.Titik ekstensi frontend
Frontend tidak memuat berkas customization lewat import statis, melainkan lewat glob yang menunjuk ke path resources/js/badaso. Setiap folder punya pemuatnya sendiri, sehingga menambah berkas di folder yang benar sudah cukup untuk mengubah tampilan atau perilaku.
Folder di resources/js/badaso | Yang dapat ditimpa | Pemuat |
|---|---|---|
components/ | komponen Vue yang dipakai lintas halaman | src/resources/badaso/app.js:983 |
pages/ | halaman admin, termasuk subfolder | src/resources/badaso/app.js:1834 |
routers/auth/, routers/public/, routers/admin/, routers/others/ | definisi route per area | src/resources/badaso/router/router.js:103-1245 |
stores/ | state Vuex | src/resources/badaso/store/store.js:416 |
api/ | modul pemanggil endpoint | src/resources/badaso/api/index.js:377 |
lang/ | berkas terjemahan | src/resources/badaso/lang/index.js:458 |
utils/ | helper bersama | src/resources/badaso/app.js:1539 |
scss/custom.scss | aturan CSS tambahan | src/resources/badaso/assets/scss/style.scss:1810 |
Karena glob di atas hanya membaca resources/js/badaso, berkas hasil publish adalah satu-satunya sumber bagi komponen dan halaman aplikasi. Berkas dengan nama yang sama di folder tujuan menggantikan berkas paket tanpa perlu menyunting vendor.
Router inti yang tidak dapat ditimpa
src/resources/badaso/router/excludeRouter.js mendaftar 41 nama route yang dikeluarkan dari mekanisme penimpaan src/resources/badaso/router/excludeRouter.js:1-4311. Daftar itu dibuka oleh Auth, PageNotFound, dan *, dilanjutkan Home serta UserProfile, lalu seluruh halaman manajemen, dan ditutup ApiDocumentation. Berkas tersebut diimpor oleh app.js src/resources/badaso/app.js:1412.
⚠️
Auth,PageNotFound, dan*ada di daftar exclude. Mengubah perilaku login atau halaman 404 lewat folderrouters/tidak berpengaruh pada entri tersebut.
Widget sebagai plugin backend
Widget adalah titik ekstensi sisi server pada halaman ini. WidgetInterface hanya mewajibkan dua method, yaitu getPermissions() dan run($params = null) src/Interfaces/WidgetInterface.php:8-1313, sehingga satu kelas widget cukup mengimplementasikan keduanya. UserWidget adalah contoh kelas yang mengimplementasikan interface itu src/Widgets/UserWidget.php:814.
getPermissions() mengembalikan satu string permission; nilai null berarti semua role boleh melihat, dan beberapa permission dipisah koma src/Widgets/UserWidget.php:10-1815. run() mengembalikan array data widget dengan kunci label, icon, value, prefix_value, dan delimiter; pada UserWidget, value diisi User::count() src/Widgets/UserWidget.php:20-2916.
graph TD
CFG["config('badaso.widgets')"] --> CTRL["BadasoDashboardController::index"]
CTRL --> NEW["new $widget()"]
NEW --> INST{"instanceof WidgetInterface"}
INST -->|"tidak"| SKIP["dilewati"]
INST -->|"ya"| PERM["getPermissions()"]
PERM --> NULL{"is_null?"}
NULL -->|"ya"| RUN["run()"]
NULL -->|"tidak"| ALLOW["AuthenticatedUser::isAllowedTo()"]
ALLOW -->|"true"| RUN
ALLOW -->|"false"| SKIP
RUN --> RESP["ApiResponse::success()"]
style CFG fill:#f59e0b,color:#000
style INST fill:#f59e0b,color:#000
style NULL fill:#f59e0b,color:#000
style SKIP fill:#dc2626,color:#fff
style RESP fill:#2d7d46,color:#fff
%% fig: Siklus satu widget pada dashboard
%% desc: Controller membaca daftar widget dari config, menyaring kelas yang bukan WidgetInterface, memeriksa permission, lalu mengumpulkan hasil run ke response.BadasoDashboardController::index membaca config('badaso.widgets'), membuat instance tiap kelas, dan memprosesnya hanya jika objek tersebut instanceof WidgetInterface. Permission diperiksa dengan AuthenticatedUser::isAllowedTo($permissions); widget yang tidak lolos tidak masuk ke array hasil, dan daftar akhir dikembalikan lewat ApiResponse::success src/Controllers/BadasoDashboardController.php:15-3217.
Mendaftarkan widget sendiri
Daftar default pada berkas config berisi tiga kelas, yaitu UserWidget, RoleWidget, dan PermissionWidget src/Config/badaso.php:48-5218. Penambahan widget berarti tiga langkah: membuat kelas yang mengimplementasikan WidgetInterface, menambahkan FQCN kelas itu ke kunci widgets, lalu menyunting config/badaso.php di aplikasi. Tag BadasoConfig memuat Config/badaso.php beserta config paket lain, sehingga berkas config dapat disalin ke aplikasi lebih dulu src/Providers/BadasoServiceProvider.php:73-8319.
⚠️ Menjalankan ulang
vendor:publish --tag=BadasoResourcemenyalin seluruhsrc/resources/customization/keresources/js/badasosrc/Providers/BadasoServiceProvider.php:91-962. Perubahan manual di folder tujuan akan tertimpa, jadi simpan kustomisasi di Version Control System sebelum publish ulang.
Rincian bagaimana hasil publish ini dipakai saat build dan pemuatan halaman admin dibahas di Frontend Admin Panel. Cara kerja kunci config lain, termasuk configuration_groups, dijelaskan di Menu dan Konfigurasi Aplikasi.