Compare commits

...

2 Commits

Author SHA1 Message Date
21012d38c3 done next -> testing 2026-01-26 16:05:39 +07:00
de1216c5f5 progress 2026-01-26 11:09:39 +07:00
22 changed files with 699 additions and 258 deletions

View File

@ -47,6 +47,7 @@ class AksesFileController extends Controller
'pegawai_nama_entry' => auth()->user()?->dataUser?->namalengkap,
'entry_at' => Carbon::now()->format('Y-m-d H:i:s.u'),
'all_akses' => $data['akses'] === "all" ? true : false,
'master_akses' => $data['master_akses'] === "yes" ? true : false,
];
$af = AksesFile::create($payload);
if($data['akses'] === "unit"){
@ -160,6 +161,7 @@ class AksesFileController extends Controller
'pegawai_nama_modified' => auth()->user()?->dataUser?->namalengkap,
'modified_at' => Carbon::now()->format('Y-m-d H:i:s.u'),
'all_akses' => request('akses') === "all" ? true : false,
'master_akses' => request('master_akses') === "yes" ? true : false,
];
$data->update($payload);

View File

@ -25,6 +25,7 @@ class DashboardController extends Controller
public function index(){
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
$klasifikasiDok = MasterKlasifikasi::where('statusenabled', true)->select('master_klasifikasi_directory_id', 'nama_klasifikasi_directory')->get();
$prefillFilter = session()->pull('dashboard_prefill');
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
$authUnitKerja = $authMapping->objectunitkerjapegawaifk;
@ -37,13 +38,37 @@ class DashboardController extends Controller
'klasifikasiDok' => $klasifikasiDok,
'authUnitKerja' => $authUnitKerja,
'authSubUnitKerja' => $authSubUnitKerja,
'allAkses' => $allAkses ?? null
'allAkses' => $allAkses ?? null,
'prefillFilter' => $prefillFilter
];
return view('dashboard.index', $payload);
}
public function setDashboardPrefill(Request $request)
{
$payload = [
'unitId' => (string) $request->input('unitId', ''),
'subId' => (string) $request->input('subId', ''),
'kategoriId' => (string) $request->input('kategoriId', ''),
'unitName' => (string) $request->input('unitName', ''),
'subName' => (string) $request->input('subName', ''),
'kategoriName' => (string) $request->input('kategoriName', ''),
];
session(['dashboard_prefill' => $payload]);
return response()->json([
'status' => true,
'message' => 'Prefill disimpan'
]);
}
public function dataUnitKerja(){
$user = auth()->user()?->dataUser;
$entryPegawaiId = auth()->user()?->objectpegawaifk;
$authMapping = $user?->mappingUnitKerjaPegawai[0] ?? null;
$authUnit = $authMapping?->objectunitkerjapegawaifk;
$authSub = $authMapping?->objectsubunitkerjapegawaifk;
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
$aksesAll = $akses?->akses ?? $akses?->all_akses ?? false;
$detailUnitIds = collect();
@ -62,6 +87,11 @@ class DashboardController extends Controller
$allowedUnitIds = collect([$akses->unit_akses]);
}
}
$limitPrivateToSubUnit = false;
if (!$aksesAll && !$allowedUnitIds && $authUnit) {
$allowedUnitIds = collect([$authUnit]);
$limitPrivateToSubUnit = true;
}
$kategori = request('kategori');
$filterUnit = request('unitKerja');
@ -71,37 +101,67 @@ class DashboardController extends Controller
$katArray = $kategori ? explode(',', $kategori) : [];
$katDok = MasterKategori::when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))->where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
$applyFileFilters = function ($q) use ($keyword, $katArray, $subArray, $entryPegawaiId) {
$q->where(function($subQuery) use ($entryPegawaiId){
$subQuery->where('status_action', '!=', 'rejected')
->orWhere(function ($pending) use ($entryPegawaiId) {
$pending->whereNull('status_action')
->where('pegawai_id_entry', $entryPegawaiId);
});
})
->when($subArray, fn($sq) => $sq->whereIn('id_sub_unit_kerja', $subArray))
->when($katArray, fn($sq) => $sq->whereIn('master_kategori_directory_id', $katArray))
->when($keyword, fn($sq) =>
$sq->where(function ($query) use ($keyword) {
$query->where('file', 'ilike', "%{$keyword}%");
})
);
};
$applyAccessFilter = function ($q) use ($aksesAll, $allowedUnitIds, $limitPrivateToSubUnit, $authSub) {
if ($aksesAll) {
return;
}
$hasPrivateScope = ($allowedUnitIds && $allowedUnitIds->isNotEmpty())
|| ($limitPrivateToSubUnit && $authSub);
$q->where(function ($query) use ($allowedUnitIds, $limitPrivateToSubUnit, $authSub, $hasPrivateScope) {
$query->where('permission_file', true);
if ($hasPrivateScope) {
$query->orWhere(function ($sub) use ($allowedUnitIds, $limitPrivateToSubUnit, $authSub) {
$sub->where('permission_file', false);
if ($allowedUnitIds && $allowedUnitIds->isNotEmpty()) {
$sub->whereIn('id_unit_kerja', $allowedUnitIds);
}
if ($limitPrivateToSubUnit && $authSub) {
$sub->where('id_sub_unit_kerja', $authSub);
}
});
}
});
};
$applyFileQuery = function ($q) use ($applyFileFilters, $applyAccessFilter) {
$applyFileFilters($q);
$applyAccessFilter($q);
};
if ($katArray && $filterUnit && $subArray) {
/* mode pencarian lengkap */
if ($allowedUnitIds && !$allowedUnitIds->contains((int) $filterUnit)) {
$unitKerja = collect();
} else {
$unitKerja = UnitKerja::where('statusenabled', true)
->where('id', $filterUnit)
->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray)
->with(['fileDirectory' => fn($q) => $q
->where('id_unit_kerja', $filterUnit)
->when($subArray, fn($q) => $q->whereIn('id_sub_unit_kerja', $subArray))
->when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))
->when($keyword, fn($q) =>
$q->where(function($query) use ($keyword) {
$query->where('file', 'ilike', "%{$keyword}%")
->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%");
})
)
])
->whereHas('fileDirectory', fn($f) => $applyFileQuery($f))
->with(['fileDirectory' => fn($f) => $applyFileQuery($f)])
])
->select('id', 'name')
->get();
}
} elseif ($aksesAll) {
/* all akses */
$unitKerja = UnitKerja::where('statusenabled', true)->with([ // muat relasi
'subUnitKerja' => fn($q) => $q->with([ // sub-unit
'fileDirectory' => fn($f) => $f->when($keyword, fn($q) =>
'fileDirectory' => fn($f) => $f->whereNotNull('status_action')->when($keyword, fn($q) =>
$q->where('file', 'ilike', "%{$keyword}%")
->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%")
)
])
])
@ -109,38 +169,37 @@ class DashboardController extends Controller
->get();
} elseif ($allowedUnitIds) {
/* akses per unit (single/multiple) */
$unitKerja = UnitKerja::where('statusenabled', true)
->whereIn('id', $allowedUnitIds)
->with([ // muat relasi
'subUnitKerja' => fn($q) => $q->with([ // sub-unit
'fileDirectory' => fn($f) => $f->when($keyword, fn($q) =>
$q->where(function($query) use ($keyword) {
$query->where('file', 'ilike', "%{$keyword}%")
->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%");
})
)
])
->where(function ($q) use ($allowedUnitIds, $applyFileQuery) {
if ($allowedUnitIds && $allowedUnitIds->isNotEmpty()) {
$q->whereIn('id', $allowedUnitIds);
}
$q->orWhereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f));
})
->with([
'subUnitKerja' => fn($q) => $q->whereHas('fileDirectory', fn($f) => $applyFileQuery($f))
->with(['fileDirectory' => fn($f) => $applyFileQuery($f)])
])
->select('id', 'name')
->get();
} else {
/* default : unit & sub milik sendiri */
$authUnit = $user?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk;
$authSub = $user?->mappingUnitKerjaPegawai[0]?->objectsubunitkerjapegawaifk;
$unitKerja = UnitKerja::where('statusenabled', true)
->where('id', $authUnit)
->where(function ($q) use ($authUnit, $applyFileQuery) {
if ($authUnit) {
$q->where('id', $authUnit);
}
$q->orWhereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f));
})
->with([ // 1. sub-unit milik user
'subUnitKerja' => fn($q) => $q->where('id', $authSub)
'subUnitKerja' => fn($q) => $q->where(function ($sq) use ($authSub, $applyFileQuery) {
if ($authSub) {
$sq->where('id', $authSub);
}
$sq->orWhereHas('fileDirectory', fn($f) => $applyFileQuery($f));
})
->with([ // 2. file-directory + filter keyword
'fileDirectory' => fn($f) => $f->when($keyword, fn($q) =>
$q->where(function($query) use ($keyword) {
$query->where('file', 'ilike', "%{$keyword}%")
->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%");
})
)
'fileDirectory' => fn($f) => $applyFileQuery($f)
])
])
->select('id', 'name')
@ -302,7 +361,7 @@ class DashboardController extends Controller
$paths = [];
foreach ($rows as $r) {
if(!empty($r['sub_unit_id'])){
$files = FileDirectory::where('id_sub_unit_kerja', $r['sub_unit_id'])->where('statusenabled', true)->pluck('file');
$files = FileDirectory::where('id_sub_unit_kerja', $r['sub_unit_id'])->where('statusenabled', true)->where('status_action', 'approved')->pluck('file');
$paths = array_merge($paths, $files->toArray());
}
@ -347,9 +406,9 @@ class DashboardController extends Controller
$type = request('type');
if($type === "unit"){
$data = FileDirectory::where('id_unit_kerja', $id)->where('statusenabled', true)->pluck('file');
$data = FileDirectory::where('id_unit_kerja', $id)->where('statusenabled', true)->where('status_action', 'approved')->pluck('file');
}else{
$data = FileDirectory::where('id_sub_unit_kerja', $id)->where('statusenabled', true)->pluck('file');
$data = FileDirectory::where('id_sub_unit_kerja', $id)->where('statusenabled', true)->where('status_action', 'approved')->pluck('file');
}
if (empty($data)) {
return response()->json(['message' => 'File tidak ditemukan'], 404);
@ -400,11 +459,18 @@ class DashboardController extends Controller
$perPage = (int) request('per_page', 10);
$authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk;
$user = auth()->user()?->dataUser;
$entryPegawaiId = auth()->user()?->objectpegawaifk;
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
$keyword = request('keyword');
$query = FileDirectory::where('statusenabled', true)
->when($keyword, function ($q) use ($keyword) {
->where(function($subQuery) use ($entryPegawaiId){
$subQuery->where('status_action', '!=', 'rejected')
->orWhere(function ($pending) use ($entryPegawaiId) {
$pending->whereNull('status_action')
->where('pegawai_id_entry', $entryPegawaiId);
});
})->when($keyword, function ($q) use ($keyword) {
$q->where(function ($sub) use ($keyword) {
$sub->where('file', 'ILIKE', "%{$keyword}%")
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
@ -674,8 +740,8 @@ class DashboardController extends Controller
$perPage = (int) request('per_page', 10);
$page = max(1, (int) request('page', 1));
$keyword = strtolower(request('keyword', ''));
$rows = FileDirectory::where('statusenabled', true)->pluck('file');
$authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
$rows = FileDirectory::where('statusenabled', true)->whereNotNull('status_action')->whereIn('id_unit_kerja', $authUnit)->pluck('file');
$grouped = [];
foreach ($rows as $path) {
@ -754,8 +820,12 @@ class DashboardController extends Controller
$keyword = request('keyword');
$start = request('start_date');
$end = request('end_date');
$authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
$query = FileDirectory::where('statusenabled', true)->whereNull('status_action')->orderBy('entry_at','desc');
$query = FileDirectory::where('statusenabled', true)->where(function($q){
$q->where('status_action', '!=', 'approved')
->orWhereNull('status_action');
})->whereIn('id_unit_kerja', $authUnit)->orderBy('entry_at','desc');
if($keyword){
$query->where(function($q) use ($keyword){
$q->where('file', 'ILIKE', "%{$keyword}%")
@ -783,6 +853,7 @@ class DashboardController extends Controller
'entry_at' => $item->entry_at,
'tanggal_terbit' => $item->tanggal_terbit,
'permission_file' => $item->permission_file,
'status_action' => $item->status_action
];
});
return response()->json([
@ -886,9 +957,10 @@ class DashboardController extends Controller
public function countDataPending(){
try {
$count = FileDirectory::where('statusenabled', true)
->whereNull('status_action')
->count();
$query = FileDirectory::where('statusenabled', true)
->whereNull('status_action');
$authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
$count= $query->whereIn('id_unit_kerja', $authUnit)->count();
return response()->json([
'status' => true,
'count' => $count,

View File

@ -22,7 +22,12 @@ class LogActivityController extends Controller
$query = LogActivity::query()
->orderBy('entry_at','desc');
if(auth()->user()->masterPersetujuan){
$authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
$query = $query->whereIn('id_unit_kerja', $authUnit);
}else{
$query = $query->where('pegawai_id_entry', auth()->user()->objectpegawaifk);
}
if($keyword){
$query->where(function($q) use ($keyword){
$q->where('pegawai_nama_entry', 'ILIKE', "%{$keyword}%")

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureMasterAkses
{
public function handle(Request $request, Closure $next): Response
{
$user = $request->user();
$hasAccess = $user && $user->akses && $user->akses->master_akses;
if (!$hasAccess) {
abort(403, 'Tidak memiliki akses.');
}
return $next($request);
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureMasterPersetujuan
{
public function handle(Request $request, Closure $next): Response
{
$user = $request->user();
$hasAccess = $user && $user->masterPersetujuan;
if (!$hasAccess) {
abort(403, 'Tidak memiliki akses.');
}
return $next($request);
}
}

View File

@ -45,8 +45,16 @@ class User extends Authenticatable
'katasandi' => 'hashed',
];
}
protected $with = ['dataUser'];
protected $with = ['dataUser', 'masterPersetujuan', 'akses'];
public function dataUser(){
return $this->belongsTo(DataUser::class, 'objectpegawaifk', 'id')->select('id', 'namalengkap');
}
public function masterPersetujuan(){
return $this->belongsTo(masterPersetujuan::class, 'objectpegawaifk', 'pegawai_id')->where('statusenabled', true)->with('details');
}
public function akses(){
return $this->belongsTo(AksesFile::class, 'objectpegawaifk', 'pegawai_id')->where('statusenabled', true);
}
}

View File

@ -11,7 +11,10 @@ return Application::configure(basePath: dirname(__DIR__))
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
//
$middleware->alias([
'akses.master' => \App\Http\Middleware\EnsureMasterAkses::class,
'master.persetujuan' => \App\Http\Middleware\EnsureMasterPersetujuan::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
//

View File

@ -15647,7 +15647,7 @@ textarea.form-control-lg {
.left-sidebar .scroll-sidebar {
overflow-y: auto;
padding: 0 24px;
height: calc(100vh - 310px);
height: calc(100vh - 120px);
border-radius: 7px;
}
.left-sidebar .scroll-sidebar .simplebar-track.simplebar-horizontal {
@ -15818,11 +15818,10 @@ textarea.form-control-lg {
width: 100%;
background: var(--bs-body-bg);
padding: 0 10px;
/* top: 65px; */
}
@media (max-width: 991.98px) {
.app-header {
top: 131px;
top: 0px;
}
}
.app-header .container-fluid, .app-header .container-sm, .app-header .container-md, .app-header .container-lg, .app-header .container-xl, .app-header .container-xxl {

View File

@ -105,7 +105,7 @@ function editAkses(e){
formEditAkses.attr('action', `/akses/${data.akses_file_id}`)
$("#unit_akses_edit").empty().trigger('change');
$("#unit_akses_wrapper_edit").addClass('d-none');
$("#master_akses_edit").prop("checked", data.master_akses == 1)
selectOptionPegawaiEdit()
selectOptionUnitKerjaEdit()
if (data.pegawai_id) {

View File

@ -18,6 +18,8 @@
{
title:"Action",
formatter: function(value, row){
console.log(row);
let buttons = '';
buttons += `
<button class="btn btn-sm btn-danger me-2" onclick="deleteAkses(this)"
@ -31,7 +33,9 @@
data-pegawai_id="${row?.pegawai_id}"
data-pegawai_nama="${row?.pegawai?.namalengkap}"
data-unit_id="${row?.unit_akses}"
data-unit_nama="${row?.akses?.name}">
data-unit_nama="${row?.akses?.name}"
data-master_akses="${row?.master_akses ? 1 : 0}"
>
<i class="fa-solid fa-pencil"></i>
</button>`
return `

View File

@ -107,8 +107,14 @@ function addForm(){
By Unit Akses
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="data[${colCount}][master_akses]" id="akses_unit_${colCount}" value="yes">
<label class="form-check-label">
Akses Master
</label>
</div>
</div>
<small class="text-muted">Pilih salah satu.</small>
</div>
<div class="col-md-4 mb-2 d-none" id="unit_akses_wrapper_${colCount}">
<label>Unit Kerja</label>

View File

@ -47,11 +47,16 @@ $(document).ready(function() {
loadSubUnitKerja(initialUnit);
}
let prefillSubIds = [];
let prefillSubMeta = {};
// jalankan setiap kali unit_kerja berubah
$('.unit_kerja').on('change', function(){
let idUnit = $(this).val();
if(idUnit){
loadSubUnitKerja(idUnit);
loadSubUnitKerja(idUnit, prefillSubIds, prefillSubMeta);
prefillSubIds = [];
prefillSubMeta = {};
}
});
@ -62,9 +67,67 @@ $(document).ready(function() {
}else{
selectOptionUnitKerjaV2(0);
}
if (window.__folderPrefillApplied) return;
const urlParams = new URLSearchParams(window.location.search);
const prefill = window.__prefillFromSession || null;
const unitId = prefill?.unitId || urlParams.get('unitKerja');
const subParam = prefill?.subId || urlParams.get('subUnit');
const katParam = prefill?.kategoriId || urlParams.get('kategori');
const unitName = prefill?.unitName || urlParams.get('unitName');
const subName = prefill?.subName || urlParams.get('subName');
const kategoriName = prefill?.kategoriName || urlParams.get('kategoriName');
let prefillSubIdsFinal = [];
let prefillKatIdsFinal = [];
if (unitId) {
window.__folderPrefillApplied = true;
window.__prefillFromSession = null;
$('.unit_kerja').val(null).trigger('change');
$('.sub_unit_kerja').val(null).trigger('change');
$('.kategori_dok').val(null).trigger('change');
const unitLabel = unitName || unitId;
const unitOption = new Option(unitLabel, unitId, true, true);
const selectedSubIds = subParam ? Array.from(new Set(subParam.split(',').filter(Boolean))) : [];
const subNames = subName ? subName.split(',').map(s => s.trim()).filter(Boolean) : [];
prefillSubIds = selectedSubIds;
prefillSubMeta = selectedSubIds.reduce((acc, id, idx) => {
let label = subNames[idx] || subNames[0] || id;
label = label.replace(/^\d+\s*\/\s*/, '');
acc[id] = label;
return acc;
}, {});
$('.unit_kerja').append(unitOption).trigger('change');
if (selectedSubIds.length) {
$('.sub_unit_kerja').val(selectedSubIds).trigger('change');
}
prefillSubIdsFinal = selectedSubIds;
}
if (katParam) {
const katIds = Array.from(new Set(katParam.split(',').filter(Boolean)));
if (katIds.length) {
$('.kategori_dok').val(katIds).trigger('change');
prefillKatIdsFinal = katIds;
} else if (kategoriName) {
const katOption = new Option(kategoriName, katParam, true, true);
$('.kategori_dok').append(katOption).trigger('change');
prefillKatIdsFinal = katParam ? [katParam] : [];
}
}
if ((unitId || subParam || katParam) && typeof index === 'function') {
index(prefillKatIdsFinal, unitId, prefillSubIdsFinal, '');
}
});
function loadSubUnitKerja(unitId){
function loadSubUnitKerja(unitId, selectedSubIds = [], selectedSubMeta = {}){
$('.sub_unit_kerja').empty().append('<option value="" disabled>-- Pilih Sub Unit Kerja --</option>');
$.ajax({
@ -73,10 +136,24 @@ function loadSubUnitKerja(unitId){
success: function(response) {
if (response?.data) {
response.data.forEach(unit => {
let selected = (authSubUnitKerja && unit.id === authSubUnitKerja.objectsubunitkerjapegawaifk);
let selected = false;
if (selectedSubIds.length) {
selected = selectedSubIds.includes(String(unit.id));
} else if (authSubUnitKerja) {
selected = unit.id === authSubUnitKerja.objectsubunitkerjapegawaifk;
}
const option = new Option(unit.name, unit.id, false, selected);
$('.sub_unit_kerja').append(option);
});
if (selectedSubIds.length) {
selectedSubIds.forEach(id => {
if ($(`.sub_unit_kerja option[value="${id}"]`).length === 0) {
const label = selectedSubMeta[id] || id;
const opt = new Option(label, id, false, true);
$('.sub_unit_kerja').append(opt);
}
});
}
$('.sub_unit_kerja').trigger('change');
}
}
@ -321,4 +398,3 @@ function selectOptionUnitKerjaV2(colCount) {
}
});
}

View File

@ -10,9 +10,18 @@ function renderTree(units, katDok, keyword) {
<li class="file-tree-li folder">
<input class="form-check-input" type="checkbox" data-select="unit" data-unit_id="${el?.id}">
<span class="fw-bolder">📂 ${el.name}</span>
<button type="button" class="btn btn-primary btn-sm" onclick="download(this)" data-part="unit" data-id="${el?.id}">
<i class="fa-solid fa-download"></i>
</button>
<div class="dropdown d-inline ms-1">
<button type="button" class="btn btn-sm btn-link text-decoration-none folder-menu-icon dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" aria-label="Menu folder">
<i class="fa-solid fa-ellipsis-vertical"></i>
</button>
<ul class="dropdown-menu">
<li>
<button type="button" class="dropdown-item folder-download" data-part="unit" data-id="${el?.id}">
<i class="fa-solid fa-download me-2"></i>Download
</button>
</li>
</ul>
</div>
${Array.isArray(el.sub_unit_kerja) && el.sub_unit_kerja.length > 0 ? `
<ul class="file-tree-ul mt-1 ms-2">
@ -21,9 +30,18 @@ function renderTree(units, katDok, keyword) {
\
<input class="form-check-input" type="checkbox" data-select="sub_unit" data-unit_id="${el.id}" data-sub_unit_id="${sub?.id}" >
<span class="fw-semibold">📂 ${sub.name}</span>
<button type="button" class="btn btn-outline-primary btn-sm ms-auto" onclick="download(this)" data-part="sub_unit" data-id="${sub?.id}">
<i class="fa-solid fa-download"></i>
</button>
<div class="dropdown d-inline ms-1">
<button type="button" class="btn btn-sm btn-link text-decoration-none folder-menu-icon dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" aria-label="Menu folder">
<i class="fa-solid fa-ellipsis-vertical"></i>
</button>
<ul class="dropdown-menu">
<li>
<button type="button" class="dropdown-item folder-download" data-part="sub_unit" data-id="${sub?.id}">
<i class="fa-solid fa-download me-2"></i>Download
</button>
</li>
</ul>
</div>
${Array.isArray(katDok) && katDok.length > 0 ? `
<ul class="file-tree-ul ms-2">
@ -41,20 +59,33 @@ function renderTree(units, katDok, keyword) {
${files.map(file => {
let fileName = file.file.split('/').pop();
const isPublic = String(file.permission_file).toLowerCase() === 'true' || file.permission_file === 1 || file.permission_file === '1';
console.log(file);
let statusLabel = '';
let statusClass = '';
if (!file.status_action) {
statusLabel = 'Pending';
statusClass = 'bg-warning text-dark';
} else if (isPublic) {
statusLabel = 'Umum';
statusClass = 'bg-success';
} else {
statusLabel = 'Internal Unit';
statusClass = 'bg-secondary';
}
return `
<li class="file-tree-li">
<div class="d-flex align-items-center gap-2 flex-wrap">
<span>📄</span>
<a href="#" class="file-link"
<a href="#" class="file-link ${!file?.status_action ? 'fst-italic' :''}"
data-file="${file?.file}"
data-fileName="${fileName || '-'}"
data-id="${file.file_directory_id}"
data-no_dokumen="${file.no_dokumen || '-'}"
data-tanggal_terbit="${file.tanggal_terbit || '-'}"
data-permission_file="${file.permission_file || '-'}">${fileName}</a>
<span class="badge ${isPublic ? 'bg-success' : 'bg-secondary'}">
${isPublic ? 'Umum' : 'Internal'}
<span class="badge ${statusClass}">
${statusLabel}
</span>
</div>
</li>
@ -94,6 +125,7 @@ function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], keyword =
if (Array.isArray(data?.data?.unitKerja)) {
file_tree.innerHTML = renderTree(data.data.unitKerja, data.data.katDok, keyword);
// Toggle buka/tutup folder
// Toggle buka/tutup folder
file_tree.querySelectorAll(".folder > span").forEach(span => {
span.addEventListener("click", () => {
@ -108,6 +140,7 @@ function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], keyword =
}
});
});
} else {
file_tree.innerHTML = `
<p style="color: primary">
@ -120,7 +153,19 @@ function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], keyword =
}
index();
const initialParams = new URLSearchParams(window.location.search);
const initialUnit = initialParams.get('unitKerja');
const initialSub = initialParams.get('subUnit');
const initialKat = initialParams.get('kategori');
const initialKeyword = initialParams.get('keyword');
const initialSubArr = initialSub ? initialSub.split(',').filter(Boolean) : [];
const initialKatArr = initialKat ? initialKat.split(',').filter(Boolean) : [];
if (initialUnit || initialSubArr.length || initialKatArr.length || initialKeyword) {
index(initialKatArr, initialUnit, initialSubArr, initialKeyword || '');
} else {
index();
}
function referesh(){
index()
@ -143,14 +188,16 @@ function searchData(){
return
}
index(kategori_dok, unitKerja, subUnitKerja, [], keyword);
index(kategori_dok, unitKerja, subUnitKerja, keyword);
}
let debounceTimer;
function debounceSearch(input) {
function debounceSearch(value) {
console.log(value);
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
searchFile(input.value.trim());
searchFile(value.trim());
}, 300);
}
@ -159,7 +206,8 @@ function searchFile(keyword){
let kategori_dok = $("#kategori_dok").val()
let unitKerja = $("#unit_kerja").val()
let subUnitKerja = $("#sub_unit_kerja").val()
index(kategori_dok, unitKerja, subUnitKerja, [], keyword);
index(kategori_dok, unitKerja, subUnitKerja, keyword);
}
@ -277,3 +325,10 @@ function downloadMultiple(){
})
}
// Klik menu download dari ikon ⋮
document.addEventListener('click', function (e) {
const btn = e.target.closest('.folder-download');
if (!btn) return;
download(btn);
});

View File

@ -77,13 +77,13 @@ function addForm(){
</select>
<small class="text-muted">Cari nama pegawai.</small>
</div>
<div class="col-md-8 mb-2" id="unit_akses_wrapper_${colCount}">
<div class="col-md-7 mb-2" id="unit_akses_wrapper_${colCount}">
<label>Unit Kerja</label>
<select class="form-control" name="data[${colCount}][unit_akses][]" id="unit_akses_${colCount}" multiple>
</select>
<small class="text-muted">Bisa pilih lebih dari satu.</small>
</div>
<div class="col-md-2">
<div class="col-md-1">
<button type="button" class="btn btn-danger mt-3 me-2" onclick="removeCol(${colCount})"><i class="fa-solid fa-trash"></i></button>
</div>

View File

@ -54,8 +54,13 @@ document.addEventListener('DOMContentLoaded', () => {
`;
return `
<tr>
<td>${aksi}</td>
<td>${item?.status_action !== "rejected" ? aksi : ''}</td>
<td>${item.no_dokumen || '-'}</td>
<td>
<button class="btn btn-sm ${item?.status_action !== "rejected" ? 'btn-warning' : 'btn-danger'} btn-warning ">
${item?.status_action !== "rejected" ? 'Pending' : 'Rejected'}
</button>
</td>
<td><a href="#" class="file-link"
data-file="${item.file}"
data-fileName="${item.fileName}"
@ -115,7 +120,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (pageData.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="4" class="text-center text-muted py-4">
<td colspan="7" class="text-center text-muted py-4">
Tidak ada data
</td>
</tr>

View File

@ -24,7 +24,7 @@
<div class="col-12 col-md-4">
<label class="form-label mb-1 d-block">Akses</label>
<div class="d-flex flex-wrap gap-3">
<div class="d-flex flex-wrap gap-2">
<div class="form-check">
<input class="form-check-input" type="radio"
name="data[0][akses]" id="akses_all_0" value="all" checked
@ -42,9 +42,15 @@
By Unit Akses
</label>
</div>
</div>
<small class="text-muted">Pilih salah satu.</small>
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="data[0][master_akses]" id="akses_unit_0" value="yes">
<label class="form-check-label" for="akses_unit_0">
Akses Master
</label>
</div>
</div>
</div>
<div class="col-md-4 mb-2 d-none" id="unit_akses_wrapper_0">
<label class="form-label">Unit Kerja</label>

View File

@ -24,7 +24,7 @@
</div>
<div class="col-12 col-md-2">
<label class="form-label mb-1 d-block">Akses</label>
<div class="d-flex flex-wrap gap-3">
<div class="d-flex flex-wrap gap-2">
<div class="form-check">
<input class="form-check-input" type="radio"
name="akses" id="akses_all_edit" value="all"
@ -41,8 +41,15 @@
By Unit Akses
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="master_akses" id="master_akses_edit" value="yes">
<label class="form-check-label">
Akses Master
</label>
</div>
</div>
<small class="text-muted">Pilih salah satu.</small>
</div>
<div class="col-12 col-md-6 d-none" id="unit_akses_wrapper_edit">
<label class="form-label">Unit Kerja</label>

View File

@ -42,6 +42,22 @@
user-select: none;
}
.folder-menu-icon {
cursor: pointer;
opacity: 0;
visibility: hidden;
padding: 0 4px;
}
.file-tree-li.folder:hover .folder-menu-icon {
opacity: 1;
visibility: visible;
}
.folder-menu-icon.dropdown-toggle::after {
display: none;
}
.collapsed > .file-tree-ul {
display: none;
}
@ -122,19 +138,18 @@
</button>
<div class="input-group input-group-sm" style="max-width:260px;">
<span class="input-group-text bg-white"><i class="fa fa-search text-muted"></i></span>
<input type="text" id="search_file" oninput="debounceSearch(this)" class="form-control" placeholder="Cari nama/no dokumen">
<input type="text" id="search_file" oninput="debounceSearch(this.value)" class="form-control" placeholder="Cari nama/no dokumen">
</div>
<div class="d-flex align-items-center gap-2 ms-auto">
<span class="badge bg-success">Umum</span>
<span class="badge bg-secondary">Internal</span>
</div>
</div>
<div id="file_tree"></div>
<div id="file_tree" style="max-height: 60vh; overflow-y:auto;"></div>
</div>
</div>
</div>
</div>
</div>
@ -147,6 +162,7 @@
const allAkses = @json($allAkses);
const authUnitKerja = @json(auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->unitKerja);
const authSubUnitKerja = @json(auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]);
window.__prefillFromSession = @json($prefillFilter ?? null);
function isPublic(permissionVal){
if(permissionVal === null || permissionVal === undefined) return false;
const val = String(permissionVal).toLowerCase();
@ -266,10 +282,6 @@
}
});
</script>
<script src="{{ ver('/js/dashboard/_init.js') }}"></script>

View File

@ -1,4 +1,41 @@
@extends('layout.main')
<style>
.table-fixed{ table-layout: fixed; width: 100%; }
.table-fixed th:nth-child(1), .table-fixed td:nth-child(1){ width: 140px; }
.table-fixed th:nth-child(2), .table-fixed td:nth-child(2){ width: 260px; }
.table-fixed th:nth-child(3), .table-fixed td:nth-child(3){ width: 220px; }
.table-fixed th:nth-child(4), .table-fixed td:nth-child(4){ width: 120px; }
.table-fixed th:nth-child(5), .table-fixed td:nth-child(5){ width: 150px; }
.file-cell{
white-space: normal;
word-break: break-word;
overflow-wrap: anywhere;
}
.folder-cell{
max-width: 220px;
}
.folder-badge{
white-space: normal !important;
word-break: break-word;
overflow-wrap: anywhere;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
max-width: 100%;
text-align: left;
line-height: 1.3;
padding: .35rem .5rem;
}
.folder-link-sm{
font-size: 13px;
text-decoration: underline;
}
</style>
@section('body_main')
<div class="row">
<div class="col-md-12">
@ -30,8 +67,8 @@
</div>
<div class="small text-muted ms-md-auto" id="tableSummary">Memuat data...</div>
</div>
<div class="table-responsive" style="max-height: 100vh; overflow-y:auto;">
<table class="table table-sm table-hover align-middle mb-0" id="lastUpdatedTable">
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
<thead>
<tr>
<th>Nomor Surat</th>
@ -100,12 +137,29 @@
const fileName = parts.pop() || '-';
const folderPath = parts.join('/') || '-';
const publicDoc = isPublic(item.permission_file);
const unitName = parts[0] || '';
const subName = parts[1] || '';
const kategoriName = parts[2] || '';
let statusLabel = '';
let statusClass = '';
if (!item.status_action) {
statusLabel = 'Pending';
statusClass = 'bg-warning text-dark';
} else if (publicDoc) {
statusLabel = 'Umum';
statusClass = 'bg-success';
} else {
statusLabel = 'Internal Unit';
statusClass = 'bg-secondary';
}
return `
<tr>
<td class="text-nowrap">${item.no_dokumen || '-'}</td>
<td>
<td class="file-cell">
<span class="me-1">📄</span>
<a href="#" class="file-link"
<a href="#" class="file-link ${statusLabel === "Pending" ? 'fst-italic' : ''}"
data-file="${item.file}"
data-fileName="${fileName}"
data-id="${item.file_directory_id}"
@ -113,10 +167,22 @@
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
data-permission_file="${item.permission_file || '-'}">${fileName}</a>
</td>
<td class="text-break"><span class="badge bg-light text-dark fw-semibold">${folderPath}</span></td>
<td class="folder-cell">
<a href="#"
class="text-dark fw-semibold folder-prefill folder-link-sm ${statusLabel === "Pending" ? 'fst-italic' : ''}"
title="${folderPath}"
data-unit_id="${item.id_unit_kerja || ''}"
data-sub_id="${item.id_sub_unit_kerja || ''}"
data-kategori_id="${item.master_kategori_directory_id || ''}"
data-unit_name="${unitName}"
data-sub_name="${subName}"
data-kategori_name="${kategoriName}">
${folderPath}
</a>
</td>
<td>
<span class="badge ${publicDoc ? 'bg-success' : 'bg-secondary'}">
${publicDoc ? 'Umum' : 'Internal Unit'}
<span class="badge ${statusClass}">
${statusLabel}
</span>
</td>
<td class="text-nowrap">${formatTanggal(item.entry_at)}</td>
@ -234,6 +300,38 @@
}
fetchData()
document.addEventListener('click', function (e) {
const btn = e.target.closest('.folder-prefill');
if (!btn) return;
e.preventDefault();
const payload = {
unitId: btn.getAttribute('data-unit_id') || '',
subId: btn.getAttribute('data-sub_id') || '',
kategoriId: btn.getAttribute('data-kategori_id') || '',
unitName: btn.getAttribute('data-unit_name') || '',
subName: btn.getAttribute('data-sub_name') || '',
kategoriName: btn.getAttribute('data-kategori_name') || '',
};
fetch('/dashboard/prefill', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'X-Requested-With': 'XMLHttpRequest'
},
body: JSON.stringify(payload)
})
.then(res => {
if (!res.ok) throw new Error('Gagal set filter');
window.location.href = '/';
})
.catch(() => {
Swal.fire({ icon: 'error', title: 'Gagal', text: 'Tidak bisa buka folder' });
});
});
let colCount = 1;
$(document).ready(function() {
$('.unit_kerja').select2({

View File

@ -1,147 +1,177 @@
<aside class="left-sidebar">
<!-- Sidebar scroll-->
<div>
<div class="brand-logo d-flex align-items-center justify-content-between">
<a href="/" class="text-nowrap logo-img">
<img src="logo/logo_rsabhk.png" alt="rsabhk" width="180" class="mt-2"/>
</a>
<div class="close-btn d-xl-none d-block sidebartoggler cursor-pointer" id="sidebarCollapse">
<i class="ti ti-x fs-6"></i>
</div>
</div>
<!-- Sidebar navigation-->
<nav class="sidebar-nav scroll-sidebar" data-simplebar="">
<ul id="sidebarnav">
<li class="nav-small-cap">
<iconify-icon icon="solar:menu-dots-linear" class="nav-small-cap-icon fs-4"></iconify-icon>
<span class="hide-menu">Home</span>
</li>
<li class="sidebar-item">
<a class="sidebar-link" href="/" aria-expanded="false">
<i class="ti ti-dashboard"></i>
<span class="hide-menu">Dashboard</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link" href="/new" aria-expanded="false">
<i class="ti ti-layout-dashboard"></i>
<span class="hide-menu">Dashboard V2</span>
</a>
</li>
<!-- ---------------------------------- -->
<!-- Dashboard -->
<!-- ---------------------------------- -->
<li class="sidebar-item">
<a class="sidebar-link justify-content-between"
href="/master-kategori" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<span class="d-flex">
<i class="ti ti-file"></i>
</span>
<span class="hide-menu">Master Kategori</span>
</div>
<div>
{{-- Logo --}}
<div class="brand-logo d-flex align-items-center justify-content-between">
<a href="{{ url('/') }}" class="text-nowrap logo-img">
<img src="{{ asset('logo/logo_rsabhk.png') }}" alt="rsabhk" width="180" class="mt-2" />
</a>
</a>
</li>
{{-- <li class="sidebar-item">
<a class="sidebar-link justify-content-between"
href="/master-klasifikasi" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<span class="d-flex">
<i class="ti ti-file"></i>
</span>
<span class="hide-menu">Master Klasifikasi</span>
</div>
</a>
</li> --}}
<li class="sidebar-item">
<a class="sidebar-link justify-content-between"
href="/akses" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<span class="d-flex">
<i class="ti ti-lock-access"></i>
</span>
<span class="hide-menu">Akses</span>
</div>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link justify-content-between"
href="/log-activity" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<span class="d-flex">
<i class="ti ti-activity"></i>
</span>
<span class="hide-menu">Log Aktivitas</span>
</div>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link justify-content-between"
href="/recap" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<span class="d-flex">
<i class="ti ti-report-analytics"></i>
</span>
<span class="hide-menu">Data Rekap</span>
</div>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link d-flex align-items-center justify-content-between"
href="/pending-file" aria-expanded="false">
<!-- Left -->
<div class="d-flex align-items-center gap-3">
<i class="ti ti-clock sidebar-icon"></i>
<span class="hide-menu">Persetujuan</span>
</div>
<!-- Right Badge -->
<span class="badge bg-danger rounded-pill sidebar-badge" id="pendingCountBadge">
0
</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link justify-content-between"
href="/master-persetujuan" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<span class="d-flex">
<i class="ti ti-report-analytics"></i>
</span>
<span class="hide-menu">Master Persetujuan</span>
</div>
</a>
</li>
</ul>
</nav>
<!-- End Sidebar navigation -->
<div class="close-btn d-xl-none d-block sidebartoggler cursor-pointer" id="sidebarCollapse">
<i class="ti ti-x fs-6"></i>
</div>
<!-- End Sidebar scroll-->
</aside>
<script>
function countData(){
const badge = document.getElementById('pendingCountBadge');
if (!badge) return;
fetch('/data/count-pending')
.then(res => res.json())
.then(data => {
const count = data?.count ?? 0;
badge.textContent = count;
if (count <= 0) {
badge.classList.add('d-none');
} else {
badge.classList.remove('d-none');
}
})
.catch(() => {
badge.classList.add('d-none');
});
}
countData();
</script>
</div>
{{-- Sidebar nav --}}
@php
$openMaster = request()->is('akses*') || request()->is('master-kategori*') || request()->is('master-persetujuan*');
@endphp
<nav class="sidebar-nav scroll-sidebar" data-simplebar="">
<ul id="sidebarnav">
{{-- HOME --}}
<li class="nav-small-cap"><span class="hide-menu">Home</span></li>
<li class="sidebar-item">
<a class="sidebar-link" href="{{ url('/') }}" aria-expanded="false">
<i class="ti ti-dashboard"></i>
<span class="hide-menu">Dashboard</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link" href="{{ url('/new') }}" aria-expanded="false">
<i class="ti ti-layout-dashboard"></i>
<span class="hide-menu">Dashboard V2</span>
</a>
</li>
{{-- AKTIVITAS --}}
<li class="nav-small-cap"><span class="hide-menu">Aktivitas</span></li>
<li class="sidebar-item">
<a class="sidebar-link d-flex align-items-center justify-content-between"
href="{{ url('/log-activity') }}" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<i class="ti ti-activity"></i>
<span class="hide-menu">Log Aktivitas</span>
</div>
</a>
</li>
@if($authUnit = auth()->user()->masterPersetujuan)
<li class="sidebar-item">
<a class="sidebar-link d-flex align-items-center justify-content-between"
href="{{ url('/pending-file') }}" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<i class="ti ti-clock"></i>
<span class="hide-menu">Persetujuan</span>
</div>
<span class="badge bg-danger rounded-pill d-none" id="pendingCountBadge">0</span>
</a>
</li>
@endif
{{-- RECAP --}}
<li class="nav-small-cap"><span class="hide-menu">Recap</span></li>
<li class="sidebar-item">
<a class="sidebar-link d-flex align-items-center justify-content-between"
href="{{ url('/recap') }}" aria-expanded="false">
<div class="d-flex align-items-center gap-3">
<i class="ti ti-report-analytics"></i>
<span class="hide-menu">Data Rekap</span>
</div>
</a>
</li>
{{-- MASTER --}}
@if(auth()->user()->akses && auth()->user()->akses->master_akses)
<li class="nav-small-cap"><span class="hide-menu">Master</span></li>
<li class="sidebar-item has-sub {{ $openMaster ? 'open' : '' }}">
<a class="sidebar-link d-flex align-items-center justify-content-between"
href="#menu-master"
data-bs-toggle="collapse"
role="button"
aria-expanded="{{ $openMaster ? 'true' : 'false' }}"
aria-controls="menu-master">
<div class="d-flex align-items-center gap-3">
<i class="ti ti-report-analytics"></i>
<span class="hide-menu">Master</span>
</div>
<i class="ti ti-chevron-right fs-6 sidebar-arrow"></i>
</a>
<ul class="collapse sidebar-submenu {{ $openMaster ? 'show' : '' }}" id="menu-master">
<li class="sidebar-item">
<a href="{{ url('/akses') }}" class="sidebar-link">
<span class="hide-menu">Akses</span>
</a>
</li>
<li class="sidebar-item">
<a href="{{ url('/master-kategori') }}" class="sidebar-link">
<span class="hide-menu">Kategori</span>
</a>
</li>
<li class="sidebar-item">
<a href="{{ url('/master-persetujuan') }}" class="sidebar-link">
<span class="hide-menu">Persetujuan</span>
</a>
</li>
</ul>
</li>
@endif
</ul>
</nav>
</div>
</aside>
{{-- Styling kecil biar submenu rapi + arrow muter --}}
<style>
.sidebar-submenu { padding-left: 2.7rem; }
.sidebar-submenu .sidebar-link { padding: 6px 0; font-size: 13px; opacity: .9; }
.sidebar-item.has-sub .sidebar-arrow { transition: transform .2s ease; }
.sidebar-item.has-sub.open .sidebar-arrow { transform: rotate(90deg); }
</style>
<script>
const badge = document.getElementById('pendingCountBadge');
async function countData() {
if (!badge) return;
try {
const res = await fetch('/data/count-pending', {
headers: { 'Accept': 'application/json' }
});
if (!res.ok) throw new Error('Request failed: ' + res.status);
const data = await res.json();
const count = Number(data?.count ?? 0);
badge.textContent = count;
badge.classList.toggle('d-none', count <= 0);
} catch (e) {
badge.classList.add('d-none');
}
}
countData();
setInterval(countData, 60000);
const masterCollapse = document.getElementById('menu-master');
const masterItem = masterCollapse
? masterCollapse.closest('.sidebar-item.has-sub')
: null;
if (masterItem && masterCollapse) {
masterCollapse.addEventListener('shown.bs.collapse', function () {
masterItem.classList.add('open');
});
masterCollapse.addEventListener('hidden.bs.collapse', function () {
masterItem.classList.remove('open');
});
}
</script>

View File

@ -44,8 +44,11 @@
<table class="table table-sm table-hover align-middle mb-0" id="lastUpdatedTable">
<thead>
<tr>
@if(auth()->user()->masterPersetujuan)
<th>Aksi</th>
@endif
<th>No Dokumen</th>
<th>Status</th>
<th>File</th>
<th>Folder</th>
<th>Unit/Sub Unit</th>

View File

@ -18,15 +18,20 @@ Route::middleware(['auth'])->group(function(){
Route::get('/file-preview/{id}', [DashboardController::class, 'dataPdf']);
Route::post('/upload', [DashboardController::class, 'store']);
Route::get('/data-unit-kerja', [DashboardController::class, 'dataUnitKerja']);
Route::post('/dashboard/prefill', [DashboardController::class, 'setDashboardPrefill']);
Route::resource('/master-kategori', MasterKategoriController::class);
Route::get('datatable/master-kategori', [MasterKategoriController::class, 'datatable']);
Route::resource('/master-klasifikasi', MasterKlasifikasiController::class);
Route::get('datatable/master-klasifikasi', [MasterKlasifikasiController::class, 'datatable']);
Route::resource('/akses', AksesFileController::class);
Route::get('datatable/akses', [AksesFileController::class, 'datatable']);
Route::get('/select-pegawai', [AksesFileController::class, 'optionPegawai']);
Route::get('/select-unit-kerja-option', [AksesFileController::class, 'optionUnitKerja']);
Route::middleware(['akses.master'])->group(function () {
Route::resource('/akses', AksesFileController::class);
Route::get('datatable/akses', [AksesFileController::class, 'datatable']);
Route::resource('/master-persetujuan', masterPersetujuanController::class)->only(['index','store','show','update','destroy']);
Route::get('datatable/master-persetujuan', [masterPersetujuanController::class, 'datatable']);
Route::resource('/master-kategori', MasterKategoriController::class);
Route::get('datatable/master-kategori', [MasterKategoriController::class, 'datatable']);
Route::resource('/master-klasifikasi', MasterKlasifikasiController::class);
Route::get('datatable/master-klasifikasi', [MasterKlasifikasiController::class, 'datatable']);
});
Route::get('/select-unit-kerja', [DashboardController::class, 'OptionUnitKerja']);
Route::get('/select-sub-unit-kerja/{id}', [DashboardController::class, 'optionSubUnitKerja']);
@ -42,14 +47,15 @@ Route::middleware(['auth'])->group(function(){
Route::get('/recap', [DashboardController::class, 'recapView']);
Route::get('/data/recap', [DashboardController::class, 'recapData']);
Route::get('/pending-file', [DashboardController::class, 'pendingFile']);
Route::get('/datatable/pending-file', [DashboardController::class, 'dataPendingFile']);
Route::post('/pending-file/{id}/approve', [DashboardController::class, 'approvePendingFile']);
Route::post('/pending-file/{id}/reject', [DashboardController::class, 'rejectPendingFile']);
Route::get('/data/count-pending', [DashboardController::class, 'countDataPending']);
Route::resource('/master-persetujuan', masterPersetujuanController::class)->only(['index','store','show','update','destroy']);
Route::get('datatable/master-persetujuan', [masterPersetujuanController::class, 'datatable']);
Route::middleware(['master.persetujuan'])->group(function () {
Route::get('/pending-file', [DashboardController::class, 'pendingFile']);
Route::get('/datatable/pending-file', [DashboardController::class, 'dataPendingFile']);
Route::post('/pending-file/{id}/approve', [DashboardController::class, 'approvePendingFile']);
Route::post('/pending-file/{id}/reject', [DashboardController::class, 'rejectPendingFile']);
Route::get('/data/count-pending', [DashboardController::class, 'countDataPending']);
});
});
Route::get('/login', [AuthController::class, 'index'])->name('login');