diff --git a/.gitignore b/.gitignore index b71b1ea..9a2acc8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ Homestead.json Homestead.yaml Thumbs.db +/public/file diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 700b357..0e6283b 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -12,6 +12,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; +use ZipArchive; use function PHPUnit\Framework\isEmpty; @@ -38,41 +39,80 @@ class DashboardController extends Controller } public function dataUnitKerja(){ - $authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0]; - $authUnitKerja = $authMapping->objectunitkerjapegawaifk; - $authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk; + $user = auth()->user()?->dataUser; + $akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first(); + $kategori = request('kategori'); $filterUnit = request('unitKerja'); $subUnit = request('subUnit'); $klasifikasi = request('klasifikasi'); - if($kategori && $filterUnit && $subUnit && $klasifikasi){ - $katArray = explode(',', $kategori); - $katArray = explode(',', $kategori); - $subArray = explode(',', $subUnit); - $klaArray = explode(',', $klasifikasi); + $keyword = request('keyword'); + $subArray = $subUnit ? explode(',', $subUnit) : []; + $katArray = $kategori ? explode(',', $kategori) : []; + $klaArray = $klasifikasi ? explode(',', $klasifikasi) : []; + $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(); + if ($katArray && $filterUnit && $subArray && $klaArray) { + /* mode pencarian lengkap */ $unitKerja = UnitKerja::where('statusenabled', true) ->where('id', $filterUnit) - ->with(['subUnitKerja' => function ($query) use ($katArray, $filterUnit, $subArray, $klaArray) { - $query->whereIn('id', $subArray) - ->with(['fileDirectory' => function ($q) use ($katArray, $filterUnit, $subArray, $klaArray) { - $q->when($filterUnit, function ($subQ) use ($filterUnit) { - $subQ->where('id_unit_kerja', $filterUnit); - })->when(!empty($subArray), function ($subQ) use ($subArray) { - $subQ->whereIn('id_sub_unit_kerja', $subArray); - })->when(!empty($katArray), function ($subQ) use ($katArray) { - $subQ->whereIn('master_kategori_directory_id', $katArray); - })->when(!empty($klaArray), function ($subQ) use ($klaArray) { - $subQ->whereIn('master_klasifikasi_directory_id', $klaArray); - }); - }]); - }]) + ->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($klaArray, fn($q) => $q->whereIn('master_klasifikasi_directory_id', $klaArray)) + ->when($keyword, fn($q) => $q->where('file', 'ilike', "%{$keyword}%")->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%")) + ]) + ]) ->select('id', 'name') ->get(); - $katDok = MasterKategori::where('statusenabled', true)->whereIn('master_kategori_directory_id', $katArray)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); - }else{ - $katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); - } + + } elseif ($akses?->all_akses) { + /* 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) => + $q->where('file', 'ilike', "%{$keyword}%") + ->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%") + ) + ]) + ]) + ->select('id', 'name') + ->get(); + + } elseif ($akses?->unit_akses) { + /* akses per unit */ + $unitKerja = UnitKerja::where(['statusenabled' => true, 'id' => $akses->unit_akses]) + ->with([ // muat relasi + 'subUnitKerja' => fn($q) => $q->with([ // sub-unit + 'fileDirectory' => fn($f) => $f->when($keyword, fn($q) => + $q->where('file', 'ilike', "%{$keyword}%") + ->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%") + ) + ]) + ]) + ->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) + ->with([ // 1. sub-unit milik user + 'subUnitKerja' => fn($q) => $q->where('id', $authSub) + ->with([ // 2. file-directory + filter keyword + 'fileDirectory' => fn($f) => $f->when($keyword, fn($q) => + $q->where('file', 'like', "%{$keyword}%")->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%") + ) + ]) + ]) + ->select('id', 'name') + ->get(); + } $data = [ 'unitKerja' => $unitKerja ?? null, @@ -210,4 +250,87 @@ class DashboardController extends Controller 'status' => true, ]); } + + public function downloadDataMultiple(){ + try { + $rows = request('ids', []); // [[unit_id=>u, sub_unit_id=>s], ...] + if (empty($rows)) { + return response()->json(['message' => 'Tidak ada data'], 422); + } + $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'); + + $paths = array_merge($paths, $files->toArray()); + } + } + $paths = array_unique($paths); + + if (empty($paths)) { + return response()->json(['message' => 'File tidak ditemukan'], 404); + } + + $zipName = 'files_' . time() . '.zip'; + $zipPath = public_path('zip/' . $zipName); + $zip = new ZipArchive; + if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){ + foreach ($paths as $path) { + $fullPath = public_path('file/' . $path); + if(file_exists($fullPath)){ + $relativePathInZip = $path; + $zip->addFile($fullPath, $relativePathInZip); + }else{ + throw new \Exception("File tidak ditemukan: " . $path); + } + } + $zip->close(); + } + return response()->download(public_path('zip/' . $zipName))->deleteFileAfterSend(true); + //code... + } catch (\Throwable $th) { + return response()->json([ + 'message' => 'Terjadi kesalahan', + 'error' => $th->getMessage() + ], 500); + } + } + + public function downloadDataFolder(){ + try { + $id = request('id'); + $type = request('type'); + + if($type === "unit"){ + $data = FileDirectory::where('id_unit_kerja', $id)->where('statusenabled', true)->pluck('file'); + }else{ + $data = FileDirectory::where('id_sub_unit_kerja', $id)->where('statusenabled', true)->pluck('file'); + } + if (empty($data)) { + return response()->json(['message' => 'File tidak ditemukan'], 404); + } + $zipName = 'files_' . time() . '.zip'; + $zipPath = public_path('zip/' . $zipName); + $zip = new ZipArchive; + if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){ + foreach ($data as $path) { + $fullPath = public_path('file/' . $path); + if(file_exists($fullPath)){ + $relativePathInZip = $path; + $zip->addFile($fullPath, $relativePathInZip); + }else{ + throw new \Exception("File tidak ditemukan: " . $path); + } + } + $zip->close(); + } + return response()->download(public_path('zip/' . $zipName))->deleteFileAfterSend(true); + } catch (\Throwable $th) { + return response()->json([ + 'message' => 'Terjadi kesalahan', + 'error' => $th->getMessage() + ], 500); + } + + } } diff --git a/app/Models/SubUnitKerja.php b/app/Models/SubUnitKerja.php index 18e0deb..f70ddc6 100644 --- a/app/Models/SubUnitKerja.php +++ b/app/Models/SubUnitKerja.php @@ -11,6 +11,7 @@ class SubUnitKerja extends Model public $timestamps = false; protected $primaryKey = 'id'; protected $guarded = ['id']; + protected $with = ['fileDirectory']; public function fileDirectory(){ return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true); diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Medis/Invoice 1 (7).pdf b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Medis/Invoice 1 (7).pdf deleted file mode 100644 index eedcb69..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Medis/Invoice 1 (7).pdf and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Medis/default.png b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Medis/default.png deleted file mode 100644 index a4f6704..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Medis/default.png and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Non Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (9).jpg b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Non Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (9).jpg deleted file mode 100644 index 838a91d..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Juknis/Non Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (9).jpg and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Invoice 1 (5).pdf b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Invoice 1 (5).pdf deleted file mode 100644 index eedcb69..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Invoice 1 (5).pdf and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Invoice 1 (6).pdf b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Invoice 1 (6).pdf deleted file mode 100644 index eedcb69..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Invoice 1 (6).pdf and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (10).jpg b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (10).jpg deleted file mode 100644 index 03dee42..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (10).jpg and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (2).jpg b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (2).jpg deleted file mode 100644 index 03dee42..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (2).jpg and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (4).jpg b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (4).jpg deleted file mode 100644 index 03dee42..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/PAKET 1 (NASI PUTIH, AYAM TALIWANG, TUMIS KANGKUNG, SAMBAL) (4).jpg and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (10).jpg b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (10).jpg deleted file mode 100644 index 838a91d..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (10).jpg and /dev/null differ diff --git a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (8).jpg b/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (8).jpg deleted file mode 100644 index 838a91d..0000000 Binary files a/public/file/Instalasi Sistem Informasi Manajemen Rumah Sakit/Instalasi Sistem Informasi Manajemen Rumah Sakit/Nota Dinas/Medis/Главная страница в 2024 г _ Дизайн веб-сайтов, Портфолио веб-дизайн, Интерактивный дизайн (8).jpg and /dev/null differ diff --git a/public/js/dashboard/action.js b/public/js/dashboard/action.js index 307ae0a..57b80a1 100644 --- a/public/js/dashboard/action.js +++ b/public/js/dashboard/action.js @@ -30,7 +30,7 @@ formCreate.on('submit', function(e){ formCreate.find('input[type="text"], input[type="file"]').val(''); formCreate.find('select').val(null).trigger('change'); - if(!$("#klasifikasi_dok").val() || !$("#kategori_dok").val() || !$("#unit_kerja").val() || !$("#sub_unit_kerja").val()){ + if($("#klasifikasi_dok").val().length === 0 || $("#kategori_dok").val().length === 0 ){ index() }else{ searchData() diff --git a/public/js/dashboard/index.js b/public/js/dashboard/index.js index a049109..7228010 100644 --- a/public/js/dashboard/index.js +++ b/public/js/dashboard/index.js @@ -1,108 +1,98 @@ -function renderTree(units, katDok, klasifikasi_id) { +function renderTree(units, katDok) { + if (!Array.isArray(units)) return ''; - if (!Array.isArray(units) || !units.length) return '
Tidak ada data
'; - return `Silakan lakukan pencarian terlebih dahulu untuk menampilkan data
'; + file_tree.innerHTML = ` ++ Silakan lakukan pencarian terlebih dahulu untuk menampilkan data +
+ `; } }) .catch(error => console.error('Error : ', error)); } + index(); function referesh(){ index() } + + function searchData(){ let klasifikasi_id = $("#klasifikasi_dok").val() let kategori_dok = $("#kategori_dok").val() let unitKerja = $("#unit_kerja").val() let subUnitKerja = $("#sub_unit_kerja").val() - if( klasifikasi_id.length === 0 || + + if(klasifikasi_id.length === 0 || kategori_dok.length === 0 || - !unitKerja.length || subUnitKerja.length === 0){ Swal.fire({ text: 'Lengkapi Isi form pencarian', @@ -155,3 +154,128 @@ function searchData(){ index(kategori_dok, unitKerja, subUnitKerja, klasifikasi_id); } + +function searchFile(keyword){ + + let klasifikasi_id = $("#klasifikasi_dok").val() + let kategori_dok = $("#kategori_dok").val() + let unitKerja = $("#unit_kerja").val() + let subUnitKerja = $("#sub_unit_kerja").val() + index(kategori_dok, unitKerja, subUnitKerja, klasifikasi_id, keyword.value); +} + + +function download(e){ + let data = $(e).data(); + let id = data?.id; + let type = data?.part; + + fetch('/download-byfolder', { + method:'POST', + headers: { + 'Content-Type' : 'application/json', + 'X-CSRF-TOKEN': document.querySelector('input[name="_token"]').value, + }, + body: JSON.stringify({ id : id, type: type}) + }) + .then(async res => { + if (!res.ok) { // 4xx/5xx + const msg = await res.json().catch(() => ({message:'Server error'})); + throw new Error(msg.message || 'Gagal membuat arsip'); + } + return res.blob(); + }) + .then(blob => { + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `files_${Date.now()}.zip`; + document.body.appendChild(a).click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }) + .catch(err => { + Swal.fire({ icon: 'error', title : 'Gagal mengunduh' }) + }) +} + +let multiIds = []; + +$(document).on('change', 'input[data-select]', function () { + const type = $(this).data('select'); + const isChecked = this.checked; + + /* 1. Auto-check semua sub-unit bila UNIT di-check */ + if (type === 'unit') { + $(this).closest('li.file-tree-li') + .find('input[data-select="sub_unit"]') + .prop('checked', isChecked) + .each(function () { + const su_id = $(this).data('sub_unit_id'); + const key = `${$(this).data('unit_id')}-${su_id}`; + const idx = multiIds.findIndex(x => x.key === key); + if (isChecked && idx === -1) multiIds.push({ key, unit_id: $(this).data('unit_id'), sub_unit_id: su_id }); + if (!isChecked && idx !== -1) multiIds.splice(idx, 1); + }); + } + + /* 2. Auto-uncheck UNIT bila sisa satu SUB-UNIT di-uncheck */ + if (type === 'sub_unit' && !isChecked) { + const $unitLi = $(this).closest('li.file-tree-li').closest('ul').closest('li.file-tree-li'); + const $unitCheck = $unitLi.children('input[data-select="unit"]'); + const stillChecked= $unitLi.find('input[data-select="sub_unit"]:checked').length > 0; + + if (!stillChecked) $unitCheck.prop('checked', false).trigger('change'); + } + + /* ---------- sisanya tetap: push/pop multiIds ---------- */ + const unit_id = $(this).data('unit_id'); + const sub_unit_id = $(this).data('sub_unit_id'); + const key = `${unit_id}-${sub_unit_id}`; + const idx = multiIds.findIndex(x => x.key === key); + + if (isChecked && idx === -1) multiIds.push({ key, unit_id, sub_unit_id }); + if (!isChecked && idx !== -1) multiIds.splice(idx, 1); + + $('#multi-count').text(multiIds.length); + $('#btn-download-multi').prop('disabled', multiIds.length === 0); +}); + + +function refreshMultiButton(){ + $("#multi-count").text(multiIds.length) + $("#btn-download-multi").prop('disable', multiIds.length === 0) +} + +function downloadMultiple(){ + if(multiIds.length === 0) return; + + fetch('/download-multiple', { + method:'POST', + headers: { + 'Content-Type' : 'application/json', + 'X-CSRF-TOKEN': document.querySelector('input[name="_token"]').value, + }, + body: JSON.stringify({ ids : multiIds}) + }) + .then(async res => { + if (!res.ok) { // 4xx/5xx + const msg = await res.json().catch(() => ({message:'Server error'})); + throw new Error(msg.message || 'Gagal membuat arsip'); + } + return res.blob(); + }) + .then(blob => { + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `files_${Date.now()}.zip`; + document.body.appendChild(a).click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }) + .catch(err => { + Swal.fire({ icon: 'error', title : 'Gagal mengunduh' }) + }) + +} diff --git a/resources/views/dashboard/index.blade.php b/resources/views/dashboard/index.blade.php index 2bfc1f9..bb0dba3 100644 --- a/resources/views/dashboard/index.blade.php +++ b/resources/views/dashboard/index.blade.php @@ -112,7 +112,16 @@