diff options
| author | Bobby <[email protected]> | 2025-12-24 17:17:15 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2025-12-24 17:17:15 +0530 |
| commit | d5ea2aa824eee4b7e2d169d21da0107d057e7bc6 (patch) | |
| tree | e608fea8cf91d6915b7b6ce5eb46896dbdc2ad79 /static/js/filters.js | |
| parent | b77d75f05fb2059389c05f6c01484e0cd12e796e (diff) | |
| download | lain-d5ea2aa824eee4b7e2d169d21da0107d057e7bc6.tar.xz lain-d5ea2aa824eee4b7e2d169d21da0107d057e7bc6.zip | |
feat: Implement API endpoints for email details and actions, and refactor email preview for client-side rendering with Shadow DOM.
Diffstat (limited to 'static/js/filters.js')
| -rw-r--r-- | static/js/filters.js | 202 |
1 files changed, 90 insertions, 112 deletions
diff --git a/static/js/filters.js b/static/js/filters.js index db48a4b..2506a1b 100644 --- a/static/js/filters.js +++ b/static/js/filters.js @@ -1,8 +1,23 @@ document.addEventListener('DOMContentLoaded', function () { const tagInputs = { - 'from': { input: document.getElementById('from-input'), tags: document.getElementById('from-tags'), hidden: document.getElementById('from-hidden'), values: [] }, - 'to': { input: document.getElementById('to-input'), tags: document.getElementById('to-tags'), hidden: document.getElementById('to-hidden'), values: [] }, - 'filename': { input: document.getElementById('filename-input'), tags: document.getElementById('filename-tags'), hidden: document.getElementById('filename-hidden'), values: [] } + 'from': { + input: document.getElementById('from-input'), + tags: document.getElementById('from-tags'), + hidden: document.getElementById('from-hidden'), + values: [] + }, + 'to': { + input: document.getElementById('to-input'), + tags: document.getElementById('to-tags'), + hidden: document.getElementById('to-hidden'), + values: [] + }, + 'filename': { + input: document.getElementById('filename-input'), + tags: document.getElementById('filename-tags'), + hidden: document.getElementById('filename-hidden'), + values: [] + } }; const autocompleteDropdown = document.getElementById('autocomplete-dropdown'); @@ -10,43 +25,45 @@ document.addEventListener('DOMContentLoaded', function () { let autocompleteResults = []; let selectedIndex = -1; + // Initialize tag inputs Object.keys(tagInputs).forEach(key => { const config = tagInputs[key]; - if (!config.input) return; - config.input.addEventListener('keydown', function (e) { - if (e.key === 'Enter' || e.key === ',') { - e.preventDefault(); - const value = this.value.trim(); - if (value && !config.values.includes(value)) { - addTag(key, value); - this.value = ''; - } - } else if (e.key === 'Backspace' && this.value === '' && config.values.length > 0) { - removeTag(key, config.values.length - 1); - } else if (e.key === 'ArrowDown') { - e.preventDefault(); - navigateAutocomplete(1); - } else if (e.key === 'ArrowUp') { - e.preventDefault(); - navigateAutocomplete(-1); - } - }); + config.input.addEventListener('keydown', handleTagInput.bind(null, key)); + config.input.addEventListener('input', handleAutocomplete.bind(null, key)); + config.input.addEventListener('blur', () => setTimeout(hideAutocomplete, 200)); + }); + + function handleTagInput(type, e) { + const config = tagInputs[type]; - config.input.addEventListener('input', function () { - if (this.value.length >= 2) { - activeTagInput = key; - showAutocomplete(this, this.value); - } else { - hideAutocomplete(); + if (e.key === 'Enter' || e.key === ',') { + e.preventDefault(); + const value = e.target.value.trim(); + if (value && !config.values.includes(value)) { + addTag(type, value); + e.target.value = ''; } - }); + } else if (e.key === 'Backspace' && e.target.value === '' && config.values.length > 0) { + removeTag(type, config.values.length - 1); + } else if (e.key === 'ArrowDown') { + e.preventDefault(); + navigateAutocomplete(1); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + navigateAutocomplete(-1); + } + } - config.input.addEventListener('blur', function () { - setTimeout(() => hideAutocomplete(), 200); - }); - }); + function handleAutocomplete(type, e) { + if (e.target.value.length >= 2) { + activeTagInput = type; + showAutocomplete(e.target, e.target.value); + } else { + hideAutocomplete(); + } + } function addTag(type, value) { const config = tagInputs[type]; @@ -54,15 +71,21 @@ document.addEventListener('DOMContentLoaded', function () { const tag = document.createElement('div'); tag.className = 'tag'; - tag.innerHTML = ` - <span>${value}</span> - <button type="button" class="tag-remove" data-index="${config.values.length - 1}">×</button> - `; - tag.querySelector('.tag-remove').addEventListener('click', function () { + const span = document.createElement('span'); + span.textContent = value; + + const button = document.createElement('button'); + button.type = 'button'; + button.className = 'tag-remove'; + button.dataset.index = config.values.length - 1; + button.textContent = '×'; + button.addEventListener('click', function () { removeTag(type, parseInt(this.dataset.index)); }); + tag.appendChild(span); + tag.appendChild(button); config.tags.appendChild(tag); config.hidden.value = config.values.join(','); } @@ -78,21 +101,14 @@ document.addEventListener('DOMContentLoaded', function () { const config = tagInputs[type]; config.tags.innerHTML = ''; config.values.forEach((value, index) => { - const tag = document.createElement('div'); - tag.className = 'tag'; - tag.innerHTML = ` - <span>${value}</span> - <button type="button" class="tag-remove" data-index="${index}">×</button> - `; - tag.querySelector('.tag-remove').addEventListener('click', function () { - removeTag(type, index); - }); - config.tags.appendChild(tag); + addTag(type, value); }); } function showAutocomplete(input, query) { - const suggestions = getSuggestions(query); + // TODO: Replace with actual API call to fetch contacts + const suggestions = []; + if (suggestions.length === 0) { hideAutocomplete(); return; @@ -105,15 +121,15 @@ document.addEventListener('DOMContentLoaded', function () { autocompleteDropdown.style.top = (rect.bottom + window.scrollY) + 'px'; autocompleteDropdown.style.left = rect.left + 'px'; autocompleteDropdown.style.width = rect.width + 'px'; - - autocompleteDropdown.innerHTML = suggestions.map((item, index) => - `<div class="autocomplete-item" data-index="${index}">${item}</div>` - ).join(''); - - autocompleteDropdown.querySelectorAll('.autocomplete-item').forEach(item => { - item.addEventListener('click', function () { - selectAutocomplete(parseInt(this.dataset.index)); - }); + autocompleteDropdown.innerHTML = ''; + + suggestions.forEach((item, index) => { + const div = document.createElement('div'); + div.className = 'autocomplete-item'; + div.dataset.index = index; + div.textContent = item; + div.addEventListener('click', () => selectAutocomplete(index)); + autocompleteDropdown.appendChild(div); }); autocompleteDropdown.style.display = 'block'; @@ -152,47 +168,11 @@ document.addEventListener('DOMContentLoaded', function () { } } - function getSuggestions(query) { - const mockSuggestions = [ - '[email protected]', - '[email protected]', - '[email protected]', - '[email protected]', - ]; - return mockSuggestions.filter(s => s.toLowerCase().includes(query.toLowerCase())); - } - - document.querySelectorAll('.options-subitem > a').forEach(function (item) { - item.addEventListener('click', function (e) { - e.preventDefault(); - const parent = this.parentElement; - - if (parent.classList.contains('disabled')) { - return; - } - - document.querySelectorAll('.options-subitem.open').forEach(function (other) { - if (other !== parent) { - other.classList.remove('open'); - } - }); - - parent.classList.toggle('open'); - }); - }); - - document.addEventListener('click', function (e) { - if (!e.target.closest('.options-subitem')) { - document.querySelectorAll('.options-subitem.open').forEach(function (item) { - item.classList.remove('open'); - }); - } - }); - + // Filter controls const toggleBtn = document.getElementById('toggle-filters'); const filters = document.getElementById('filters'); const closeBtn = document.getElementById('close-filters'); + const clearBtn = document.getElementById('clear-filters'); if (toggleBtn && filters) { toggleBtn.addEventListener('click', function (e) { @@ -202,12 +182,9 @@ document.addEventListener('DOMContentLoaded', function () { } if (closeBtn && filters) { - closeBtn.addEventListener('click', function () { - filters.style.display = 'none'; - }); + closeBtn.addEventListener('click', () => filters.style.display = 'none'); } - const clearBtn = document.getElementById('clear-filters'); if (clearBtn) { clearBtn.addEventListener('click', function () { Object.keys(tagInputs).forEach(key => { @@ -221,25 +198,17 @@ document.addEventListener('DOMContentLoaded', function () { }); } + // Date preset handling const datePreset = document.getElementById('date-preset'); const customDateRange = document.getElementById('custom-date-range'); + if (datePreset && customDateRange) { datePreset.addEventListener('change', function () { customDateRange.style.display = this.value === 'custom' ? 'block' : 'none'; }); } - document.addEventListener('click', function (e) { - const filters = document.getElementById('filters'); - const toggleBtn = document.getElementById('toggle-filters'); - - if (filters && toggleBtn) { - if (!filters.contains(e.target) && !toggleBtn.contains(e.target)) { - filters.style.display = 'none'; - } - } - }); - + // Scope handling const scopeSelect = document.querySelector('select[name="scope"]'); const customFoldersInput = document.getElementById('custom-folders-input'); @@ -248,4 +217,13 @@ document.addEventListener('DOMContentLoaded', function () { customFoldersInput.style.display = this.value === 'custom' ? 'block' : 'none'; }); } -}); + + // Close filters when clicking outside + document.addEventListener('click', function (e) { + if (filters && toggleBtn) { + if (!filters.contains(e.target) && !toggleBtn.contains(e.target)) { + filters.style.display = 'none'; + } + } + }); +});
\ No newline at end of file |
