done file directory next -> testing
1
.gitignore
vendored
@ -22,3 +22,4 @@
|
|||||||
Homestead.json
|
Homestead.json
|
||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
/public/file
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use ZipArchive;
|
||||||
|
|
||||||
use function PHPUnit\Framework\isEmpty;
|
use function PHPUnit\Framework\isEmpty;
|
||||||
|
|
||||||
@ -38,40 +39,79 @@ class DashboardController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function dataUnitKerja(){
|
public function dataUnitKerja(){
|
||||||
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
|
$user = auth()->user()?->dataUser;
|
||||||
$authUnitKerja = $authMapping->objectunitkerjapegawaifk;
|
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
|
||||||
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk;
|
|
||||||
$kategori = request('kategori');
|
$kategori = request('kategori');
|
||||||
$filterUnit = request('unitKerja');
|
$filterUnit = request('unitKerja');
|
||||||
$subUnit = request('subUnit');
|
$subUnit = request('subUnit');
|
||||||
$klasifikasi = request('klasifikasi');
|
$klasifikasi = request('klasifikasi');
|
||||||
if($kategori && $filterUnit && $subUnit && $klasifikasi){
|
$keyword = request('keyword');
|
||||||
$katArray = explode(',', $kategori);
|
$subArray = $subUnit ? explode(',', $subUnit) : [];
|
||||||
$katArray = explode(',', $kategori);
|
$katArray = $kategori ? explode(',', $kategori) : [];
|
||||||
$subArray = explode(',', $subUnit);
|
$klaArray = $klasifikasi ? explode(',', $klasifikasi) : [];
|
||||||
$klaArray = 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)
|
$unitKerja = UnitKerja::where('statusenabled', true)
|
||||||
->where('id', $filterUnit)
|
->where('id', $filterUnit)
|
||||||
->with(['subUnitKerja' => function ($query) use ($katArray, $filterUnit, $subArray, $klaArray) {
|
->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray)
|
||||||
$query->whereIn('id', $subArray)
|
->with(['fileDirectory' => fn($q) => $q
|
||||||
->with(['fileDirectory' => function ($q) use ($katArray, $filterUnit, $subArray, $klaArray) {
|
->where('id_unit_kerja', $filterUnit)
|
||||||
$q->when($filterUnit, function ($subQ) use ($filterUnit) {
|
->when($subArray, fn($q) => $q->whereIn('id_sub_unit_kerja', $subArray))
|
||||||
$subQ->where('id_unit_kerja', $filterUnit);
|
->when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))
|
||||||
})->when(!empty($subArray), function ($subQ) use ($subArray) {
|
->when($klaArray, fn($q) => $q->whereIn('master_klasifikasi_directory_id', $klaArray))
|
||||||
$subQ->whereIn('id_sub_unit_kerja', $subArray);
|
->when($keyword, fn($q) => $q->where('file', 'ilike', "%{$keyword}%")->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%"))
|
||||||
})->when(!empty($katArray), function ($subQ) use ($katArray) {
|
])
|
||||||
$subQ->whereIn('master_kategori_directory_id', $katArray);
|
])
|
||||||
})->when(!empty($klaArray), function ($subQ) use ($klaArray) {
|
->select('id', 'name')
|
||||||
$subQ->whereIn('master_klasifikasi_directory_id', $klaArray);
|
->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')
|
->select('id', 'name')
|
||||||
->get();
|
->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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
@ -210,4 +250,87 @@ class DashboardController extends Controller
|
|||||||
'status' => true,
|
'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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ class SubUnitKerja extends Model
|
|||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
protected $primaryKey = 'id';
|
protected $primaryKey = 'id';
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
protected $with = ['fileDirectory'];
|
||||||
|
|
||||||
public function fileDirectory(){
|
public function fileDirectory(){
|
||||||
return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true);
|
return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true);
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 466 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 36 KiB |
@ -30,7 +30,7 @@ formCreate.on('submit', function(e){
|
|||||||
formCreate.find('input[type="text"], input[type="file"]').val('');
|
formCreate.find('input[type="text"], input[type="file"]').val('');
|
||||||
formCreate.find('select').val(null).trigger('change');
|
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()
|
index()
|
||||||
}else{
|
}else{
|
||||||
searchData()
|
searchData()
|
||||||
|
|||||||
@ -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 '<p class="text-muted">Tidak ada data</p>';
|
return `
|
||||||
return `<ul class="file-tree-ul">
|
|
||||||
${units.map(u => `
|
<ul class="file-tree-ul mt-3">
|
||||||
|
${units.map(el => `
|
||||||
<li class="file-tree-li folder">
|
<li class="file-tree-li folder">
|
||||||
<span>📂 ${u.name}</span>
|
<input class="form-check-input" type="checkbox" data-select="unit" data-unit_id="${el?.id}">
|
||||||
<ul class="file-tree-ul ms-1">
|
<span class="fw-bolder">📂 ${el.name}</span>
|
||||||
${u.sub_unit_kerja.map(s => `
|
<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>
|
||||||
|
|
||||||
|
${Array.isArray(el.sub_unit_kerja) && el.sub_unit_kerja.length > 0 ? `
|
||||||
|
<ul class="file-tree-ul mt-1 ms-2">
|
||||||
|
${el.sub_unit_kerja.map(sub => `
|
||||||
<li class="file-tree-li folder">
|
<li class="file-tree-li folder">
|
||||||
<span>📂 ${s.name}</span>
|
\
|
||||||
<ul class="file-tree-ul ms-1">
|
<input class="form-check-input" type="checkbox" data-select="sub_unit" data-unit_id="${el.id}" data-sub_unit_id="${sub?.id}" >
|
||||||
${katDok.map(k => `
|
<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>
|
||||||
|
|
||||||
|
${Array.isArray(katDok) && katDok.length > 0 ? `
|
||||||
|
<ul class="file-tree-ul ms-2">
|
||||||
|
${katDok.map(kat => {
|
||||||
|
// filter file sesuai kategori
|
||||||
|
const files = (sub.file_directory || []).filter(
|
||||||
|
file => file.master_kategori_directory_id === kat.master_kategori_directory_id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!files.length) return '';
|
||||||
|
return `
|
||||||
<li class="file-tree-li folder">
|
<li class="file-tree-li folder">
|
||||||
<span class="kat-folder" onclick="loadFiles(this)"
|
<span>📂 ${kat.nama_kategori_directory}</span>
|
||||||
data-path="${u.id}-${s.id}-${k.master_kategori_directory_id}"
|
<ul class="file-tree-ul ms-2">
|
||||||
data-unit="${u.id}"
|
${files.map(file => {
|
||||||
data-sub="${s.id}"
|
let fileName = file.file.split('/').pop();
|
||||||
data-kat="${k.master_kategori_directory_id}"
|
let uploadedBy = file.pegawai_nama_entry || "Unknown";
|
||||||
data-klas='${JSON.stringify(klasifikasi_id)}'">
|
let uploadedAt = new Date(file.entry_at).toLocaleString("id-ID", {
|
||||||
📂 ${k.nama_kategori_directory}
|
day: "2-digit",
|
||||||
</span>
|
month: "short",
|
||||||
<ul class="file-tree-ul" id="isi-${u.id}-${s.id}-${k.master_kategori_directory_id}" style="display:none"></ul>
|
year: "numeric",
|
||||||
</li>`).join('')}
|
hour: "2-digit",
|
||||||
</ul>
|
minute: "2-digit"
|
||||||
</li>`).join('')}
|
|
||||||
</ul>
|
|
||||||
</li>`).join('')}
|
|
||||||
</ul>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadFiles(e) {
|
|
||||||
|
|
||||||
const ul = e.nextElementSibling;
|
|
||||||
const unitId = $(e).data('unit')
|
|
||||||
const subId = $(e).data('sub')
|
|
||||||
const katId = $(e).data('kat')
|
|
||||||
const klas = $(e).data('klas')
|
|
||||||
|
|
||||||
const loaded = ul.getAttribute('data-loaded');
|
|
||||||
|
|
||||||
if (loaded === '1') { // toggle saja
|
|
||||||
ul.style.display = ul.style.display === 'none' ? 'block' : 'none';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.innerHTML = '<li><small class="text-muted">memuat...</small></li>';
|
|
||||||
ul.style.display = 'block';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const r = await fetch(`/getFile/${unitId}/${subId}/${katId}?klasifikasi=${klas}`);
|
|
||||||
const res = await r.json(); // array kosong / ada isi
|
|
||||||
const files = res.data || [];
|
|
||||||
if (!Array.isArray(files) || !files.length) {
|
|
||||||
ul.innerHTML = '<li><small class="text-muted">kosong</small></li>';
|
|
||||||
ul.setAttribute('data-loaded', '1');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.innerHTML = files.map(f => {
|
|
||||||
const name = f.file.split('/').pop();
|
|
||||||
const by = f.pegawai_nama_entry || 'Unknown';
|
|
||||||
const at = new Date(f.entry_at).toLocaleString('id-ID', {
|
|
||||||
day:'2-digit', month:'short', year:'numeric',
|
|
||||||
hour:'2-digit', minute:'2-digit'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<li class="file-tree-li">
|
<li class="file-tree-li">
|
||||||
<!-- baris atas : nama + klasifikasi -->
|
|
||||||
<div class="">
|
<div class="">
|
||||||
📄 <a href="#" class="file-link"
|
📄 <a href="#"
|
||||||
data-file="${f.file}"
|
class="file-link"
|
||||||
data-name_file="${name}"
|
data-file="${file?.file}"
|
||||||
data-id="${f.file_directory_id}"
|
data-name_file="${fileName}"
|
||||||
data-upload="${by}"
|
data-upload="${uploadedBy}"
|
||||||
data-time="${at}"
|
data-time="${uploadedAt}"
|
||||||
data-klasifikasi="${f.klasifikasi?.nama_klasifikasi_directory}"
|
data-klasifikasi="${file?.klasifikasi?.nama_klasifikasi_directory}"
|
||||||
title="Di-upload oleh: ${by} pada ${at}">
|
data-id="${file?.file_directory_id}"
|
||||||
${name}
|
title="Diupload oleh: ${uploadedBy} pada ${uploadedAt}">
|
||||||
|
${fileName} - <strong>(${file?.klasifikasi?.nama_klasifikasi_directory})</strong>
|
||||||
</a>
|
</a>
|
||||||
<strong>(${f.klasifikasi?.nama_klasifikasi_directory})</strong>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- baris bawah : pembuat & tanggal (kecil + italic) -->
|
|
||||||
<small class="text-muted fst-italic">
|
<small class="text-muted fst-italic">
|
||||||
Upload by ${by} · ${at}
|
Upload by ${uploadedBy} · ${uploadedAt}
|
||||||
</small>
|
</small>
|
||||||
</li>`;
|
</li>
|
||||||
}).join('');
|
|
||||||
|
|
||||||
ul.setAttribute('data-loaded', '1');
|
`;
|
||||||
} catch (e) {
|
}).join('')}
|
||||||
ul.innerHTML = '<li><small class="text-danger">gagal memuat</small></li>';
|
</ul>
|
||||||
console.error(e);
|
</li>
|
||||||
}
|
`;
|
||||||
|
}).join('')}
|
||||||
|
</ul>
|
||||||
|
` : ''}
|
||||||
|
</li>
|
||||||
|
`).join('')}
|
||||||
|
</ul>
|
||||||
|
` : ''}
|
||||||
|
</li>
|
||||||
|
`).join('')}
|
||||||
|
</ul>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], klasifikasi_id = []) {
|
|
||||||
|
|
||||||
|
function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], klasifikasi_id = [], keyword = '') {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
if (kategori_dok.length) params.append("kategori", kategori_dok);
|
if (kategori_dok.length) params.append("kategori", kategori_dok);
|
||||||
if (unitKerja) params.append("unitKerja", unitKerja);
|
if (unitKerja) params.append("unitKerja", unitKerja);
|
||||||
if (subUnitKerja.length) params.append("subUnit", subUnitKerja);
|
if (subUnitKerja.length) params.append("subUnit", subUnitKerja);
|
||||||
if (klasifikasi_id.length) params.append("klasifikasi", klasifikasi_id);
|
if (klasifikasi_id.length) params.append("klasifikasi", klasifikasi_id);
|
||||||
|
if (keyword) params.append("keyword", keyword);
|
||||||
|
|
||||||
fetch(`/data-unit-kerja?${params.toString()}`)
|
fetch(`/data-unit-kerja?${params.toString()}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
@ -111,12 +101,14 @@ function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], klasifika
|
|||||||
file_tree.innerHTML = '';
|
file_tree.innerHTML = '';
|
||||||
|
|
||||||
if (Array.isArray(data?.data?.unitKerja)) {
|
if (Array.isArray(data?.data?.unitKerja)) {
|
||||||
file_tree.innerHTML = renderTree(data.data.unitKerja, data.data.katDok, klasifikasi_id);
|
file_tree.innerHTML = renderTree(data.data.unitKerja, data.data.katDok);
|
||||||
|
|
||||||
// Toggle buka/tutup folder
|
// Toggle buka/tutup folder
|
||||||
file_tree.querySelectorAll(".folder > span").forEach(span => {
|
file_tree.querySelectorAll(".folder > span").forEach(span => {
|
||||||
span.addEventListener("click", () => {
|
span.addEventListener("click", () => {
|
||||||
let li = span.parentElement;
|
let li = span.parentElement;
|
||||||
li.classList.toggle("collapsed");
|
li.classList.toggle("collapsed");
|
||||||
|
|
||||||
// Ganti ikon 📂 <-> 📁
|
// Ganti ikon 📂 <-> 📁
|
||||||
if (li.classList.contains("collapsed")) {
|
if (li.classList.contains("collapsed")) {
|
||||||
span.textContent = span.textContent.replace("📂", "📁");
|
span.textContent = span.textContent.replace("📂", "📁");
|
||||||
@ -126,25 +118,32 @@ function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], klasifika
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
file_tree.innerHTML = '<p style="color:primary">Silakan lakukan pencarian terlebih dahulu untuk menampilkan data</p>';
|
file_tree.innerHTML = `
|
||||||
|
<p style="color: primary">
|
||||||
|
Silakan lakukan pencarian terlebih dahulu untuk menampilkan data
|
||||||
|
</p>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error : ', error));
|
.catch(error => console.error('Error : ', error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
index();
|
index();
|
||||||
|
|
||||||
function referesh(){
|
function referesh(){
|
||||||
index()
|
index()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function searchData(){
|
function searchData(){
|
||||||
let klasifikasi_id = $("#klasifikasi_dok").val()
|
let klasifikasi_id = $("#klasifikasi_dok").val()
|
||||||
let kategori_dok = $("#kategori_dok").val()
|
let kategori_dok = $("#kategori_dok").val()
|
||||||
let unitKerja = $("#unit_kerja").val()
|
let unitKerja = $("#unit_kerja").val()
|
||||||
let subUnitKerja = $("#sub_unit_kerja").val()
|
let subUnitKerja = $("#sub_unit_kerja").val()
|
||||||
if( klasifikasi_id.length === 0 ||
|
|
||||||
|
if(klasifikasi_id.length === 0 ||
|
||||||
kategori_dok.length === 0 ||
|
kategori_dok.length === 0 ||
|
||||||
!unitKerja.length ||
|
|
||||||
subUnitKerja.length === 0){
|
subUnitKerja.length === 0){
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
text: 'Lengkapi Isi form pencarian',
|
text: 'Lengkapi Isi form pencarian',
|
||||||
@ -155,3 +154,128 @@ function searchData(){
|
|||||||
|
|
||||||
index(kategori_dok, unitKerja, subUnitKerja, klasifikasi_id);
|
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' })
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -112,7 +112,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div id="tree-wrapper" class="col-md-6 mb-3">
|
<div id="tree-wrapper" class="col-md-12 mb-3">
|
||||||
|
<div class="d-flex gap-2 mb-3 flex-wrap">
|
||||||
|
<button class="btn btn-sm btn-primary" onclick="referesh()">
|
||||||
|
<i class="fas fa-sync-alt"></i> Refresh
|
||||||
|
</button>
|
||||||
|
<button type="button" id="btn-download-multi" class="btn btn-sm btn-primary" onclick="downloadMultiple()" disabled>
|
||||||
|
<i class="fas fa-download"></i> Download Multiple (<span id="multi-count">0</span>)
|
||||||
|
</button>
|
||||||
|
<input type="text" id="search_file" oninput="searchFile(this)" class="form-control form-control-sm" placeholder="Search" style="max-width:220px;">
|
||||||
|
</div>
|
||||||
<div id="file_tree"></div>
|
<div id="file_tree"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="preview-wrapper" class="col-md-6 d-none">
|
<div id="preview-wrapper" class="col-md-6 d-none">
|
||||||
|
|||||||
@ -26,6 +26,9 @@ Route::middleware(['auth'])->group(function(){
|
|||||||
Route::get('/select-sub-unit-kerja/{id}', [DashboardController::class, 'optionSubUnitKerja']);
|
Route::get('/select-sub-unit-kerja/{id}', [DashboardController::class, 'optionSubUnitKerja']);
|
||||||
Route::delete('/delete-file/{id}', [DashboardController::class, 'deleteFile']);
|
Route::delete('/delete-file/{id}', [DashboardController::class, 'deleteFile']);
|
||||||
Route::get('/getFile/{id_unit_kerja}/{id_sub_unit_kerja}/{master_kategori_directory_id}', [DashboardController::class, 'getFile']);
|
Route::get('/getFile/{id_unit_kerja}/{id_sub_unit_kerja}/{master_kategori_directory_id}', [DashboardController::class, 'getFile']);
|
||||||
|
|
||||||
|
Route::post('/download-multiple', [DashboardController::class, 'downloadDataMultiple']);
|
||||||
|
Route::post('/download-byfolder', [DashboardController::class, 'downloadDataFolder']);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/login', [AuthController::class, 'index'])->name('login');
|
Route::get('/login', [AuthController::class, 'index'])->name('login');
|
||||||
|
|||||||