335 lines
15 KiB
JavaScript

function renderTree(units, katDok, keyword) {
if (!Array.isArray(units)) return '';
return `
<ul class="file-tree-ul mt-3">
${units.map(el => {
return `
<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>
<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">
${el.sub_unit_kerja.map(sub => `
<li class="file-tree-li folder">
\
<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>
<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">
${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">
<span>📂 ${kat.nama_kategori_directory}</span>
<ul class="file-tree-ul ms-2">
${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 ${!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 ${statusClass}">
${statusLabel}
</span>
</div>
</li>
`;
}).join('')}
</ul>
</li>
`;
}).join('')}
</ul>
` : ''}
</li>
`).join('')}
</ul>
` : ''}
</li>`
}).join('')}
</ul>
`;
}
function index(kategori_dok = [], unitKerja = null, subUnitKerja = [], keyword = '') {
const params = new URLSearchParams();
if (kategori_dok.length) params.append("kategori", kategori_dok);
if (unitKerja) params.append("unitKerja", unitKerja);
if (subUnitKerja.length) params.append("subUnit", subUnitKerja);
if (keyword) params.append("keyword", keyword);
fetch(`/data-unit-kerja?${params.toString()}`)
.then(response => response.json())
.then(data => {
let file_tree = document.getElementById("file_tree");
file_tree.innerHTML = '';
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", () => {
let li = span.parentElement;
li.classList.toggle("collapsed");
// Ganti ikon 📂 <-> 📁
if (li.classList.contains("collapsed")) {
span.textContent = span.textContent.replace("📂", "📁");
} else {
span.textContent = span.textContent.replace("📁", "📂");
}
});
});
} else {
file_tree.innerHTML = `
<p style="color: primary">
Silakan lakukan pencarian terlebih dahulu untuk menampilkan data
</p>
`;
}
})
.catch(error => console.error('Error : ', error));
}
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()
}
function searchData(){
let kategori_dok = $("#kategori_dok").val()
let unitKerja = $("#unit_kerja").val()
let subUnitKerja = $("#sub_unit_kerja").val()
let keyword = ($("#search_file").val() || '').trim();
const hasFilters = kategori_dok.length && subUnitKerja.length;
if(!hasFilters && !keyword){
Swal.fire({
text: 'Isi kata kunci atau lengkapkan filter pencarian.',
icon: 'warning'
})
return
}
index(kategori_dok, unitKerja, subUnitKerja, keyword);
}
let debounceTimer;
function debounceSearch(value) {
console.log(value);
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
searchFile(value.trim());
}, 300);
}
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);
}
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 : err.message })
})
}
// Klik menu download dari ikon ⋮
document.addEventListener('click', function (e) {
const btn = e.target.closest('.folder-download');
if (!btn) return;
download(btn);
});