Add My Docs picker to deep-research, advocate, barnevernet, korrespond, citations
- PHP: Add docPickerSection (button + chips + hidden input) to all 5 tool pages - JS: Send doc_ids in payload for deep-research, advocate, barnevernet, korrespond - Backend: Inject selected corpus doc content into paste_text/narrative/notes via dbnToolsInjectDocContent - Citations: Add upload zone (file → api/extract.php → textarea) + paste textarea with live Norwegian legal reference extraction (regex) + ref chips → title search; doc picker populates titleInput via MutationObserver Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -115,6 +115,128 @@
|
||||
titleInput.addEventListener('blur', () => setTimeout(hideAc, 150));
|
||||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') hideAc(); });
|
||||
|
||||
// ── Legal reference extraction ─────────────────────────────────────────────
|
||||
|
||||
const REF_PATTERNS = [
|
||||
/\bLOV-\d{4}-\d{2}-\d{2}-\d+\b/g,
|
||||
/\bFOR-\d{4}-\d{2}-\d{2}-\d+\b/g,
|
||||
/\bHR-\d{4}-\d{3,5}-[AUS]\b/g,
|
||||
/\bLB-\d{4}-\d+\b/g,
|
||||
/\bLA-\d{4}-\d+\b/g,
|
||||
/\bLE-\d{4}-\d+\b/g,
|
||||
/\bLF-\d{4}-\d+\b/g,
|
||||
/\bLG-\d{4}-\d+\b/g,
|
||||
/\bRt\.\s*\d{4}\s+\d+\b/g,
|
||||
];
|
||||
|
||||
const refChipsEl = document.getElementById('citRefChips');
|
||||
|
||||
function extractRefs(text) {
|
||||
const found = new Set();
|
||||
REF_PATTERNS.forEach((rx) => {
|
||||
const matches = text.match(new RegExp(rx.source, rx.flags)) || [];
|
||||
matches.forEach((m) => found.add(m.replace(/\s+/g, ' ').trim()));
|
||||
});
|
||||
return Array.from(found).slice(0, 20);
|
||||
}
|
||||
|
||||
function renderRefChips(refs) {
|
||||
if (!refChipsEl) return;
|
||||
refChipsEl.innerHTML = refs.map((ref) => {
|
||||
const safe = ref.replace(/"/g, '"');
|
||||
return `<button type="button" class="doc-chip" style="cursor:pointer" data-ref="${safe}">`
|
||||
+ `<span class="doc-chip__label">${ref}</span>`
|
||||
+ `</button>`;
|
||||
}).join('');
|
||||
refChipsEl.querySelectorAll('.doc-chip').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
titleInput.value = btn.dataset.ref;
|
||||
docIdInput.value = '';
|
||||
fetchAc(btn.dataset.ref);
|
||||
titleInput.focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const citPasteInput = document.getElementById('citPasteInput');
|
||||
if (citPasteInput) {
|
||||
citPasteInput.addEventListener('input', debounce(() => {
|
||||
const refs = extractRefs(citPasteInput.value);
|
||||
renderRefChips(refs);
|
||||
}, 400));
|
||||
}
|
||||
|
||||
// ── File upload → extract text → populate paste area ─────────────────────
|
||||
|
||||
const citUploadZone = document.getElementById('citUploadZone');
|
||||
const citUploadInput = document.getElementById('citUploadInput');
|
||||
const citUploadPrompt = document.getElementById('citUploadPrompt');
|
||||
const citUploadFileInfo = document.getElementById('citUploadFileInfo');
|
||||
const citUploadFileList = document.getElementById('citUploadFileList');
|
||||
const citUploadClear = document.getElementById('citUploadClear');
|
||||
|
||||
function handleCitFile(file) {
|
||||
if (!file) return;
|
||||
citUploadFileList.innerHTML = `<li><span class="upload-filename">${esc(file.name)}</span> <em class="upload-chars">Extracting…</em></li>`;
|
||||
citUploadPrompt.classList.add('is-hidden');
|
||||
citUploadFileInfo.classList.remove('is-hidden');
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append('file', file);
|
||||
fetch('api/extract.php', { method: 'POST', body: fd, credentials: 'same-origin' })
|
||||
.then((r) => r.json())
|
||||
.then((data) => {
|
||||
const text = data.text || '';
|
||||
if (citPasteInput) {
|
||||
citPasteInput.value = text.slice(0, 8000);
|
||||
citPasteInput.dispatchEvent(new Event('input'));
|
||||
}
|
||||
const chars = data.chars || text.length;
|
||||
citUploadFileList.innerHTML = `<li><span class="upload-filename">${esc(file.name)}</span> <span class="upload-chars">${chars.toLocaleString()} chars extracted</span></li>`;
|
||||
})
|
||||
.catch(() => {
|
||||
citUploadFileList.innerHTML = `<li><span class="upload-filename">${esc(file.name)}</span> <em class="upload-chars" style="color:var(--coral)">Extraction failed</em></li>`;
|
||||
});
|
||||
}
|
||||
|
||||
if (citUploadInput) {
|
||||
citUploadInput.addEventListener('change', () => handleCitFile(citUploadInput.files[0]));
|
||||
}
|
||||
if (citUploadZone) {
|
||||
citUploadZone.addEventListener('dragover', (e) => { e.preventDefault(); citUploadZone.classList.add('is-dragover'); });
|
||||
citUploadZone.addEventListener('dragleave', () => citUploadZone.classList.remove('is-dragover'));
|
||||
citUploadZone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
citUploadZone.classList.remove('is-dragover');
|
||||
const file = e.dataTransfer?.files?.[0];
|
||||
if (file) handleCitFile(file);
|
||||
});
|
||||
}
|
||||
if (citUploadClear) {
|
||||
citUploadClear.addEventListener('click', () => {
|
||||
if (citUploadInput) citUploadInput.value = '';
|
||||
if (citUploadFileInfo) citUploadFileInfo.classList.add('is-hidden');
|
||||
if (citUploadPrompt) citUploadPrompt.classList.remove('is-hidden');
|
||||
if (citPasteInput) { citPasteInput.value = ''; renderRefChips([]); }
|
||||
});
|
||||
}
|
||||
|
||||
// ── Doc picker → populate title input ─────────────────────────────────────
|
||||
// doc-picker.js handles the modal; we hook the confirm callback by listening
|
||||
// for changes to the hidden docPickerIds input and reading the chip labels.
|
||||
const docPickerChipsEl = document.getElementById('docPickerChips');
|
||||
if (docPickerChipsEl) {
|
||||
const observer = new MutationObserver(() => {
|
||||
const firstChip = docPickerChipsEl.querySelector('.doc-chip__label');
|
||||
if (firstChip && firstChip.textContent.trim()) {
|
||||
titleInput.value = firstChip.textContent.trim();
|
||||
docIdInput.value = '';
|
||||
fetchAc(titleInput.value);
|
||||
}
|
||||
});
|
||||
observer.observe(docPickerChipsEl, { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
// ── Action radios + depth slider ──────────────────────────────────────────
|
||||
|
||||
document.querySelectorAll('input[name="citAction"]').forEach(r => {
|
||||
|
||||
Reference in New Issue
Block a user