@milaboratories/milaboratories.ui-examples.ui 1.6.6 → 1.7.0
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/.turbo/turbo-build.log +4 -4
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +21 -0
- package/dist/assets/{index-D3ynzqog.js → index-Dw_dnB1D.js} +111 -111
- package/dist/assets/{index-D3ynzqog.js.map → index-Dw_dnB1D.js.map} +1 -1
- package/dist/index.html +1 -1
- package/package.json +6 -6
- package/src/pages/PlAdvancedFilterPage.vue +31 -27
- package/src/pages/PlAnnotationPage.vue +66 -23
- package/src/pages/PlAutocompleteMultiPage/BasicTab.vue +17 -12
- package/src/pages/PlAutocompleteMultiPage/ComboboxTab.vue +9 -8
package/dist/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self' blob: data: 'unsafe-eval';">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-Dw_dnB1D.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="./assets/index-CrE9XJ4f.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/milaboratories.ui-examples.ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"vue": "^3.5.24",
|
|
7
|
-
"@
|
|
8
|
-
"@
|
|
7
|
+
"@platforma-sdk/model": "1.46.0",
|
|
8
|
+
"@milaboratories/milaboratories.ui-examples.model": "1.3.8"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"typescript": "~5.6.3",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"zod": "~3.23.8",
|
|
14
14
|
"ag-grid-enterprise": "~34.1.2",
|
|
15
15
|
"ag-grid-vue3": "~34.1.2",
|
|
16
|
-
"@milaboratories/ts-configs": "1.0.6",
|
|
17
16
|
"@milaboratories/build-configs": "1.0.8",
|
|
18
|
-
"@
|
|
17
|
+
"@milaboratories/ts-configs": "1.0.6",
|
|
18
|
+
"@platforma-sdk/ui-vue": "1.46.0",
|
|
19
19
|
"@milaboratories/ts-builder": "1.0.5",
|
|
20
20
|
"@milaboratories/helpers": "1.12.0",
|
|
21
|
-
"@milaboratories/uikit": "2.
|
|
21
|
+
"@milaboratories/uikit": "2.7.0"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"dev": "ts-builder serve --target browser",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { AxisId, CanonicalizedJson } from '@platforma-sdk/model';
|
|
3
|
-
import { stringifyColumnId, type
|
|
3
|
+
import { stringifyColumnId, type ListOptionBase, type SUniversalPColumnId } from '@platforma-sdk/model';
|
|
4
|
+
import type { PlAdvancedFilterFilter, PlAdvancedFilterItem } from '@platforma-sdk/ui-vue';
|
|
4
5
|
import { PlAdvancedFilter, PlBlockPage, PlCheckbox, PlDropdown } from '@platforma-sdk/ui-vue';
|
|
5
|
-
import {
|
|
6
|
+
import { ref, watch } from 'vue';
|
|
6
7
|
|
|
7
8
|
const column1Id = stringifyColumnId({ name: '1', axes: [] }) as SUniversalPColumnId;
|
|
8
9
|
const column2Id = stringifyColumnId({ name: '2', axes: [] }) as SUniversalPColumnId;
|
|
@@ -19,7 +20,7 @@ const uniqueValuesByAxisIdx: Record<string, Record<number, ListOptionBase<string
|
|
|
19
20
|
[column1Id]: { 0: [{ value: 'axisValue1', label: 'Axis Value 1' }, { value: 'axisValue2', label: 'Axis Value 2' }] },
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
const options = [
|
|
23
|
+
const options: PlAdvancedFilterItem[] = [
|
|
23
24
|
{
|
|
24
25
|
id: column1Id,
|
|
25
26
|
label: 'Column 1',
|
|
@@ -60,44 +61,48 @@ async function getSuggestModel({ columnId, searchStr, axisIdx }: { columnId: SUn
|
|
|
60
61
|
return columnValues.find((v) => v.value === searchStr) || { value: searchStr, label: `Label of ${searchStr}` };
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
const errorState = {
|
|
64
|
+
const errorState: PlAdvancedFilterFilter = {
|
|
65
|
+
id: Math.random(),
|
|
64
66
|
type: 'and' as const,
|
|
65
67
|
filters: [
|
|
66
68
|
{
|
|
69
|
+
id: Math.random(),
|
|
67
70
|
type: 'and' as const,
|
|
68
71
|
filters: [
|
|
69
72
|
{
|
|
73
|
+
id: Math.random(),
|
|
70
74
|
type: 'patternEquals' as const,
|
|
71
75
|
column: inconsistentColumnId, // error - column id is not from available columns
|
|
72
76
|
value: 'A',
|
|
73
77
|
},
|
|
74
78
|
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
column: inconsistentColumnId, // error - column id is not from available columns
|
|
80
|
-
value: 'A',
|
|
81
|
-
},
|
|
82
|
-
],
|
|
79
|
+
id: Math.random(),
|
|
80
|
+
type: 'patternEquals' as const,
|
|
81
|
+
column: inconsistentColumnId, // error - column id is not from available columns
|
|
82
|
+
value: 'A',
|
|
83
83
|
},
|
|
84
84
|
],
|
|
85
85
|
}, {
|
|
86
|
+
id: Math.random(),
|
|
86
87
|
type: 'and' as const,
|
|
87
88
|
filters: [
|
|
88
89
|
{
|
|
90
|
+
id: Math.random(),
|
|
89
91
|
type: 'isNA' as const,
|
|
90
92
|
column: inconsistentColumnId, // error - column id is not from available columns
|
|
91
93
|
},
|
|
92
94
|
{
|
|
95
|
+
id: Math.random(),
|
|
93
96
|
type: 'isNotNA' as const,
|
|
94
97
|
column: inconsistentColumnId, // error - column id is not from available columns
|
|
95
98
|
},
|
|
96
99
|
],
|
|
97
100
|
}, {
|
|
101
|
+
id: Math.random(),
|
|
98
102
|
type: 'and' as const,
|
|
99
103
|
filters: [
|
|
100
104
|
{
|
|
105
|
+
id: Math.random(),
|
|
101
106
|
type: 'patternContainSubsequence' as const,
|
|
102
107
|
column: inconsistentColumnId, // error - column id is not from available columns
|
|
103
108
|
value: 'someString',
|
|
@@ -106,15 +111,19 @@ const errorState = {
|
|
|
106
111
|
}],
|
|
107
112
|
};
|
|
108
113
|
|
|
109
|
-
const normalState:
|
|
114
|
+
const normalState: PlAdvancedFilterFilter = {
|
|
115
|
+
id: Math.random(),
|
|
110
116
|
type: 'and' as const,
|
|
111
117
|
filters: [
|
|
112
118
|
{
|
|
119
|
+
id: Math.random(),
|
|
113
120
|
type: 'or' as const,
|
|
114
121
|
filters: [{
|
|
122
|
+
id: Math.random(),
|
|
115
123
|
type: 'isNA' as const,
|
|
116
124
|
column: column1Id,
|
|
117
125
|
}, {
|
|
126
|
+
id: Math.random(),
|
|
118
127
|
type: 'equal' as const,
|
|
119
128
|
column: column2Id,
|
|
120
129
|
x: 10,
|
|
@@ -122,13 +131,16 @@ const normalState: FilterSpec = {
|
|
|
122
131
|
},
|
|
123
132
|
{
|
|
124
133
|
type: 'and' as const,
|
|
134
|
+
id: Math.random(),
|
|
125
135
|
filters: [
|
|
126
136
|
{
|
|
137
|
+
id: Math.random(),
|
|
127
138
|
type: 'isNotNA' as const,
|
|
128
139
|
column: column3Id,
|
|
129
140
|
}, {
|
|
141
|
+
id: Math.random(),
|
|
130
142
|
type: 'patternFuzzyContainSubsequence' as const,
|
|
131
|
-
column:
|
|
143
|
+
column: column2Id,
|
|
132
144
|
value: 'abc',
|
|
133
145
|
},
|
|
134
146
|
],
|
|
@@ -136,32 +148,24 @@ const normalState: FilterSpec = {
|
|
|
136
148
|
],
|
|
137
149
|
};
|
|
138
150
|
|
|
139
|
-
const filterStates
|
|
151
|
+
const filterStates = ref<Record<string, PlAdvancedFilterFilter>>({
|
|
140
152
|
normalState: normalState,
|
|
141
153
|
errorState: errorState,
|
|
142
154
|
emptyState: {
|
|
155
|
+
id: Math.random(),
|
|
143
156
|
type: 'and',
|
|
144
157
|
filters: [],
|
|
145
158
|
},
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const filtersModel = computed<FilterSpec>({
|
|
149
|
-
get: () => {
|
|
150
|
-
return filterStates[selectedSavedFilters.value];
|
|
151
|
-
},
|
|
152
|
-
set: (v) => {
|
|
153
|
-
console.log('updated filters state: ', v);
|
|
154
|
-
},
|
|
155
159
|
});
|
|
156
160
|
|
|
157
|
-
const selectedSavedFilters = ref<keyof typeof filterStates>('normalState');
|
|
161
|
+
const selectedSavedFilters = ref<keyof typeof filterStates.value>('normalState');
|
|
158
162
|
const filterStatesOptions = [
|
|
159
163
|
{ value: 'normalState', label: 'Normal state' },
|
|
160
164
|
{ value: 'errorState', label: 'State with errors' },
|
|
161
165
|
{ value: 'emptyState', label: 'Empty state' },
|
|
162
166
|
];
|
|
163
167
|
|
|
164
|
-
watch(() =>
|
|
168
|
+
watch(() => filterStates.value[selectedSavedFilters.value], (m) => {
|
|
165
169
|
console.log('Model changed: ', m);
|
|
166
170
|
});
|
|
167
171
|
</script>
|
|
@@ -186,7 +190,7 @@ watch(() => filtersModel.value, (m) => {
|
|
|
186
190
|
</div>
|
|
187
191
|
<div :key="selectedSavedFilters" :class="$style.rightColumn" >
|
|
188
192
|
<PlAdvancedFilter
|
|
189
|
-
v-model="
|
|
193
|
+
v-model:filters="filterStates[selectedSavedFilters] as PlAdvancedFilterFilter"
|
|
190
194
|
:items="options"
|
|
191
195
|
:enable-dnd="enableDnd"
|
|
192
196
|
:get-suggest-options="getSuggestOptions"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { randomInt } from '@milaboratories/helpers';
|
|
3
|
-
import type
|
|
3
|
+
import { stringifyColumnId, type ListOptionBase, type PObjectId, type SUniversalPColumnId, type CanonicalizedJson, type AxisId } from '@platforma-sdk/model';
|
|
4
|
+
import type { PlAdvancedFilterItem, Annotation } from '@platforma-sdk/ui-vue';
|
|
4
5
|
import { PlAnnotationsModal } from '@platforma-sdk/ui-vue';
|
|
5
6
|
import { ref, watch } from 'vue';
|
|
6
7
|
|
|
@@ -11,11 +12,17 @@ watch(showModal, (value) => {
|
|
|
11
12
|
}
|
|
12
13
|
});
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const sampleNameId = stringifyColumnId({ name: 'sample_name', axes: [] }) as SUniversalPColumnId;
|
|
16
|
+
const countId = stringifyColumnId({ name: 'count', axes: [] }) as SUniversalPColumnId;
|
|
17
|
+
const descriptionId = stringifyColumnId({ name: 'description', axes: [] }) as SUniversalPColumnId;
|
|
18
|
+
const scoreId = stringifyColumnId({ name: 'score', axes: [] }) as SUniversalPColumnId;
|
|
19
|
+
const frequencyId = stringifyColumnId({ name: 'frequency', axes: [] }) as SUniversalPColumnId;
|
|
20
|
+
|
|
21
|
+
const mockAnnotations = ref<Annotation>({
|
|
15
22
|
title: 'Sample Pattern Filter',
|
|
16
23
|
steps: [
|
|
17
24
|
{
|
|
18
|
-
id:
|
|
25
|
+
id: randomInt(),
|
|
19
26
|
label: 'Text Pattern Filter',
|
|
20
27
|
filter: {
|
|
21
28
|
id: randomInt(),
|
|
@@ -24,14 +31,14 @@ const mockAnnotations = ref({
|
|
|
24
31
|
{
|
|
25
32
|
id: randomInt(),
|
|
26
33
|
type: 'patternEquals' as const,
|
|
27
|
-
column:
|
|
34
|
+
column: sampleNameId,
|
|
28
35
|
value: 'Sample_001',
|
|
29
36
|
},
|
|
30
37
|
],
|
|
31
38
|
},
|
|
32
39
|
},
|
|
33
40
|
{
|
|
34
|
-
id:
|
|
41
|
+
id: randomInt(),
|
|
35
42
|
label: 'Numeric Comparison',
|
|
36
43
|
filter: {
|
|
37
44
|
id: randomInt(),
|
|
@@ -40,7 +47,7 @@ const mockAnnotations = ref({
|
|
|
40
47
|
{
|
|
41
48
|
id: randomInt(),
|
|
42
49
|
type: 'greaterThan' as const,
|
|
43
|
-
column:
|
|
50
|
+
column: countId,
|
|
44
51
|
x: 100,
|
|
45
52
|
},
|
|
46
53
|
],
|
|
@@ -49,53 +56,87 @@ const mockAnnotations = ref({
|
|
|
49
56
|
],
|
|
50
57
|
});
|
|
51
58
|
|
|
52
|
-
const mockColumns = ref<
|
|
59
|
+
const mockColumns = ref<PlAdvancedFilterItem[]>([
|
|
53
60
|
{
|
|
54
|
-
id:
|
|
61
|
+
id: sampleNameId,
|
|
55
62
|
label: 'Sample Name',
|
|
56
|
-
|
|
63
|
+
error: false,
|
|
64
|
+
spec: {
|
|
65
|
+
kind: 'PColumn',
|
|
66
|
+
name: 'sample_name',
|
|
57
67
|
valueType: 'String' as const,
|
|
58
|
-
|
|
68
|
+
axesSpec: [],
|
|
59
69
|
},
|
|
60
70
|
},
|
|
61
71
|
{
|
|
62
|
-
id:
|
|
72
|
+
id: countId,
|
|
63
73
|
label: 'Count',
|
|
64
|
-
|
|
74
|
+
error: false,
|
|
75
|
+
spec: {
|
|
76
|
+
kind: 'PColumn',
|
|
77
|
+
name: 'count',
|
|
65
78
|
valueType: 'Int' as const,
|
|
66
|
-
|
|
79
|
+
axesSpec: [],
|
|
67
80
|
},
|
|
68
81
|
},
|
|
69
82
|
{
|
|
70
|
-
id:
|
|
83
|
+
id: descriptionId,
|
|
71
84
|
label: 'Description',
|
|
72
|
-
|
|
85
|
+
error: false,
|
|
86
|
+
spec: {
|
|
87
|
+
kind: 'PColumn',
|
|
88
|
+
name: 'description',
|
|
73
89
|
valueType: 'String' as const,
|
|
74
|
-
|
|
90
|
+
axesSpec: [],
|
|
75
91
|
},
|
|
76
92
|
},
|
|
77
93
|
{
|
|
78
|
-
id:
|
|
94
|
+
id: scoreId,
|
|
79
95
|
label: 'Score',
|
|
80
|
-
|
|
96
|
+
error: false,
|
|
97
|
+
spec: {
|
|
98
|
+
kind: 'PColumn',
|
|
99
|
+
name: 'score',
|
|
81
100
|
valueType: 'Double' as const,
|
|
82
|
-
|
|
101
|
+
axesSpec: [],
|
|
83
102
|
},
|
|
84
103
|
},
|
|
85
104
|
{
|
|
86
|
-
id:
|
|
105
|
+
id: frequencyId,
|
|
87
106
|
label: 'Frequency',
|
|
88
|
-
|
|
107
|
+
error: false,
|
|
108
|
+
spec: {
|
|
109
|
+
kind: 'PColumn',
|
|
110
|
+
name: 'frequency',
|
|
89
111
|
valueType: 'Float' as const,
|
|
90
|
-
|
|
112
|
+
axesSpec: [],
|
|
91
113
|
},
|
|
92
114
|
},
|
|
93
115
|
]);
|
|
94
116
|
|
|
117
|
+
const uniqueValuesByColumnId: Record<string, ListOptionBase<string>[]> = {
|
|
118
|
+
[sampleNameId]: [
|
|
119
|
+
{ value: 'Sample_001', label: 'Sample_001' },
|
|
120
|
+
{ value: 'Sample_002', label: 'Sample_002' },
|
|
121
|
+
{ value: 'Sample_003', label: 'Sample_003' },
|
|
122
|
+
{ value: 'Control_001', label: 'Control_001' },
|
|
123
|
+
{ value: 'Control_002', label: 'Control_002' },
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
async function getSuggestOptions({ columnId, searchStr }: { columnId: SUniversalPColumnId | CanonicalizedJson<AxisId>; searchStr: string; axisIdx?: number }) {
|
|
128
|
+
return (uniqueValuesByColumnId[columnId] || []).filter((v) => v.label.toLowerCase().includes(searchStr.toLowerCase()));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function getSuggestModel({ columnId, searchStr }: { columnId: SUniversalPColumnId | CanonicalizedJson<AxisId>; searchStr: string; axisIdx?: number }) {
|
|
132
|
+
const columnValues = uniqueValuesByColumnId[columnId];
|
|
133
|
+
return columnValues?.find((v) => v.value === searchStr) || { value: searchStr, label: `Label of ${searchStr}` };
|
|
134
|
+
}
|
|
135
|
+
|
|
95
136
|
const getValuesForSelectedColumns = async () => {
|
|
96
137
|
// Mock implementation - in real app this would fetch actual column values
|
|
97
138
|
return {
|
|
98
|
-
columnId:
|
|
139
|
+
columnId: sampleNameId as PObjectId,
|
|
99
140
|
values: ['Sample_001', 'Sample_002', 'Sample_003', 'Control_001', 'Control_002'],
|
|
100
141
|
};
|
|
101
142
|
};
|
|
@@ -108,6 +149,8 @@ const getValuesForSelectedColumns = async () => {
|
|
|
108
149
|
v-model:annotation="mockAnnotations"
|
|
109
150
|
:columns="mockColumns"
|
|
110
151
|
:hasSelectedColumns="true"
|
|
152
|
+
:getSuggestOptions="getSuggestOptions"
|
|
153
|
+
:getSuggestModel="getSuggestModel"
|
|
111
154
|
:getValuesForSelectedColumns="getValuesForSelectedColumns"
|
|
112
155
|
/>
|
|
113
156
|
|
|
@@ -24,19 +24,25 @@ const data = reactive({
|
|
|
24
24
|
sourceId: '1',
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
async function
|
|
28
|
-
return db.filter((el) => values.includes(el.value));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function fetchOptions(str: string): Promise<ListOptionBase<string>[]> {
|
|
32
|
-
str = str.toLowerCase();
|
|
27
|
+
async function fetchOptions(str: string | string[], type: 'value' | 'label'): Promise<ListOptionBase<string>[]> {
|
|
33
28
|
await delay(1000);
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
|
|
30
|
+
if (type === 'value' && Array.isArray(str)) {
|
|
31
|
+
const values = str;
|
|
32
|
+
return db.filter((el) => values.includes(el.value));
|
|
36
33
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
|
|
35
|
+
if (type === 'label' && typeof str === 'string') {
|
|
36
|
+
const lowerStr = str.toLowerCase();
|
|
37
|
+
if (lowerStr.includes('error')) {
|
|
38
|
+
throw new Error('test error');
|
|
39
|
+
}
|
|
40
|
+
return Promise.resolve(
|
|
41
|
+
db.filter((el) => el.value.toLowerCase().includes(lowerStr) || el.label.toLowerCase().includes(lowerStr)).slice(0, 100),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
throw new Error('Invalid arguments combination');
|
|
40
46
|
}
|
|
41
47
|
</script>
|
|
42
48
|
|
|
@@ -47,7 +53,6 @@ async function fetchOptions(str: string): Promise<ListOptionBase<string>[]> {
|
|
|
47
53
|
label="Autocomplete"
|
|
48
54
|
:required="true"
|
|
49
55
|
:optionsSearch="fetchOptions"
|
|
50
|
-
:modelSearch="fetchModelOptions"
|
|
51
56
|
:source-id="data.sourceId"
|
|
52
57
|
/>
|
|
53
58
|
<PlBtnPrimary style="width: 120px" @click="data.sourceId = String(Math.random())">Change source id</PlBtnPrimary>
|
|
@@ -7,15 +7,17 @@ const data = reactive({
|
|
|
7
7
|
selected: ['tag1', 'tag2'],
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
async function
|
|
11
|
-
|
|
12
|
-
}
|
|
10
|
+
async function fetchOptions(str: string | string[], type: 'value' | 'label'): Promise<ListOptionBase<string>[]> {
|
|
11
|
+
if (type === 'value' && Array.isArray(str)) {
|
|
12
|
+
return str.map((v) => ({ value: v, label: v }));
|
|
13
|
+
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return [];
|
|
15
|
+
if (type === 'label' && typeof str === 'string') {
|
|
16
|
+
if (str === '') return [];
|
|
17
|
+
return [{ value: str, label: str }];
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
throw new Error('Invalid arguments combination');
|
|
19
21
|
}
|
|
20
22
|
</script>
|
|
21
23
|
|
|
@@ -26,7 +28,6 @@ async function fetchOptions(str: string): Promise<ListOptionBase<string>[]> {
|
|
|
26
28
|
label="String tags (combobox)"
|
|
27
29
|
:required="true"
|
|
28
30
|
:optionsSearch="fetchOptions"
|
|
29
|
-
:modelSearch="fetchModelOptions"
|
|
30
31
|
:debounce="0"
|
|
31
32
|
:resetSearchOnSelect="true"
|
|
32
33
|
:emptyOptionsText="`Enter tag name and press Enter`"
|