feat(ssa): Complete Phase V-A editable analysis plan variables
Features: - Add editable variable selection in workflow plan (SingleVarSelect + MultiVarTags) - Implement 3-layer flexible interception (warning bar + icon + blocking dialog) - Add tool_param_constraints.json for 12 statistical tools parameter validation - Add PATCH /workflow/:id/params API with Zod structural validation - Implement synchronous parameter sync before execution (Promise chaining) - Fix LLM hallucination by strict system prompt constraints - Fix DynamicReport object-based rows compatibility (R baseline_table) - Fix Word export row.map error with same normalization logic - Restore inferGroupingVar for smart default variable selection - Add ReactMarkdown rendering in SSAChatPane - Update SSA module status document to v3.5 Modified files: - backend: workflow.routes, ChatHandlerService, SystemPromptService, FlowTemplateService - frontend: WorkflowTimeline, SSAWorkspacePane, DynamicReport, SSAChatPane, ssaStore, ssa.css - config: tool_param_constraints.json (new) - docs: SSA status doc, team review reports Tested: Cohort study end-to-end execution + report export verified Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -77,8 +77,8 @@ function blockToDocxElements(block: ReportBlock, index: number): (Paragraph | Ta
|
||||
|
||||
case 'table': {
|
||||
const headers = block.headers ?? [];
|
||||
const rows = block.rows ?? [];
|
||||
if (headers.length > 0 || rows.length > 0) {
|
||||
const rawRows = block.rows ?? [];
|
||||
if (headers.length > 0 || (Array.isArray(rawRows) && rawRows.length > 0)) {
|
||||
if (block.title) {
|
||||
elements.push(
|
||||
new Paragraph({
|
||||
@@ -91,8 +91,15 @@ function blockToDocxElements(block: ReportBlock, index: number): (Paragraph | Ta
|
||||
if (headers.length > 0) {
|
||||
tableRows.push(makeRow(headers.map(String), true));
|
||||
}
|
||||
for (const row of rows) {
|
||||
tableRows.push(makeRow(row.map(c => (c === null || c === undefined ? '-' : String(c)))));
|
||||
const normalizedRows = (Array.isArray(rawRows) ? rawRows : []).map((row: any) => {
|
||||
if (Array.isArray(row)) return row;
|
||||
if (row && typeof row === 'object') {
|
||||
return headers.length > 0 ? headers.map((h: string) => row[h] ?? '') : Object.values(row);
|
||||
}
|
||||
return [String(row ?? '')];
|
||||
});
|
||||
for (const row of normalizedRows) {
|
||||
tableRows.push(makeRow(row.map((c: any) => (c === null || c === undefined ? '-' : String(c)))));
|
||||
}
|
||||
elements.push(
|
||||
new Table({
|
||||
|
||||
Reference in New Issue
Block a user