From cec6841938aa8f2697c69a6530692ec3c7b6e8a1 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 14 Mar 2026 19:51:59 -0400 Subject: [PATCH] feat: auto-summarize long requests in Summary View; smarter placeholder text --- portal/templates/app/project.html | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/portal/templates/app/project.html b/portal/templates/app/project.html index 56581fe..8a51b77 100644 --- a/portal/templates/app/project.html +++ b/portal/templates/app/project.html @@ -415,6 +415,22 @@ return false; } + // Auto-summarize long request text for Summary View. + // Short text (≤8 words or ≤60 chars) is returned as-is. + // Longer text: extract the first complete sentence; if still long, trim to ~80 chars at a word boundary. + function summarize(text) { + if (!text) return text; + const wordCount = text.trim().split(/\s+/).length; + if (wordCount <= 8 || text.length <= 60) return text; + // Try to find a sentence boundary + const m = text.match(/^(.+?[.!?])(?:\s|$)/); + if (m && m[1].length <= 120) return m[1]; + // No clean sentence — trim to ~80 chars at last word boundary + if (text.length <= 80) return text; + const cut = text.lastIndexOf(' ', 80); + return text.substring(0, cut > 20 ? cut : 80) + '…'; + } + function renderTree() { const tbody = document.getElementById('treeBody'); let html = ''; @@ -481,19 +497,7 @@ titleHtml += `
${escHtml(d.description)}
`; } } else { - // Show first complete sentence, or full title if short — no arbitrary mid-word cut-off - let displayTitle = title; - if (title.length > 120) { - const sentenceEnd = title.search(/[.!?]\s/); - if (sentenceEnd > 20 && sentenceEnd < 160) { - displayTitle = title.substring(0, sentenceEnd + 1); - } else { - // Break at last word boundary before 120 - const cut = title.lastIndexOf(' ', 120); - displayTitle = title.substring(0, cut > 40 ? cut : 120); - } - } - titleHtml = `${escHtml(displayTitle)}`; + titleHtml = `${escHtml(summarize(title))}`; } // Priority select @@ -552,7 +556,7 @@ if (existing) existing.remove(); const label = type === 'section' ? 'Section name' : 'Request text'; - const placeholder = type === 'section' ? 'e.g. Legal, Financial, Operations' : 'e.g. Provide last 3 years audited financials'; + const placeholder = type === 'section' ? 'e.g. Legal, Financial, Operations' : 'Enter the full request text — Dealspace will automatically show a concise summary in Summary View'; const tr = document.createElement('tr'); tr.id = 'inlineAddRow';