@epcare/esm-report-builder 0.1.1-pre.39 → 0.1.1-pre.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/538.js +1 -0
  2. package/dist/538.js.map +1 -0
  3. package/dist/729.js +1 -1
  4. package/dist/main.js +1 -1
  5. package/dist/openmrs-esm-report-builder.js.buildmanifest.json +26 -26
  6. package/dist/routes.json +1 -1
  7. package/package.json +1 -1
  8. package/src/components/indicators/indicator-search-select.component.tsx +0 -12
  9. package/src/components/indicators/indicators-page.component.tsx +2 -3
  10. package/src/components/linelist/builder/column-category-selector.component.tsx +162 -9
  11. package/src/components/linelist/builder/column-category-selector.scss +148 -3
  12. package/src/components/linelist/builder/column-debug-panel.component.tsx +197 -0
  13. package/src/components/linelist/builder/column-debug-panel.scss +141 -0
  14. package/src/components/linelist/builder/encounter-diagnosis-column-modal.component.tsx +43 -22
  15. package/src/components/linelist/builder/linelist-builder-workspace.component.tsx +1 -23
  16. package/src/components/linelist/builder/observation-column-modal.component.tsx +125 -40
  17. package/src/components/linelist/modals/linelist-report-builder-modal.component.tsx +78 -8
  18. package/src/components/linelist/pages/linelist-report-editor-page.component.tsx +0 -2
  19. package/src/components/linelist/shared/json-preview.component.tsx +5 -2
  20. package/src/components/report-sections/hooks/useSectionEditorState.ts +4 -7
  21. package/src/components/shared/concept-selector.component.tsx +19 -2
  22. package/src/hooks/theme/useMambaTables.ts +0 -2
  23. package/src/types/linelist-types.ts +19 -1
  24. package/src/utils/config-enhancer.ts +62 -0
  25. package/dist/378.js +0 -1
  26. package/dist/378.js.map +0 -1
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Column Debug Panel Component
3
+ *
4
+ * Displays detailed column information for debugging
5
+ * Shows ID, position, data definition config, source info, etc.
6
+ */
7
+
8
+ import React from 'react';
9
+ import { Button, Tag, CodeSnippet, Accordion, AccordionItem } from '@carbon/react';
10
+ import { Settings, Information } from '@carbon/react/icons';
11
+ import type { LinelistColumnDraft } from '../../../types/linelist-types';
12
+ import styles from './column-debug-panel.scss';
13
+
14
+ type Props = {
15
+ column: LinelistColumnDraft;
16
+ onClose: () => void;
17
+ };
18
+
19
+ export default function ColumnDebugPanel({ column, onClose }: Props) {
20
+ return (
21
+ <div className={styles.debugPanel}>
22
+ <div className={styles.header}>
23
+ <div className={styles.headerTitle}>
24
+ <Settings size={16} className={styles.icon} />
25
+ <span>Column Debug Info</span>
26
+ </div>
27
+ <Button kind="ghost" size="sm" onClick={onClose}>
28
+ Close
29
+ </Button>
30
+ </div>
31
+
32
+ <Accordion className={styles.accordion}>
33
+ {/* Basic Info */}
34
+ <AccordionItem title="Basic Information" open={true}>
35
+ <div className={styles.section}>
36
+ <DebugRow label="Column ID" value={column.id} type="uuid" />
37
+ <DebugRow label="Name" value={column.name} />
38
+ <DebugRow label="Description" value={column.description} />
39
+ <DebugRow label="Position (sortOrder)" value={column.sortOrder?.toString()} type="number" />
40
+ <DebugRow label="Data Type" value={column.dataDefinitionType} type="tag" />
41
+ </div>
42
+ </AccordionItem>
43
+
44
+ {/* Source Info */}
45
+ <AccordionItem title="Source Information" open={true}>
46
+ <div className={styles.section}>
47
+ {column.source ? (
48
+ <>
49
+ <DebugRow label="Data Source UUID" value={column.source.dataSourceUuid} type="uuid" />
50
+ <DebugRow label="Data Source Name" value={column.source.dataSourceUuid} />
51
+ <DebugRow label="Table" value={column.source.table} type="code" />
52
+ <DebugRow label="Field" value={column.source.field} type="code" />
53
+ <DebugRow label="Field Type" value={column.source.fieldType} type="tag" />
54
+ {column.source.conceptUuid && (
55
+ <DebugRow label="Concept UUID" value={column.source.conceptUuid} type="uuid" />
56
+ )}
57
+ {column.source.attributeTypeUuid && (
58
+ <DebugRow label="Attribute Type UUID" value={column.source.attributeTypeUuid} type="uuid" />
59
+ )}
60
+ {column.source.identifierTypeUuid && (
61
+ <DebugRow label="Identifier Type UUID" value={column.source.identifierTypeUuid} type="uuid" />
62
+ )}
63
+ </>
64
+ ) : (
65
+ <div className={styles.warning}>
66
+ <Information size={16} />
67
+ <span>No source information available</span>
68
+ </div>
69
+ )}
70
+ </div>
71
+ </AccordionItem>
72
+
73
+ {/* Data Definition Config */}
74
+ <AccordionItem title="Data Definition Config" open={false}>
75
+ <div className={styles.section}>
76
+ {column.dataDefinitionConfig ? (
77
+ <pre className={styles.code}>{JSON.stringify(column.dataDefinitionConfig, null, 2)}</pre>
78
+ ) : (
79
+ <div className={styles.warning}>
80
+ <Information size={16} />
81
+ <span>No data definition config available</span>
82
+ </div>
83
+ )}
84
+ </div>
85
+ </AccordionItem>
86
+
87
+ {/* Repeat Resolution */}
88
+ <AccordionItem title="Repeat Resolution" open={false}>
89
+ <div className={styles.section}>
90
+ {column.repeatResolution ? (
91
+ <>
92
+ <DebugRow label="Strategy" value={column.repeatResolution.strategy} />
93
+ <DebugRow label="Order By" value={column.repeatResolution.orderBy} />
94
+ <DebugRow label="Restrict to Period" value={column.repeatResolution.restrictToPeriod?.toString()} type="boolean" />
95
+ <DebugRow label="Ignore Voided" value={column.repeatResolution.ignoreVoided?.toString()} type="boolean" />
96
+ </>
97
+ ) : (
98
+ <div className={styles.info}>
99
+ <Information size={16} />
100
+ <span>No repeat resolution configured</span>
101
+ </div>
102
+ )}
103
+ </div>
104
+ </AccordionItem>
105
+
106
+ {/* Display Settings */}
107
+ <AccordionItem title="Display Settings" open={false}>
108
+ <div className={styles.section}>
109
+ {column.display ? (
110
+ <>
111
+ <DebugRow label="Width" value={column.display.width?.toString()} type="number" />
112
+ <DebugRow label="Align" value={column.display.align} />
113
+ <DebugRow label="Sortable" value={column.display.sortable?.toString()} type="boolean" />
114
+ <DebugRow label="Filterable" value={column.display.filterable?.toString()} type="boolean" />
115
+ <DebugRow label="Format" value={column.display.format} />
116
+ </>
117
+ ) : (
118
+ <div className={styles.info}>
119
+ <Information size={16} />
120
+ <span>No display settings configured</span>
121
+ </div>
122
+ )}
123
+ </div>
124
+ </AccordionItem>
125
+
126
+ {/* Addition Info */}
127
+ <AccordionItem title="Addition Info" open={false}>
128
+ <div className={styles.section}>
129
+ {column.additionInfo ? (
130
+ <>
131
+ <DebugRow label="Added Via" value={column.additionInfo.addedVia} />
132
+ <DebugRow label="Added At" value={column.additionInfo.addedAt} />
133
+ <DebugRow label="Order Added" value={column.additionInfo.orderAdded?.toString()} type="number" />
134
+ </>
135
+ ) : (
136
+ <div className={styles.info}>
137
+ <Information size={16} />
138
+ <span>No addition info available</span>
139
+ </div>
140
+ )}
141
+ </div>
142
+ </AccordionItem>
143
+
144
+ {/* Raw JSON */}
145
+ <AccordionItem title="Raw Column JSON" open={false}>
146
+ <div className={styles.section}>
147
+ <CodeSnippet type="multi" feedback="Copied!">
148
+ {JSON.stringify(column, null, 2)}
149
+ </CodeSnippet>
150
+ </div>
151
+ </AccordionItem>
152
+ </Accordion>
153
+ </div>
154
+ );
155
+ }
156
+
157
+ function DebugRow({ label, value, type = 'text' }: { label: string; value: any; type?: string }) {
158
+ if (value === undefined || value === null || value === '') {
159
+ return (
160
+ <div className={styles.row}>
161
+ <span className={styles.label}>{label}:</span>
162
+ <span className={styles.valueEmpty}>(not set)</span>
163
+ </div>
164
+ );
165
+ }
166
+
167
+ let displayValue = value;
168
+
169
+ switch (type) {
170
+ case 'uuid':
171
+ case 'code':
172
+ displayValue = <code className={styles.codeInline}>{value}</code>;
173
+ break;
174
+ case 'tag':
175
+ displayValue = <Tag size="sm" type="cool-gray">{value}</Tag>;
176
+ break;
177
+ case 'boolean':
178
+ displayValue = (
179
+ <Tag size="sm" type={value === 'true' ? 'green' : 'red'}>
180
+ {value === 'true' ? 'Yes' : 'No'}
181
+ </Tag>
182
+ );
183
+ break;
184
+ case 'number':
185
+ displayValue = <Tag size="sm" type="blue">{value}</Tag>;
186
+ break;
187
+ default:
188
+ displayValue = value;
189
+ }
190
+
191
+ return (
192
+ <div className={styles.row}>
193
+ <span className={styles.label}>{label}:</span>
194
+ <span className={styles.value}>{displayValue}</span>
195
+ </div>
196
+ );
197
+ }
@@ -0,0 +1,141 @@
1
+ .debugPanel {
2
+ position: fixed;
3
+ top: 50%;
4
+ left: 50%;
5
+ transform: translate(-50%, -50%);
6
+ width: 90%;
7
+ max-width: 600px;
8
+ max-height: 80vh;
9
+ background-color: #f4f4f4;
10
+ border: 2px solid #0f62fe;
11
+ border-radius: 8px;
12
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
13
+ z-index: 9999;
14
+ display: flex;
15
+ flex-direction: column;
16
+
17
+ .header {
18
+ display: flex;
19
+ justify-content: space-between;
20
+ align-items: center;
21
+ padding: 1rem;
22
+ background-color: #0f62fe;
23
+ color: white;
24
+ border-radius: 6px 6px 0 0;
25
+
26
+ .headerTitle {
27
+ display: flex;
28
+ align-items: center;
29
+ gap: 0.5rem;
30
+ font-weight: 600;
31
+ }
32
+
33
+ .icon {
34
+ // Icon styling
35
+ }
36
+ }
37
+
38
+ .accordion {
39
+ flex: 1;
40
+ overflow-y: auto;
41
+ padding: 1rem;
42
+
43
+ // Scrollbar styling
44
+ &::-webkit-scrollbar {
45
+ width: 8px;
46
+ }
47
+
48
+ &::-webkit-scrollbar-track {
49
+ background: #e0e0e0;
50
+ border-radius: 4px;
51
+ }
52
+
53
+ &::-webkit-scrollbar-thumb {
54
+ background: #8a8a8a;
55
+ border-radius: 4px;
56
+
57
+ &:hover {
58
+ background: #6f6f6f;
59
+ }
60
+ }
61
+ }
62
+
63
+ .section {
64
+ padding: 0.75rem 0;
65
+ }
66
+
67
+ .row {
68
+ display: flex;
69
+ align-items: flex-start;
70
+ gap: 0.75rem;
71
+ padding: 0.375rem 0;
72
+ border-bottom: 1px solid #e0e0e0;
73
+
74
+ &:last-child {
75
+ border-bottom: none;
76
+ }
77
+
78
+ .label {
79
+ font-weight: 500;
80
+ color: #525252;
81
+ min-width: 150px;
82
+ font-size: 0.875rem;
83
+ }
84
+
85
+ .value {
86
+ color: #161616;
87
+ font-size: 0.875rem;
88
+ word-break: break-all;
89
+ }
90
+
91
+ .valueEmpty {
92
+ color: #a8a8a8;
93
+ font-style: italic;
94
+ font-size: 0.875rem;
95
+ }
96
+ }
97
+
98
+ .codeInline {
99
+ background-color: #e0e0e0;
100
+ padding: 0.125rem 0.375rem;
101
+ border-radius: 3px;
102
+ font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
103
+ font-size: 0.8rem;
104
+ color: #0f62fe;
105
+ }
106
+
107
+ .code {
108
+ background-color: #1a1a1a;
109
+ color: #f4f4f4;
110
+ padding: 1rem;
111
+ border-radius: 4px;
112
+ overflow-x: auto;
113
+ font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
114
+ font-size: 0.8rem;
115
+ line-height: 1.5;
116
+ max-height: 300px;
117
+ overflow-y: auto;
118
+ }
119
+
120
+ .warning {
121
+ display: flex;
122
+ align-items: center;
123
+ gap: 0.5rem;
124
+ padding: 0.75rem;
125
+ background-color: #fff8e1;
126
+ border-left: 3px solid #f1c21b;
127
+ border-radius: 4px;
128
+ color: #525252;
129
+ }
130
+
131
+ .info {
132
+ display: flex;
133
+ align-items: center;
134
+ gap: 0.5rem;
135
+ padding: 0.75rem;
136
+ background-color: #e5f1ff;
137
+ border-left: 3px solid #0f62fe;
138
+ border-radius: 4px;
139
+ color: #525252;
140
+ }
141
+ }
@@ -29,6 +29,8 @@ type Props = {
29
29
  onAddColumn: (column: LinelistColumnDraft) => void;
30
30
  /** Existing columns to check for duplicates */
31
31
  existingColumns?: LinelistColumnDraft[];
32
+ /** Column to edit (if provided, modal is in edit mode) */
33
+ editingColumn?: LinelistColumnDraft | null;
32
34
  };
33
35
 
34
36
  type StrategyOption = 'ALL_VALUES' | 'LATEST' | 'FIRST_WITHIN_PERIOD' | 'LAST_WITHIN_PERIOD';
@@ -52,6 +54,7 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
52
54
  onClose,
53
55
  onAddColumn,
54
56
  existingColumns = [],
57
+ editingColumn = null,
55
58
  }) => {
56
59
  const [conceptSelectorKey, setConceptSelectorKey] = useState(0);
57
60
  const [selectedConcept, setSelectedConcept] = useState<ConceptSummary | undefined>();
@@ -61,15 +64,6 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
61
64
  const [confirmedOnly, setConfirmedOnly] = useState(true);
62
65
  const [returnDisplay, setReturnDisplay] = useState(true);
63
66
 
64
- /**
65
- * Reset form state when modal opens/closes
66
- */
67
- useEffect(() => {
68
- if (open) {
69
- setConceptSelectorKey((k) => k + 1);
70
- }
71
- }, [open]);
72
-
73
67
  /**
74
68
  * Reset form state
75
69
  */
@@ -82,6 +76,33 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
82
76
  setReturnDisplay(true);
83
77
  }, []);
84
78
 
79
+ /**
80
+ * Reset form state when modal opens/closes
81
+ * Also populate form when editing existing column
82
+ */
83
+ useEffect(() => {
84
+ if (open) {
85
+ setConceptSelectorKey((k) => k + 1);
86
+ if (editingColumn) {
87
+ // Populate form with existing column data
88
+ const config = editingColumn.dataDefinitionConfig || {};
89
+ setSelectedConcept(editingColumn.source?.conceptUuid ? {
90
+ uuid: editingColumn.source.conceptUuid,
91
+ display: config.conceptName || editingColumn.name,
92
+ datatype: { name: editingColumn.source?.fieldType || 'TEXT' },
93
+ } as ConceptSummary : undefined);
94
+ setColumnName(editingColumn.name || '');
95
+ setStrategy(config.strategy || 'LAST_WITHIN_PERIOD');
96
+ setRank(config.rank || 'ANY');
97
+ setConfirmedOnly(config.confirmedOnly !== false);
98
+ setReturnDisplay(config.returnDisplay !== false);
99
+ } else {
100
+ // Reset for new column creation
101
+ resetForm();
102
+ }
103
+ }
104
+ }, [open, editingColumn, resetForm]);
105
+
85
106
  /**
86
107
  * Handle modal close
87
108
  */
@@ -108,9 +129,9 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
108
129
  // Allow empty concept selection to capture ALL diagnoses
109
130
  const finalColumnName = columnName?.trim() || (selectedConcept?.display || 'Diagnoses');
110
131
 
111
- // Check for duplicate column names
132
+ // Check for duplicate column names (exclude current column when editing)
112
133
  const duplicateName = existingColumns.some(col =>
113
- col.name.toLowerCase() === finalColumnName.toLowerCase()
134
+ col.id !== editingColumn?.id && col.name.toLowerCase() === finalColumnName.toLowerCase()
114
135
  );
115
136
  if (duplicateName) {
116
137
  // TODO: Show error notification
@@ -120,13 +141,13 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
120
141
  const now = new Date().toISOString();
121
142
 
122
143
  const newColumn: LinelistColumnDraft = {
123
- id: `col-${now}-${selectedConcept?.uuid || 'all-diagnoses'}`,
144
+ id: editingColumn?.id || `col-${now}-${selectedConcept?.uuid || 'all-diagnoses'}`,
124
145
  name: finalColumnName,
125
- description: selectedConcept ? `Diagnosis: ${selectedConcept.display}` : 'All encounter diagnoses',
146
+ description: editingColumn?.description || (selectedConcept ? `Diagnosis: ${selectedConcept.display}` : 'All encounter diagnoses'),
126
147
  source: {
127
148
  dataSourceUuid: 'encounter_diagnoses',
128
149
  dataSourceName: 'Encounter Diagnoses',
129
- table: 'encounter_diagnosis',
150
+ table: 'encounter_diagnoses',
130
151
  field: selectedConcept?.uuid || '*',
131
152
  fieldType: 'TEXT',
132
153
  conceptUuid: selectedConcept?.uuid,
@@ -141,18 +162,18 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
141
162
  returnDisplay,
142
163
  },
143
164
  additionInfo: {
144
- addedVia: 'VISUAL_SELECTOR',
145
- addedAt: now,
146
- orderAdded: existingColumns.length,
165
+ addedVia: editingColumn?.additionInfo?.addedVia || 'VISUAL_SELECTOR',
166
+ addedAt: editingColumn?.additionInfo?.addedAt || now,
167
+ orderAdded: editingColumn?.additionInfo?.orderAdded || existingColumns.length,
147
168
  },
148
- display: {
169
+ display: editingColumn?.display || {
149
170
  width: 150,
150
171
  align: 'left',
151
172
  sortable: true,
152
173
  filterable: true,
153
174
  format: 'coded',
154
175
  },
155
- sortOrder: existingColumns.length,
176
+ sortOrder: editingColumn?.sortOrder ?? existingColumns.length,
156
177
  repeatResolution: {
157
178
  strategy: strategy === 'ALL_VALUES' ? 'NONE' : 'LATEST',
158
179
  orderBy: 'encounter_date',
@@ -163,7 +184,7 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
163
184
 
164
185
  onAddColumn(newColumn);
165
186
  handleClose();
166
- }, [selectedConcept, columnName, strategy, rank, confirmedOnly, returnDisplay, existingColumns, onAddColumn, handleClose]);
187
+ }, [selectedConcept, columnName, strategy, rank, confirmedOnly, returnDisplay, existingColumns, onAddColumn, handleClose, editingColumn]);
167
188
 
168
189
  /**
169
190
  * Check if form is valid
@@ -174,11 +195,11 @@ const EncounterDiagnosisColumnModal: React.FC<Props> = ({
174
195
  <Modal
175
196
  open={open}
176
197
  onRequestClose={handleClose}
177
- modalHeading="Add Diagnosis Column"
198
+ modalHeading={editingColumn ? "Edit Diagnosis Column" : "Add Diagnosis Column"}
178
199
  modalLabel="Data Catalogue"
179
200
  size="md"
180
201
  preventCloseOnClickOutside
181
- primaryButtonText="Add Column"
202
+ primaryButtonText={editingColumn ? "Save Changes" : "Add Column"}
182
203
  primaryButtonDisabled={!isFormValid}
183
204
  onRequestSubmit={handleSubmit}
184
205
  secondaryButtonText="Cancel"
@@ -47,7 +47,7 @@ import type {
47
47
  import type { EtlStructure } from '../../../types/etl/etl-types';
48
48
  import {
49
49
  draftToConfig,
50
- isLinelistDraftReadyToCompile,
50
+ // isLinelistDraftReadyToCompile,
51
51
  // isLinelistDraftReadyToPublish,
52
52
  createEmptyDraft,
53
53
  // isLinelistDraftValid,
@@ -82,13 +82,10 @@ type Props = {};
82
82
  * This function populates the draft with all builder details from the saved report
83
83
  */
84
84
  function reportToDraft(report: LinelistReportDto): LinelistReportDraft {
85
- console.log('🔴 reportToDraft called with:', report);
86
-
87
85
  let config: LinelistReportDefinitionConfig | null = null;
88
86
 
89
87
  try {
90
88
  config = report.configJson ? JSON.parse(report.configJson) : null;
91
- console.log('Parsed config:', config);
92
89
  } catch (e) {
93
90
  console.error('Failed to parse report config:', e);
94
91
  }
@@ -357,7 +354,6 @@ function reportToDraft(report: LinelistReportDto): LinelistReportDraft {
357
354
  let indicatorRules: PopulationDefinition['indicatorRules'] = undefined;
358
355
 
359
356
  const configIndicatorRules = builderState?.indicatorRules || (config as any).indicatorRules;
360
- console.log('🔴 configIndicatorRules:', configIndicatorRules);
361
357
  if (Array.isArray(configIndicatorRules) && configIndicatorRules.length > 0) {
362
358
  indicatorRules = configIndicatorRules.map((rule: any, idx: number) => ({
363
359
  id: rule.id || `rule-${idx}`,
@@ -367,18 +363,15 @@ function reportToDraft(report: LinelistReportDto): LinelistReportDraft {
367
363
  logicalOperator: rule.logicalOperator || 'AND',
368
364
  negate: rule.negate || false,
369
365
  }));
370
- console.log('🔴 Loaded indicatorRules from config:', indicatorRules);
371
366
  }
372
367
 
373
368
  // Fall back to metaJson for buildMethod and indicator rules if not in config
374
369
  if (report.metaJson && (!indicatorRules || buildMethod === 'SQL_BUILDER')) {
375
370
  try {
376
371
  const meta = JSON.parse(report.metaJson);
377
- console.log('🔴 Parsed metaJson:', meta);
378
372
  // Try to get buildMethod from metaJson as fallback
379
373
  if (meta.buildMethod && (meta.buildMethod === 'INDICATOR_BASED' || meta.buildMethod === 'VISUAL_FILTER' || meta.buildMethod === 'SQL_BUILDER')) {
380
374
  buildMethod = meta.buildMethod;
381
- console.log('🔴 Using buildMethod from metaJson:', buildMethod);
382
375
  }
383
376
  // Also try to get indicator rules from metaJson as fallback
384
377
  if (!indicatorRules && Array.isArray(meta.indicatorRules) && meta.indicatorRules.length > 0) {
@@ -390,7 +383,6 @@ function reportToDraft(report: LinelistReportDto): LinelistReportDraft {
390
383
  logicalOperator: rule.logicalOperator || 'AND',
391
384
  negate: rule.negate || false,
392
385
  }));
393
- console.log('🔴 Loaded indicatorRules from metaJson:', indicatorRules);
394
386
  }
395
387
  } catch (e) {
396
388
  console.warn('Failed to parse metaJson:', e);
@@ -437,9 +429,6 @@ function reportToDraft(report: LinelistReportDto): LinelistReportDraft {
437
429
  },
438
430
  ],
439
431
  };
440
- console.log('🔴 Final population state:', population);
441
- console.log('🔴 population.indicatorRules:', population.indicatorRules);
442
- console.log('🔴 population.buildMethod:', population.buildMethod);
443
432
 
444
433
  // === CREATE THE DRAFT ===
445
434
  // Build population sources from primary datasource
@@ -503,7 +492,6 @@ function reportToDraft(report: LinelistReportDto): LinelistReportDraft {
503
492
  },
504
493
  };
505
494
 
506
- console.log('🟢 Returning draft with builder details:', draft);
507
495
  return draft;
508
496
  }
509
497
 
@@ -581,12 +569,10 @@ const LinelistBuilderWorkspace: React.FC<Props> = () => {
581
569
  import('../../../resources/linelist/linelist-reports.api')
582
570
  .then(({ getLinelistReport }) => getLinelistReport(reportId))
583
571
  .then((report: LinelistReportDto) => {
584
- console.error('🔴 LOADED REPORT:', report?.name, report);
585
572
  setInitialReport(report);
586
573
  setMode('edit');
587
574
  // Convert report to draft
588
575
  const draft = reportToDraft(report);
589
- console.error('🟢 CONVERTED TO DRAFT:', draft);
590
576
  setDraft(draft);
591
577
  })
592
578
  .catch((err) => {
@@ -1229,14 +1215,6 @@ function getDefaultOperator(fieldType: FilterFieldType): FilterOperator {
1229
1215
  }
1230
1216
  }
1231
1217
 
1232
- // Debug: Check what's preventing readiness
1233
- const validationErrors = validateLinelistDraft(draft);
1234
- if (Object.keys(validationErrors).length > 0) {
1235
- console.log('⚠️ Draft validation errors:', validationErrors);
1236
- }
1237
- const isReady = isLinelistDraftReadyToCompile(draft);
1238
- console.log('🔴 Compile button state:', { compiling, hasReportUuid: !!initialReport?.uuid, isReady });
1239
-
1240
1218
  if (loading) {
1241
1219
  return (
1242
1220
  <div className={styles.workspace}>