@meaningfully/ui 0.0.10 → 0.0.11
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/README.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
# meaningfully-ui
|
|
2
2
|
|
|
3
|
-
This is a library of UI components for [meaningfully](https://www.github.com/jeremybmerrill/meaningfully), which is an app (or collection of apps!) for semantic search over spreadsheets. See the main repo URL for more discussion.
|
|
3
|
+
This is a library of UI components for [meaningfully](https://www.github.com/jeremybmerrill/meaningfully), which is an app (or collection of apps!) for semantic search over spreadsheets. See the main repo URL for more discussion.
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
How to run:
|
|
8
|
+
|
|
9
|
+
- `npm run build` to build
|
|
10
|
+
- `npm run watch` to build continuously, rebuilding on file modification.
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
textColumn: string;
|
|
8
8
|
metadataColumns?: string[];
|
|
9
9
|
loading?: boolean;
|
|
10
|
+
hasMore?: boolean;
|
|
11
|
+
loadingMore?: boolean;
|
|
12
|
+
showMore?: () => void;
|
|
10
13
|
originalDocumentClick?: (sourceNodeId: string) => void;
|
|
11
14
|
}
|
|
12
15
|
|
|
@@ -15,18 +18,12 @@
|
|
|
15
18
|
textColumn,
|
|
16
19
|
metadataColumns = [],
|
|
17
20
|
loading = false,
|
|
21
|
+
hasMore = false,
|
|
22
|
+
loadingMore = false,
|
|
23
|
+
showMore = () => {},
|
|
18
24
|
originalDocumentClick = () => {},
|
|
19
25
|
}: Props = $props();
|
|
20
26
|
|
|
21
|
-
// Initial number of results to display
|
|
22
|
-
const initialDisplayCount = 10;
|
|
23
|
-
let displayCount = $state(initialDisplayCount);
|
|
24
|
-
|
|
25
|
-
// Function to load more results
|
|
26
|
-
const showMore = () => {
|
|
27
|
-
displayCount += 10;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
27
|
// copied from https://github.com/run-llama/LlamaIndexTS/blob/main/packages/providers/storage/weaviate/src/sanitize.ts
|
|
31
28
|
// weaviate requires property names (i.e. metadata column names) to start with a lowercase letter or underscore,
|
|
32
29
|
// and only contain letters, numbers, and underscores.
|
|
@@ -101,8 +98,6 @@
|
|
|
101
98
|
}, 5000);
|
|
102
99
|
};
|
|
103
100
|
|
|
104
|
-
// Computed property for visible results
|
|
105
|
-
let visibleResults = $derived(results.slice(0, displayCount));
|
|
106
101
|
</script>
|
|
107
102
|
|
|
108
103
|
<div class="space-y-4">
|
|
@@ -134,7 +129,7 @@
|
|
|
134
129
|
{:else}
|
|
135
130
|
<div class="bg-white rounded-lg shadow text-black">
|
|
136
131
|
<Table
|
|
137
|
-
data={
|
|
132
|
+
data={results}
|
|
138
133
|
{textColumn}
|
|
139
134
|
{metadataColumns}
|
|
140
135
|
showSimilarity={true}
|
|
@@ -143,13 +138,14 @@
|
|
|
143
138
|
/>
|
|
144
139
|
</div>
|
|
145
140
|
|
|
146
|
-
{#if
|
|
141
|
+
{#if hasMore}
|
|
147
142
|
<div class="flex justify-center mt-4">
|
|
148
143
|
<button
|
|
149
144
|
onclick={showMore}
|
|
145
|
+
disabled={loadingMore}
|
|
150
146
|
class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
|
|
151
147
|
>
|
|
152
|
-
Show More
|
|
148
|
+
{loadingMore ? 'Loading...' : 'Show More'}
|
|
153
149
|
</button>
|
|
154
150
|
</div>
|
|
155
151
|
{/if}
|
|
@@ -3,6 +3,9 @@ interface Props {
|
|
|
3
3
|
textColumn: string;
|
|
4
4
|
metadataColumns?: string[];
|
|
5
5
|
loading?: boolean;
|
|
6
|
+
hasMore?: boolean;
|
|
7
|
+
loadingMore?: boolean;
|
|
8
|
+
showMore?: () => void;
|
|
6
9
|
originalDocumentClick?: (sourceNodeId: string) => void;
|
|
7
10
|
}
|
|
8
11
|
declare const Results: import("svelte").Component<Props, {}, "">;
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
let metadataColumns: string[] = $state([]);
|
|
18
18
|
let textColumn: string = $state('');
|
|
19
19
|
let loading = $state(false);
|
|
20
|
+
let loadingMore = $state(false);
|
|
20
21
|
let hasResults = $state(false);
|
|
22
|
+
let hasMore = $state(false);
|
|
21
23
|
let showModal = $state(false);
|
|
22
24
|
let modalContent: Record<string, any> | null = $state(null);
|
|
23
25
|
|
|
@@ -28,6 +30,8 @@
|
|
|
28
30
|
let results: Array<Record<string, any>> = $state([]);
|
|
29
31
|
let error: string | null = $state(null);
|
|
30
32
|
|
|
33
|
+
const pageSize = 10;
|
|
34
|
+
|
|
31
35
|
api.getDocumentSet(documentSetId).then((receivedDocumentSet: DocumentSet) => {
|
|
32
36
|
documentSet = receivedDocumentSet;
|
|
33
37
|
documentSet.uploadDate = new Date(documentSet.uploadDate); // convert to Date object, if necessary (SQLite returns date obj, Postgres returns string)
|
|
@@ -50,36 +54,74 @@
|
|
|
50
54
|
];
|
|
51
55
|
const placeholderQuery = placeholderQueries[Math.floor(Math.random() * placeholderQueries.length)];
|
|
52
56
|
|
|
57
|
+
const mapSearchResults = (searchResults: Array<Record<string, any>>) => {
|
|
58
|
+
return searchResults.map(result => ({ // TODO Factor this out if preview and search use the same data structure.
|
|
59
|
+
...result.metadata, // flatten the metadata so that this object is the same shape as a CSV row.
|
|
60
|
+
similarity: result.score,
|
|
61
|
+
[textColumn]: result.text,
|
|
62
|
+
sourceNodeId: result.sourceNodeId
|
|
63
|
+
}));
|
|
64
|
+
};
|
|
65
|
+
|
|
53
66
|
async function handleSearch() {
|
|
54
67
|
if (!searchQuery.trim() || !documentSet) return;
|
|
55
68
|
hasResults = true;
|
|
56
69
|
loading = true;
|
|
70
|
+
hasMore = false;
|
|
57
71
|
try {
|
|
58
|
-
const
|
|
72
|
+
const searchResponse = await api.searchDocumentSet({
|
|
59
73
|
documentSetId: documentSet.documentSetId,
|
|
60
74
|
query: searchQuery,
|
|
61
|
-
n_results:
|
|
75
|
+
n_results: pageSize,
|
|
76
|
+
offset: 0,
|
|
62
77
|
filters: metadataFilters.map(filter => ({
|
|
63
78
|
key: filter.key,
|
|
64
79
|
operator: filter.operator,
|
|
65
80
|
value: filter.value
|
|
66
81
|
}))
|
|
67
82
|
});
|
|
68
|
-
results =
|
|
69
|
-
|
|
70
|
-
similarity: result.score.toFixed(2),
|
|
71
|
-
[textColumn]: result.text,
|
|
72
|
-
sourceNodeId: result.sourceNodeId
|
|
73
|
-
}));
|
|
83
|
+
results = mapSearchResults(searchResponse.results);
|
|
84
|
+
hasMore = searchResponse.hasMore;
|
|
74
85
|
error = null;
|
|
75
86
|
} catch (error_: any) {
|
|
76
87
|
console.error('Search failed:', error_);
|
|
77
|
-
error = error_;
|
|
88
|
+
error = error_ instanceof Error ? error_.message : String(error_);
|
|
89
|
+
results = [];
|
|
90
|
+
hasMore = false;
|
|
78
91
|
} finally {
|
|
79
92
|
loading = false;
|
|
80
93
|
}
|
|
81
94
|
}
|
|
82
95
|
|
|
96
|
+
async function handleLoadMore() {
|
|
97
|
+
if (!documentSet || loadingMore || loading || !hasMore) return;
|
|
98
|
+
|
|
99
|
+
loadingMore = true;
|
|
100
|
+
try {
|
|
101
|
+
const searchResponse = await api.searchDocumentSet({
|
|
102
|
+
documentSetId: documentSet.documentSetId,
|
|
103
|
+
query: searchQuery,
|
|
104
|
+
n_results: pageSize,
|
|
105
|
+
offset: results.length,
|
|
106
|
+
filters: metadataFilters.map(filter => ({
|
|
107
|
+
key: filter.key,
|
|
108
|
+
operator: filter.operator,
|
|
109
|
+
value: filter.value
|
|
110
|
+
}))
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const nextRows = mapSearchResults(searchResponse.results);
|
|
114
|
+
results = [...results, ...nextRows];
|
|
115
|
+
hasMore = searchResponse.hasMore;
|
|
116
|
+
error = null;
|
|
117
|
+
} catch (error_: any) {
|
|
118
|
+
console.error('Loading more failed:', error_);
|
|
119
|
+
error = error_ instanceof Error ? error_.message : String(error_);
|
|
120
|
+
} finally {
|
|
121
|
+
loadingMore = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
83
125
|
function addFilter() {
|
|
84
126
|
metadataFilters = [...metadataFilters, { key: '', operator: '==', value: '' }];
|
|
85
127
|
}
|
|
@@ -220,6 +262,9 @@
|
|
|
220
262
|
<Results
|
|
221
263
|
{results}
|
|
222
264
|
{loading}
|
|
265
|
+
{loadingMore}
|
|
266
|
+
{hasMore}
|
|
267
|
+
showMore={handleLoadMore}
|
|
223
268
|
{textColumn}
|
|
224
269
|
{metadataColumns}
|
|
225
270
|
originalDocumentClick={handleOriginalDocumentClick}
|
package/dist/types.d.ts
CHANGED
|
@@ -32,12 +32,16 @@ export interface MeaningfullyAPI {
|
|
|
32
32
|
documentSetId: number;
|
|
33
33
|
query: string;
|
|
34
34
|
n_results: number;
|
|
35
|
+
offset?: number;
|
|
35
36
|
filters?: {
|
|
36
37
|
key: string;
|
|
37
38
|
operator: "==" | "in" | ">" | "<" | "!=" | ">=" | "<=" | "nin" | "any" | "all" | "text_match" | "contains" | "is_empty";
|
|
38
39
|
value: any;
|
|
39
40
|
}[];
|
|
40
|
-
}) => Promise<
|
|
41
|
+
}) => Promise<{
|
|
42
|
+
results: SearchResult[];
|
|
43
|
+
hasMore: boolean;
|
|
44
|
+
}>;
|
|
41
45
|
getDocument: (params: {
|
|
42
46
|
documentSetId: number;
|
|
43
47
|
documentId: string;
|