@morscherlab/mld-sdk 0.7.6 → 0.7.7
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.
- package/dist/components/AutoGroupModal.vue.js +2 -2
- package/dist/components/AutoGroupModal.vue.js.map +1 -1
- package/dist/components/NumberInput.vue.js +53 -50
- package/dist/components/NumberInput.vue.js.map +1 -1
- package/dist/composables/useAutoGroup.d.ts +1 -0
- package/dist/composables/useAutoGroup.js +24 -4
- package/dist/composables/useAutoGroup.js.map +1 -1
- package/dist/styles.css +46 -18
- package/package.json +1 -1
- package/src/__tests__/composables/useAutoGroup.test.ts +133 -0
- package/src/components/AutoGroupModal.story.vue +100 -32
- package/src/components/AutoGroupModal.vue +2 -2
- package/src/components/NumberInput.vue +33 -31
- package/src/composables/useAutoGroup.ts +34 -5
- package/src/styles/components/app-sidebar.css +1 -1
- package/src/styles/components/auto-group-modal.css +5 -4
- package/src/styles/components/modal.css +6 -0
- package/src/styles/components/number-input.css +7 -5
- package/src/styles/components/step-wizard.css +5 -0
|
@@ -100,6 +100,20 @@ export function detectOutliers(
|
|
|
100
100
|
return outliers
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
const QC_KEYWORDS = new Set([
|
|
104
|
+
'eqc', 'iqc', 'qc', 'blank', 'std', 'standard', 'test',
|
|
105
|
+
])
|
|
106
|
+
|
|
107
|
+
export function classifyOutlierAction(
|
|
108
|
+
sample: string,
|
|
109
|
+
delimiter: string,
|
|
110
|
+
): OutlierAction {
|
|
111
|
+
const segments = sample.split(delimiter)
|
|
112
|
+
return segments.some(seg => QC_KEYWORDS.has(seg.toLowerCase()))
|
|
113
|
+
? 'qc'
|
|
114
|
+
: 'include'
|
|
115
|
+
}
|
|
116
|
+
|
|
103
117
|
export function extractColumns(
|
|
104
118
|
samples: string[],
|
|
105
119
|
delimiter: string,
|
|
@@ -378,18 +392,33 @@ export function useAutoGroup() {
|
|
|
378
392
|
const analysis = analyzeDelimiter(lines)
|
|
379
393
|
delimiter.value = analysis.delimiter
|
|
380
394
|
dominantFieldCount.value = analysis.dominantFieldCount
|
|
381
|
-
minFieldCount.value = analysis.minFieldCount
|
|
382
395
|
|
|
383
|
-
|
|
396
|
+
// Use dominantFieldCount as outlier threshold so QC/test samples with
|
|
397
|
+
// fewer fields than the majority are correctly flagged
|
|
398
|
+
outliers.value = detectOutliers(lines, analysis.delimiter, analysis.dominantFieldCount)
|
|
399
|
+
|
|
400
|
+
// Apply smart default actions: auto-classify QC/test samples
|
|
401
|
+
for (const outlier of outliers.value) {
|
|
402
|
+
outlier.action = classifyOutlierAction(outlier.sample, analysis.delimiter)
|
|
403
|
+
}
|
|
384
404
|
|
|
385
405
|
const conforming = lines.filter(
|
|
386
406
|
(_, i) => !outliers.value.some(o => o.index === i)
|
|
387
407
|
)
|
|
388
|
-
fields.value = extractColumns(conforming, analysis.delimiter, analysis.minFieldCount)
|
|
389
408
|
|
|
390
|
-
//
|
|
409
|
+
// Recompute minFieldCount from conforming samples only
|
|
410
|
+
const conformingFieldCounts = conforming.map(s => s.split(analysis.delimiter).length)
|
|
411
|
+
minFieldCount.value = conformingFieldCounts.length > 0
|
|
412
|
+
? Math.min(...conformingFieldCounts)
|
|
413
|
+
: analysis.dominantFieldCount
|
|
414
|
+
|
|
415
|
+
fields.value = extractColumns(conforming, analysis.delimiter, minFieldCount.value)
|
|
416
|
+
|
|
417
|
+
// Reset field names; auto-disable constant columns (cardinality 1)
|
|
391
418
|
fieldNames.value = {}
|
|
392
|
-
enabledFields.value = new Set(
|
|
419
|
+
enabledFields.value = new Set(
|
|
420
|
+
fields.value.filter(f => f.cardinality > 1).map(f => f.index)
|
|
421
|
+
)
|
|
393
422
|
}
|
|
394
423
|
|
|
395
424
|
function parseCsvInput() {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/* AutoGroupModal - Smart grouping wizard */
|
|
2
2
|
|
|
3
3
|
.mld-auto-group {
|
|
4
|
-
|
|
4
|
+
flex: 1;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
min-height: 0;
|
|
5
8
|
}
|
|
6
9
|
|
|
7
10
|
/* --- Mode toggle --- */
|
|
@@ -401,9 +404,7 @@
|
|
|
401
404
|
.mld-auto-group__preview-groups {
|
|
402
405
|
display: flex;
|
|
403
406
|
flex-direction: column;
|
|
404
|
-
gap: 0.
|
|
405
|
-
max-height: 320px;
|
|
406
|
-
overflow-y: auto;
|
|
407
|
+
gap: 0.5rem;
|
|
407
408
|
}
|
|
408
409
|
|
|
409
410
|
.mld-auto-group__preview-group {
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
.mld-modal__container {
|
|
23
23
|
position: relative;
|
|
24
24
|
width: 100%;
|
|
25
|
+
max-height: calc(100vh - 2rem);
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
25
28
|
background-color: var(--bg-card);
|
|
26
29
|
border-radius: var(--mld-radius-lg);
|
|
27
30
|
box-shadow: var(--mld-shadow-lg);
|
|
@@ -90,6 +93,9 @@
|
|
|
90
93
|
/* Modal Body */
|
|
91
94
|
.mld-modal__body {
|
|
92
95
|
padding: 1rem 1.5rem;
|
|
96
|
+
flex: 1;
|
|
97
|
+
min-height: 0;
|
|
98
|
+
overflow-y: auto;
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
/* Modal Footer */
|
|
@@ -39,6 +39,12 @@
|
|
|
39
39
|
opacity: 0.5;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
.mld-number-input__buttons {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-shrink: 0;
|
|
45
|
+
border-left: 1px solid var(--border-color);
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
.mld-number-input__button {
|
|
43
49
|
display: flex;
|
|
44
50
|
align-items: center;
|
|
@@ -65,10 +71,6 @@
|
|
|
65
71
|
border-right: 1px solid var(--border-color);
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
.mld-number-input__button--increment {
|
|
69
|
-
border-left: 1px solid var(--border-color);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
74
|
.mld-number-input__button--sm {
|
|
73
75
|
width: 1.75rem;
|
|
74
76
|
}
|
|
@@ -89,7 +91,7 @@
|
|
|
89
91
|
.mld-number-input__input {
|
|
90
92
|
flex: 1;
|
|
91
93
|
min-width: 0;
|
|
92
|
-
text-align:
|
|
94
|
+
text-align: left;
|
|
93
95
|
background-color: var(--bg-secondary);
|
|
94
96
|
color: var(--text-primary);
|
|
95
97
|
border: none;
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
gap: 1.5rem;
|
|
5
5
|
outline: none;
|
|
6
|
+
flex: 1;
|
|
7
|
+
min-height: 0;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
/* Progress indicator */
|
|
9
11
|
.mld-wizard__progress {
|
|
12
|
+
flex-shrink: 0;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
.mld-wizard__steps-indicator {
|
|
@@ -101,6 +104,7 @@
|
|
|
101
104
|
.mld-wizard__body {
|
|
102
105
|
flex: 1;
|
|
103
106
|
min-height: 0;
|
|
107
|
+
overflow-y: auto;
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
/* Navigation */
|
|
@@ -110,6 +114,7 @@
|
|
|
110
114
|
gap: 0.5rem;
|
|
111
115
|
padding-top: 1rem;
|
|
112
116
|
border-top: 1px solid var(--border-color);
|
|
117
|
+
flex-shrink: 0;
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
.mld-wizard__nav-btn {
|