progress revisi

This commit is contained in:
JokoPrasetio 2026-06-15 16:03:08 +07:00
parent c750177fee
commit a0be3a4c74
11 changed files with 647 additions and 132 deletions

View File

@ -628,7 +628,6 @@ class DashboardController extends Controller
'pegawai_id_entry' => auth()->user()->dataUser->id ?? 1,
'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap ?? 'tes',
];
dd($payload);
if($file){
$imageName = $file->getClientOriginalName();
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}/{$nama_klasifikasi}";
@ -714,26 +713,98 @@ class DashboardController extends Controller
], 200);
}
public function deleteFile(string $id){
public function deleteFile(string $id)
{
DB::connection('dbDirectory')->beginTransaction();
try {
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
->where('objectpegawaifk', auth()->user()?->dataUser?->id)
->first();
$mapping = $this->getDeleteNotificationMapping();
$data = FileDirectory::where('file_directory_id', $id)->first();
if (!$data) {
return response()->json([
'success' => false,
'message' => 'File tidak ditemukan'
]);
], 404);
}
$fileInfo = pathinfo($data->file);
$newFileName = $fileInfo['filename'] . '_deleted.' . ($fileInfo['extension'] ?? '');
$this->deleteFileRecord($data, $mapping);
DB::connection('dbDirectory')->commit();
return response()->json([
'success' => true,
'message' => 'Berhasil menghapus data'
]);
} catch (\Throwable $th) {
DB::connection('dbDirectory')->rollBack();
return response()->json([
'success' => false,
'message' => 'Gagal menghapus data'
], 500);
}
}
public function deleteFiles(Request $request)
{
$ids = collect($request->input('ids', []))
->filter(fn ($id) => filled($id))
->map(fn ($id) => (string) $id)
->unique()
->values();
if ($ids->isEmpty()) {
return response()->json([
'success' => false,
'message' => 'Tidak ada dokumen yang dipilih'
], 422);
}
DB::connection('dbDirectory')->beginTransaction();
try {
$mapping = $this->getDeleteNotificationMapping();
$files = FileDirectory::whereIn('file_directory_id', $ids)->get()->keyBy('file_directory_id');
foreach ($ids as $id) {
$data = $files->get($id);
if (!$data) {
throw new \RuntimeException("File {$id} tidak ditemukan");
}
$this->deleteFileRecord($data, $mapping);
}
DB::connection('dbDirectory')->commit();
return response()->json([
'success' => true,
'message' => 'Berhasil menghapus ' . $ids->count() . ' dokumen'
]);
} catch (\Throwable $th) {
DB::connection('dbDirectory')->rollBack();
return response()->json([
'success' => false,
'message' => 'Gagal menghapus dokumen'
], 500);
}
}
private function getDeleteNotificationMapping(): ?MappingUnitKerjaPegawai
{
return MappingUnitKerjaPegawai::where('statusenabled', true)
->where('objectpegawaifk', auth()->user()?->dataUser?->id)
->first();
}
private function deleteFileRecord(FileDirectory $data, ?MappingUnitKerjaPegawai $mapping): void
{
$fileInfo = pathinfo((string) $data->file);
$extension = $fileInfo['extension'] ?? '';
$newFileName = ($fileInfo['filename'] ?? 'dokumen') . '_deleted' . ($extension !== '' ? '.' . $extension : '');
$dirName = $fileInfo['dirname'] ?? '';
$newPath = ($dirName && $dirName !== '.') ? ($dirName . '/' . $newFileName) : $newFileName;
$disk = Storage::disk('s3');
if ($disk->exists($data->file)) {
// S3 tidak bisa rename langsung, jadi copy lalu delete
$disk->copy($data->file, $newPath);
$disk->delete($data->file);
}
@ -745,27 +816,22 @@ class DashboardController extends Controller
$uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna';
$docNumber = $data->no_dokumen ? 'nomor ' . $data->no_dokumen : $data->nama_dokumen;
$payloadNotification = [
'created_at' => now(),
'text_notifikasi' => "Dokumen {$docNumber} . dihapus oleh {$uploaderName}.",
'url' => '/pending-file',
'is_read' => false,
'pegawai_id' => $mapping?->objectatasanlangsungfk,
];
$notifiedPegawaiIds = collect([
$mapping?->objectatasanlangsungfk,
$mapping?->objectpejabatpenilaifk,
])->filter()->unique();
Notifkasi::create($payloadNotification);
if($mapping->objectpejabatpenilaifk){
$payloadNotification = [
foreach ($notifiedPegawaiIds as $pegawaiId) {
Notifkasi::create([
'created_at' => now(),
'text_notifikasi' => "Dokumen {$docNumber}. dihapus oleh {$uploaderName}.",
'url' => '/pending-file',
'is_read' => false,
'pegawai_id' => $mapping?->objectpejabatpenilaifk,
];
Notifkasi::create($payloadNotification);
'pegawai_id' => $pegawaiId,
]);
}
$payloadLog = [
LogActivity::create([
'file_directory_id' => $data->file_directory_id,
'pegawai_id_entry' => $data->pegawai_id_entry,
'pegawai_nama_entry' => $data->pegawai_nama_entry,
@ -775,24 +841,10 @@ class DashboardController extends Controller
'nama_dokumen' => $data->nama_dokumen ?? null,
'no_dokumen' => $data->no_dokumen ?? null,
'mod_change' => null,
'id_unit_kerja' => $data ? $data->id_unit_kerja : null,
'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null,
'id_unit_kerja' => $data->id_unit_kerja,
'id_sub_unit_kerja' => $data->id_sub_unit_kerja,
'action_type' => 'Menghapus Dokumen',
];
LogActivity::create($payloadLog);
DB::connection('dbDirectory')->commit();
return response()->json([
'success' => true,
'message' => 'Berhasil menghapus data'
]);
} catch (\Throwable $th) {
DB::connection('dbDirectory')->rollBack();
return response()->json([
'success' => false,
'message' => 'Gagal menghapus data'
]);
}
}
public function optionSubUnitKerja(string $id){
@ -969,6 +1021,7 @@ class DashboardController extends Controller
public function downloadFile(string $id)
{
try {
$data = FileDirectory::where('file_directory_id', $id)
->where('statusenabled', true)
->first();
@ -1031,6 +1084,13 @@ class DashboardController extends Controller
});
return $response;
} catch (\Throwable $th) {
return back()->with([
'status' => false,
'message' => 'terdapat kesalahan coba lagi nanti'
]);
}
}
public function dataUmum(){
@ -2002,6 +2062,76 @@ class DashboardController extends Controller
}
}
public function recommendDeleteFile(Request $request, string $id)
{
try {
DB::connection('dbDirectory')->beginTransaction();
$data = FileDirectory::where('file_directory_id', $id)
->where('statusenabled', true)
->first();
if (!$data) {
return response()->json([
'status' => false,
'message' => 'Data tidak ditemukan'
], 404);
}
$note = trim((string) $request->input('note', ''));
if ($note === '') {
return response()->json([
'status' => false,
'message' => 'Catatan rekomendasi wajib diisi'
], 422);
}
$actionName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna';
$docNumber = $data->no_dokumen ? 'nomor ' . $data->no_dokumen : ($data->nama_dokumen ?? 'dokumen');
Notifkasi::create([
'created_at' => now(),
'text_notifikasi' => "Dokumen {$docNumber} direkomendasikan untuk dihapus oleh {$actionName}. Catatan: {$note}",
'url' => '/pengajuan-file',
'is_read' => false,
'pegawai_id' => $data->pegawai_id_entry,
]);
LogActivity::create([
'file_directory_id' => $data->file_directory_id,
'pegawai_id_entry' => $data->pegawai_id_entry,
'pegawai_nama_entry' => $data->pegawai_nama_entry,
'entry_at' => now(),
'file' => $data->file,
'statusenabled' => true,
'nama_dokumen' => $data->nama_dokumen ?? null,
'no_dokumen' => $data->no_dokumen ?? null,
'id_unit_kerja' => $data->id_unit_kerja,
'id_sub_unit_kerja' => $data->id_sub_unit_kerja,
'action_type' => 'Rekomendasi Hapus Dokumen',
]);
$data->update([
'hapus_turt' => true,
'note_hapus_turt' => $note,
'turt_by' => auth()->user()->objectpegawaifk,
'turt_at' => now()
]);
DB::connection('dbDirectory')->commit();
return response()->json([
'status' => true,
'message' => 'Rekomendasi hapus berhasil dikirim'
], 200);
} catch (\Throwable $th) {
DB::connection('dbDirectory')->rollBack();
return response()->json([
'status' => false,
'message' => $th->getMessage()
], 500);
}
}
public function countDataPending(){
try {
$objectpegawaifk = MappingUnitKerjaPegawai::query()

View File

@ -12,7 +12,6 @@ class EnsureMasterPersetujuan
{
$user = $request->user();
$hasAccess = $user && $user->masterPersetujuan;
if (!$hasAccess) {
abort(403, 'Tidak memiliki akses.');
}

View File

@ -11,9 +11,9 @@ class SubUnitKerja extends Model
public $timestamps = false;
protected $primaryKey = 'id';
protected $guarded = ['id'];
protected $with = ['fileDirectory'];
// protected $with = ['fileDirectory'];
public function fileDirectory(){
return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true);
}
// public function fileDirectory(){
// return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true);
// }
}

View File

@ -11,10 +11,10 @@ class UnitKerja extends Model
public $timestamps = false;
protected $primaryKey = 'id';
protected $guarded = ['id'];
protected $with = ['subUnitKerja'];
// protected $with = ['subUnitKerja'];
public function subUnitKerja(){
return $this->hasMany(SubUnitKerja::class, 'objectunitkerjapegawaifk', 'id')->where('statusenabled', true)->select('id', 'objectunitkerjapegawaifk', 'name');
}
// public function subUnitKerja(){
// return $this->hasMany(SubUnitKerja::class, 'objectunitkerjapegawaifk', 'id')->where('statusenabled', true)->select('id', 'objectunitkerjapegawaifk', 'name');
// }
}

View File

@ -13,6 +13,12 @@ document.addEventListener('DOMContentLoaded', () => {
const titleEl = document.getElementById('pengajuanTitle');
const tabPengajuanEl = document.getElementById('tabPengajuan');
const tabHistoryEl = document.getElementById('tabHistory');
const selectAllCheckbox = document.getElementById('selectAllPengajuan');
const bulkDeleteBtn = document.getElementById('bulkDeleteBtn');
const clearSelectionBtn = document.getElementById('clearSelectionBtn');
const selectedCountEl = document.getElementById('selectedCount');
const bulkActionsEl = document.getElementById('pengajuanBulkActions');
const deleteDataEl = document.getElementById('deleteData');
const formCreate = document.getElementById('formFile');
const modalCreate = document.getElementById('modalCreateFile');
let colCount = 1;
@ -20,6 +26,7 @@ document.addEventListener('DOMContentLoaded', () => {
const editForm = document.getElementById('formEditPengajuanFile');
const editUnitSelect = $('#edit_id_unit_kerja');
const editSubUnitSelect = $('#edit_id_sub_unit_kerja');
const selectedIds = new Set();
if (pageSizeSelect) {
const initialSize = parseInt(pageSizeSelect.value);
@ -61,6 +68,41 @@ document.addEventListener('DOMContentLoaded', () => {
});
}
function getSelectableIdsOnPage(){
return (tableState.data || []).map((row) => String(row.file_directory_id));
}
function updateSelectAllState(){
if (!selectAllCheckbox) return;
if (tableState.mode === 'history') {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
selectAllCheckbox.disabled = true;
return;
}
const pageIds = getSelectableIdsOnPage();
if (pageIds.length === 0) {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
selectAllCheckbox.disabled = true;
return;
}
selectAllCheckbox.disabled = false;
const selectedOnPage = pageIds.filter((id) => selectedIds.has(id)).length;
selectAllCheckbox.checked = selectedOnPage > 0 && selectedOnPage === pageIds.length;
selectAllCheckbox.indeterminate = selectedOnPage > 0 && selectedOnPage < pageIds.length;
}
function updateSelectionUI(){
const count = selectedIds.size;
if (selectedCountEl) selectedCountEl.textContent = String(count);
if (bulkDeleteBtn) bulkDeleteBtn.disabled = count === 0 || tableState.mode === 'history';
if (clearSelectionBtn) clearSelectionBtn.disabled = count === 0 || tableState.mode === 'history';
updateSelectAllState();
}
function buildRow(item){
let tanggal = item.entry_at ? formatTanggal(item.entry_at) : '-';
let tanggalExp = item.tgl_expired ? formatTanggal(item.tgl_expired) : '-';
@ -69,6 +111,8 @@ document.addEventListener('DOMContentLoaded', () => {
const isRejected = item?.status_action === 'rejected';
const showEdit = !isApproved;
const showInfo = isRejected;
const id = String(item.file_directory_id);
const checked = selectedIds.has(id);
const aksi = `
<div class="d-flex gap-1">
<button href="#" class="btn btn-sm btn-primary" onclick="infoDok(this)"
@ -93,7 +137,13 @@ document.addEventListener('DOMContentLoaded', () => {
</div>
`;
return `
<tr>
<tr class="${checked ? 'table-active' : ''}">
<td class="text-center">
<input type="checkbox"
class="form-check-input row-select"
data-id="${id}"
${checked ? 'checked' : ''}>
</td>
<td>${aksi}</td>
<td>${item.no_dokumen || '-'}</td>
<td>
@ -168,6 +218,41 @@ document.addEventListener('DOMContentLoaded', () => {
return (tableState.data || []).find((row) => String(row.file_directory_id) === String(id));
}
function deleteDocuments(ids, successMessage){
return fetch('/delete-file/bulk', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
},
body: JSON.stringify({ ids })
}).then(async(res) => {
const data = await res.json();
if (!res.ok || !data?.success) {
throw new Error(data?.message || 'Gagal menghapus dokumen.');
}
ids.forEach((id) => selectedIds.delete(String(id)));
if (window.idDirectory && ids.includes(String(window.idDirectory))) {
window.idDirectory = null;
window.currentFile = null;
if (deleteDataEl) deleteDataEl.classList.add('d-none');
const modalEl = document.getElementById('previewModal');
const modalInstance = modalEl ? bootstrap.Modal.getInstance(modalEl) : null;
modalInstance?.hide();
}
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || successMessage,
timer: 1500,
showConfirmButton: false
});
fetchData();
});
}
function renderPagination(totalPages){
const activeState = tableState.mode === 'history' ? historyState : tableState;
const paginationEl = tableState.mode === 'history' ? paginationHistory : paginationPengajuan;
@ -218,7 +303,7 @@ document.addEventListener('DOMContentLoaded', () => {
const activeState = isHistoryMode ? historyState : tableState;
const pageData = activeState.data || [];
const targetBody = isHistoryMode ? tbodyHistory : tbodyPengajuan;
const colSpan = isHistoryMode ? 9 : 10;
const colSpan = isHistoryMode ? 9 : 11;
const rowBuilder = isHistoryMode ? buildHistoryRow : buildRow;
if (pageData.length === 0) {
targetBody.innerHTML = `
@ -239,6 +324,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
renderPagination(activeState.lastPage || 1);
updateSelectionUI();
}
let searchDebounce;
@ -264,6 +350,7 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementById('tableSearch').value = '';
startDateInput.value = '';
endDateInput.value = '';
selectedIds.clear();
tableState.page = 1;
historyState.page = 1;
fetchData();
@ -278,10 +365,18 @@ document.addEventListener('DOMContentLoaded', () => {
if (titleEl) {
titleEl.textContent = tableState.mode === 'history' ? 'Log History' : 'Data Pengajuan';
}
document.body.dataset.pengajuanMode = tableState.mode;
if (tabPengajuanEl && tabHistoryEl) {
tabPengajuanEl.classList.toggle('d-none', tableState.mode === 'history');
tabHistoryEl.classList.toggle('d-none', tableState.mode !== 'history');
}
if (bulkActionsEl) {
bulkActionsEl.classList.toggle('d-none', tableState.mode === 'history');
}
if (deleteDataEl && tableState.mode === 'history') {
deleteDataEl.classList.add('d-none');
}
updateSelectionUI();
}
if (tabsEl) {
@ -297,6 +392,63 @@ document.addEventListener('DOMContentLoaded', () => {
});
}
if (tbodyPengajuan) {
tbodyPengajuan.addEventListener('change', (e) => {
const target = e.target;
if (!target.classList.contains('row-select')) return;
const id = target.getAttribute('data-id');
if (!id) return;
if (target.checked) selectedIds.add(id);
else selectedIds.delete(id);
const row = target.closest('tr');
if (row) row.classList.toggle('table-active', target.checked);
updateSelectionUI();
});
}
if (selectAllCheckbox) {
selectAllCheckbox.addEventListener('change', () => {
const pageIds = getSelectableIdsOnPage();
if (selectAllCheckbox.checked) {
pageIds.forEach((id) => selectedIds.add(id));
} else {
pageIds.forEach((id) => selectedIds.delete(id));
}
renderTable();
});
}
if (clearSelectionBtn) {
clearSelectionBtn.addEventListener('click', () => {
selectedIds.clear();
renderTable();
});
}
if (bulkDeleteBtn) {
bulkDeleteBtn.addEventListener('click', () => {
if (selectedIds.size === 0) return;
const ids = Array.from(selectedIds);
Swal.fire({
title: 'Hapus dokumen terpilih?',
text: `Total ${ids.length} dokumen akan dihapus.`,
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Hapus',
cancelButtonText: 'Batal'
}).then((result) => {
if (!result.isConfirmed) return;
deleteDocuments(ids, 'Dokumen berhasil dihapus.').catch((err) => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
});
}
function fetchData(){
if (summaryEl) summaryEl.textContent = 'Memuat data...';
const activeState = tableState.mode === 'history' ? historyState : tableState;
@ -360,6 +512,9 @@ document.addEventListener('DOMContentLoaded', () => {
permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit';
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
}
if (deleteDataEl) {
deleteDataEl.classList.remove('d-none');
}
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = `<div id="pdfWrap" style="height:500px; overflow:auto; background:#f7f7f7; padding:8px;">
<div id="pdfPages"></div>`;
@ -1076,6 +1231,7 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
});
});
document.addEventListener('click', function(e){
if(e.target.matches('.file-link')){
@ -1105,6 +1261,10 @@ document.addEventListener('click', function(e){
const publicDoc = isPublic(permissionFile);
permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit';
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
}
const deleteDataEl = document.getElementById('deleteData');
if (deleteDataEl) {
deleteDataEl.classList.toggle('d-none', document.body.dataset.pengajuanMode !== 'pengajuan');
}
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = `<div id="pdfWrap" style="height:500px; overflow:auto; background:#f7f7f7; padding:8px;">
@ -1119,6 +1279,56 @@ document.addEventListener('click', function(e){
if(e.target.matches('#btn-view-full')){
window.open(`/full-preview/${idDirectory}`, '_blank');
}
if(e.target.matches('#delete-file')){
if(!idDirectory){
Swal.fire({
icon: 'warning',
title: 'Pilih dokumen',
text: 'Dokumen belum dipilih.'
});
return;
}
Swal.fire({
title: 'Hapus dokumen ini?',
text: 'Dokumen yang dihapus tidak akan tampil lagi.',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Hapus',
cancelButtonText: 'Batal'
}).then((result) => {
if (!result.isConfirmed) return;
fetch('/delete-file/bulk', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
},
body: JSON.stringify({ ids: [String(idDirectory)] })
}).then(async(res) => {
const data = await res.json();
if (!res.ok || !data?.success) {
throw new Error(data?.message || 'Gagal menghapus dokumen.');
}
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || 'Dokumen berhasil dihapus.',
timer: 1500,
showConfirmButton: false
}).then(() => {
window.location.reload();
});
}).catch((err) => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
}
})
function isPublic(permissionVal){
if(permissionVal === null || permissionVal === undefined) return false;

View File

@ -226,7 +226,8 @@
<script>
const katDok = @json($katDok);
const authUnitKerja = @json(auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->unitKerja);
const authSubUnitKerja = @json(auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]->sub_unit_kerja);
// const authSubUnitKerja = @json(auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]->sub_unit_kerja);
const mappingUnitKerjaPegawai = @json(auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]);
const authPegawai = @json(auth()->user()->objectpegawaifk);
const formCreate = $("#formFile")
@ -472,6 +473,22 @@
>
<i class="fa-solid fa-download"></i>
</a>
${authUnitKerja.id === 22 ? `
<button
type="button"
class="btn btn-warning btn-sm"
onclick="rekomendasiDelete(this)"
title="Rekomendasi Hapus"
data-filename="${item.nama_dokumen || '-'}"
data-id="${item.file_directory_id}"
data-no_dokumen="${item.no_dokumen || '-'}"
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
data-permission_file="${item.permission_file || '-'}"
data-pegawai_id_entry="${item.pegawai_id_entry || '-'}"
>
<i class="fa-solid fa-trash-can"></i>
</button>
` : ''}
</div>
</td>
@ -1176,5 +1193,67 @@
}
$("#previewModal").modal('show')
}
function rekomendasiDelete(button){
const id = $(button).data('id');
const fileName = $(button).data('filename') || 'dokumen';
const noDokumen = $(button).data('no_dokumen') || '-';
Swal.fire({
title: 'Rekomendasi hapus dokumen?',
text: `${fileName} (${noDokumen})`,
icon: 'warning',
input: 'textarea',
inputLabel: 'Catatan rekomendasi',
inputPlaceholder: 'Tulis alasan kenapa dokumen ini direkomendasikan untuk dihapus...',
inputAttributes: {
'aria-label': 'Catatan rekomendasi'
},
showCancelButton: true,
confirmButtonText: 'Kirim rekomendasi',
cancelButtonText: 'Batal',
preConfirm: (value) => {
const note = (value || '').trim();
if (!note) {
Swal.showValidationMessage('Catatan rekomendasi wajib diisi.');
}
return note;
}
}).then((result) => {
if (!result.isConfirmed) return;
fetch(`/recommend-delete-file/${id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({
note: result.value
})
})
.then(res => res.json())
.then(data => {
if (data.status) {
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || 'Rekomendasi hapus berhasil dikirim.',
timer: 1800,
showConfirmButton: false
});
} else {
throw new Error(data.message || 'Gagal mengirim rekomendasi hapus.');
}
})
.catch(err => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
}
</script>
@endsection

View File

@ -607,6 +607,23 @@
>
<i class="fa-solid fa-download"></i>
</a>
${authUnitKerja.id === 22 ? `
<button
type="button"
class="btn btn-warning btn-sm"
onclick="rekomendasiDelete(this)"
title="Rekomendasi Hapus"
data-filename="${item.nama_dokumen || '-'}"
data-id="${item.file_directory_id}"
data-no_dokumen="${item.no_dokumen || '-'}"
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
data-permission_file="${item.permission_file || '-'}"
data-pegawai_id_entry="${item.pegawai_id_entry || '-'}"
>
<i class="fa-solid fa-trash-can"></i>
</button>
` : ''}
</div>
</td>
<td class="text-nowrap">${item.no_dokumen || '-'}</td>
@ -1020,6 +1037,8 @@
url: `/select-sub-unit-kerja-mapping/${unitId}`,
method: 'GET',
success: function(response) {
console.log(response);
if (response?.data) {
response.data.forEach(unit => {
let selected = (authSubUnitKerja && unit.id === authSubUnitKerja.objectsubunitkerjapegawaifk);
@ -1228,7 +1247,7 @@
processResults: function(data){
return {
results : data?.data.map(item => ({
id: item.id+'/'+item.name,
id: item.id,
text: item.name,
sub_units: item.sub_unit_kerja // kirim ke front
}))
@ -1482,5 +1501,67 @@
}
$("#previewModal").modal('show')
}
function rekomendasiDelete(button){
const id = $(button).data('id');
const fileName = $(button).data('filename') || 'dokumen';
const noDokumen = $(button).data('no_dokumen') || '-';
Swal.fire({
title: 'Rekomendasi hapus dokumen?',
text: `${fileName} (${noDokumen})`,
icon: 'warning',
input: 'textarea',
inputLabel: 'Catatan rekomendasi',
inputPlaceholder: 'Tulis alasan kenapa dokumen ini direkomendasikan untuk dihapus...',
inputAttributes: {
'aria-label': 'Catatan rekomendasi'
},
showCancelButton: true,
confirmButtonText: 'Kirim rekomendasi',
cancelButtonText: 'Batal',
preConfirm: (value) => {
const note = (value || '').trim();
if (!note) {
Swal.showValidationMessage('Catatan rekomendasi wajib diisi.');
}
return note;
}
}).then((result) => {
if (!result.isConfirmed) return;
fetch(`/recommend-delete-file/${id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({
note: result.value
})
})
.then(res => res.json())
.then(data => {
if (data.status) {
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || 'Rekomendasi hapus berhasil dikirim.',
timer: 1800,
showConfirmButton: false
});
} else {
throw new Error(data.message || 'Gagal mengirim rekomendasi hapus.');
}
})
.catch(err => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
}
</script>
@endsection

View File

@ -114,7 +114,7 @@
</a>
</li>
@if(!Auth::guard('admin')->check())
@if(auth()->user()->dataUser->mappingUnitKerjaPegawai()->where('objectunitkerjapegawaifk', 43)->exists())
@if(auth()->user()->dataUser->mappingUnitKerjaPegawai()->whereIn('objectunitkerjapegawaifk', [43, 22])->exists())
<li class="nav-small-cap"><span class="hide-menu">Master</span></li>
<li class="sidebar-item has-sub {{ $openMaster ? 'open' : '' }}">

View File

@ -13,6 +13,9 @@
<!-- Body -->
<div class="modal-body p-2" style="min-height:250px; max-height:70vh; overflow:auto;">
<div class="d-flex justify-content-end align-items-center sticky-top bg-white z-10 d-none" id="deleteData">
<button type="button" class="btn btn-sm btn-outline-danger mb-2 me-2" id="delete-file">Hapus</button>
</div>
<div id="file-preview"
class="text-center text-muted d-flex justify-content-center align-items-center"
style="height:100%;">

View File

@ -78,6 +78,14 @@
<option value="100">100</option>
</select>
</div>
<div class="d-flex align-items-center gap-2" id="pengajuanBulkActions">
<button class="btn btn-danger btn-sm" id="bulkDeleteBtn" disabled>
Hapus dipilih (<span id="selectedCount">0</span>)
</button>
<button class="btn btn-outline-secondary btn-sm" id="clearSelectionBtn" disabled>
Reset pilihan
</button>
</div>
<button class="btn btn-outline-secondary btn-sm" onclick="refreshLog()">
<i class="fa fa-rotate"></i> Refresh
</button>
@ -88,6 +96,9 @@
<table class="table table-sm table-hover align-middle mb-0" id="tablePengajuan">
<thead>
<tr>
<th class="text-center">
<input type="checkbox" class="form-check-input" id="selectAllPengajuan" title="Pilih semua di halaman">
</th>
<th>Aksi</th>
<th>No Dokumen</th>
<th>Status</th>

View File

@ -51,7 +51,9 @@ Route::middleware(['auth:admin,web'])->group(function(){
Route::get('/select-sub-unit-kerja-mapping/{id}', [DashboardController::class, 'optionSubUnitKerjaByMapping']);
Route::delete('/delete-file/bulk', [DashboardController::class, 'deleteFiles']);
Route::delete('/delete-file/{id}', [DashboardController::class, 'deleteFile']);
Route::post('/recommend-delete-file/{id}', [DashboardController::class, 'recommendDeleteFile']);
// Route::get('/getFile/{id_unit_kerja}/{id_sub_unit_kerja}/{master_kategori_directory_id}', [DashboardController::class, 'getFile']);
Route::post('/download-multiple', [DashboardController::class, 'downloadDataMultiple']);