ZDDC — Zero Day Document Control. A file-naming convention plus five single-file HTML tools (archive, transmittal, classifier, mdedit, landing) and an optional Go HTTP server (zddc-server) with ACL and a virtual archive index. Self-contained, offline-capable, dependency-free. See README.md for an overview, AGENTS.md and ARCHITECTURE.md for the build/release/architecture detail, bootstrap/README.md for the two-level deployment install pattern, and zddc/README.md for the HTTP server.
141 lines
4.5 KiB
JavaScript
141 lines
4.5 KiB
JavaScript
// Filtering functionality
|
|
|
|
// Apply all filters
|
|
function applyFilters() {
|
|
// Start with files from selected transmittal folders AND selected grouping folders
|
|
let filtered = window.app.files.filter(file => {
|
|
// Must have at least one grouping folder selected (if grouping folders exist)
|
|
if (window.app.groupingFolders.length > 0 && window.app.selectedGroupingFolders.size === 0) {
|
|
return false;
|
|
}
|
|
|
|
// Must have at least one transmittal folder selected
|
|
if (window.app.selectedTransmittalFolders.size === 0) {
|
|
return false;
|
|
}
|
|
|
|
// File must be in a selected transmittal folder
|
|
if (!window.app.selectedTransmittalFolders.has(file.folderPath)) {
|
|
return false;
|
|
}
|
|
|
|
// Outstanding files: actualPath must be under a selected grouping folder that is
|
|
// itself visible (not hidden by folder type toggles).
|
|
if (file.folderPath === '__outstanding__') {
|
|
if (!window.app.modules.app.outstandingFileIsVisible(file)) return false;
|
|
}
|
|
|
|
// If grouping folders exist and are selected, the file's transmittal folder must be within one.
|
|
// Outstanding files are exempt — their grouping scope is enforced by the actualPath check above.
|
|
if (file.folderPath !== '__outstanding__' && window.app.groupingFolders.length > 0 && window.app.selectedGroupingFolders.size > 0) {
|
|
const inSelectedGrouping = Array.from(window.app.selectedGroupingFolders).some(groupingPath =>
|
|
file.folderPath.startsWith(groupingPath + '/')
|
|
);
|
|
if (!inSelectedGrouping) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
|
|
|
|
// Apply column filters
|
|
filtered = applyColumnFilters(filtered);
|
|
|
|
// Apply modifier filter
|
|
if (window.app.selectedModifiers.size < window.app.availableModifiers.size) {
|
|
filtered = filtered.filter(file => window.app.modules.app.filePassesModifierFilter(file));
|
|
}
|
|
|
|
updateResetFiltersBtn();
|
|
|
|
// Apply selected-only filter
|
|
if (window.app.showSelectedOnly) {
|
|
filtered = filtered.filter(file => window.app.selectedFiles.has(file.id));
|
|
}
|
|
|
|
window.app.filteredFiles = filtered;
|
|
window.app.modules.table.updateFileTable();
|
|
window.app.modules.app.updateStatusBar();
|
|
window.app.modules.table.updateSelectAllVisibleCheckbox();
|
|
}
|
|
|
|
|
|
|
|
// Apply column filters using stored ASTs
|
|
function applyColumnFilters(files) {
|
|
const asts = window.app.columnFilterASTs;
|
|
|
|
if (asts.trackingNumber && asts.trackingNumber.length > 0) {
|
|
files = files.filter(file =>
|
|
zddc.filter.matches(file.trackingNumber || '', asts.trackingNumber)
|
|
);
|
|
}
|
|
|
|
if (asts.title && asts.title.length > 0) {
|
|
files = files.filter(file =>
|
|
zddc.filter.matches(file.title || '', asts.title)
|
|
);
|
|
}
|
|
|
|
if (asts.revisions && asts.revisions.length > 0) {
|
|
files = files.filter(file => {
|
|
const revisionText = [
|
|
file.revision,
|
|
file.status,
|
|
file.extension
|
|
].join(' ');
|
|
return zddc.filter.matches(revisionText, asts.revisions);
|
|
});
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
// Clear all filters
|
|
function clearFilters() {
|
|
window.app.columnFilters = {
|
|
trackingNumber: '',
|
|
title: '',
|
|
revisions: ''
|
|
};
|
|
window.app.columnFilterASTs = {
|
|
trackingNumber: null,
|
|
title: null,
|
|
revisions: null
|
|
};
|
|
window.app.groupingFilter = '';
|
|
window.app.transmittalFilter = '';
|
|
|
|
// Clear UI inputs
|
|
const groupingFilterEl = document.getElementById('groupingFilter');
|
|
groupingFilterEl.value = '';
|
|
groupingFilterEl.classList.remove('filter-active');
|
|
const transmittalFilterEl = document.getElementById('transmittalFilter');
|
|
transmittalFilterEl.value = '';
|
|
transmittalFilterEl.classList.remove('filter-active');
|
|
document.querySelectorAll('.column-filter').forEach(input => {
|
|
input.value = '';
|
|
input.classList.remove('filter-active');
|
|
});
|
|
|
|
window.app.modules.app.toggleAllModifiers(true);
|
|
updateResetFiltersBtn();
|
|
applyFilters();
|
|
window.app.modules.urlState.push();
|
|
}
|
|
|
|
// Update reset filters button visibility
|
|
function updateResetFiltersBtn() {
|
|
// Button is always visible — no show/hide logic needed
|
|
}
|
|
|
|
// Register filtering module
|
|
window.app.modules.filtering = {
|
|
applyFilters,
|
|
applyColumnFilters,
|
|
clearFilters,
|
|
updateResetFiltersBtn
|
|
};
|