mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
vectorsdb collection page and empty state bugs
This commit is contained in:
+17
@@ -2,6 +2,7 @@ import { sdk } from '$lib/stores/sdk';
|
||||
import type { Page } from '@sveltejs/kit';
|
||||
import type { TerminologyResult } from './types';
|
||||
import {
|
||||
type CollectionDatabaseType,
|
||||
type DatabaseType,
|
||||
type Entity,
|
||||
type EntityList,
|
||||
@@ -111,6 +112,22 @@ export type DatabaseSdkResult = {
|
||||
}) => Promise<{}>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the raw DocumentsDB or VectorsDB SDK service for a given database type.
|
||||
* Use in load functions (.ts) where Svelte runes aren't available.
|
||||
*/
|
||||
export function getCollectionService(region: string, project: string, type: CollectionDatabaseType) {
|
||||
const projectSdk = sdk.forProject(region, project);
|
||||
switch (type) {
|
||||
case 'documentsdb':
|
||||
return projectSdk.documentsDB;
|
||||
case 'vectorsdb':
|
||||
return projectSdk.vectorsDB;
|
||||
default:
|
||||
throw new Error(`Unsupported collection database type: ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function useDatabaseSdk(
|
||||
regionOrPage: string | Page,
|
||||
projectOrTerminology: string | TerminologyResult,
|
||||
|
||||
+6
-3
@@ -10,6 +10,9 @@ type ImplementedDBTypes = Omit<BaseTerminology, 'legacy'>;
|
||||
|
||||
/* manual type for the time being because vectorsdb is pending */
|
||||
export type DatabaseType = 'legacy' | 'tablesdb' | 'documentsdb' | 'vectorsdb';
|
||||
export type CollectionDatabaseType = Extract<DatabaseType, 'documentsdb' | 'vectorsdb'>;
|
||||
|
||||
export const DEFAULT_VECTOR_DIMENSION = 768;
|
||||
|
||||
export type RecordType = ImplementedDBTypes[keyof ImplementedDBTypes]['record'];
|
||||
|
||||
@@ -63,9 +66,9 @@ export const baseTerminology = {
|
||||
record: 'document'
|
||||
},
|
||||
vectorsdb: {
|
||||
entity: 'table',
|
||||
field: 'column',
|
||||
record: 'row'
|
||||
entity: 'collection',
|
||||
field: 'attribute',
|
||||
record: 'document'
|
||||
}
|
||||
} as const;
|
||||
|
||||
|
||||
+15
-4
@@ -4,14 +4,14 @@
|
||||
import { Modal, CustomId } from '$lib/components';
|
||||
import { subNavigation } from '$lib/stores/database';
|
||||
import { ID } from '@appwrite.io/console';
|
||||
import { Button, InputText } from '$lib/elements/forms';
|
||||
import { Button, InputNumber, InputText } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import {
|
||||
Input as SuggestionsInput,
|
||||
entityColumnSuggestions
|
||||
} from '$database/(suggestions)/index';
|
||||
|
||||
import { getTerminologies } from '../helpers';
|
||||
import { getTerminologies, DEFAULT_VECTOR_DIMENSION } from '$database/(entity)';
|
||||
import { resetSampleFieldsConfig } from '$database/store';
|
||||
|
||||
let {
|
||||
@@ -21,7 +21,7 @@
|
||||
}: {
|
||||
show: boolean;
|
||||
useSuggestions?: boolean;
|
||||
onCreateEntity: (id: string, name: string) => Promise<void>;
|
||||
onCreateEntity: (id: string, name: string, dimension?: number) => Promise<void>;
|
||||
} = $props();
|
||||
|
||||
const { analytics, terminology } = getTerminologies();
|
||||
@@ -29,12 +29,14 @@
|
||||
const lower = terminology.entity.lower.singular;
|
||||
const title = terminology.entity.title.singular;
|
||||
const analyticsCreateSubmit = analytics.submit.entity('Create');
|
||||
const isVectorsDb = terminology.type === 'vectorsdb';
|
||||
|
||||
// example - `table-[table]`, `collection-[collection]`
|
||||
const isOnEntitiesPage = $derived(page.route?.id.endsWith(`${lower}-[${lower}]`));
|
||||
|
||||
let name = $state('');
|
||||
let id = $state(null);
|
||||
let dimension = $state(DEFAULT_VECTOR_DIMENSION);
|
||||
let error = $state(null);
|
||||
let creatingEntity = $state(false);
|
||||
|
||||
@@ -64,7 +66,7 @@
|
||||
enableThinkingModeForSuggestions(finalId, name);
|
||||
|
||||
// create entity.
|
||||
await onCreateEntity(finalId, name);
|
||||
await onCreateEntity(finalId, name, isVectorsDb ? dimension : undefined);
|
||||
|
||||
// cleanup
|
||||
updateAndCleanup();
|
||||
@@ -121,6 +123,15 @@
|
||||
|
||||
<CustomId show bind:id required={false} autofocus={false} name={title} syncFrom={name} />
|
||||
|
||||
{#if isVectorsDb}
|
||||
<InputNumber
|
||||
id="dimension"
|
||||
label="Vector dimension"
|
||||
bind:value={dimension}
|
||||
min={1}
|
||||
required />
|
||||
{/if}
|
||||
|
||||
{#if useSuggestions}
|
||||
<SuggestionsInput showSampleCountPicker={!terminology.schema} />
|
||||
{/if}
|
||||
|
||||
+5
-4
@@ -292,7 +292,7 @@
|
||||
|
||||
const spreadsheetColumns = $derived.by(() => {
|
||||
return isRecordMode
|
||||
? type !== 'documentsdb'
|
||||
? type === 'tablesdb' || type === 'legacy'
|
||||
? getRowColumns()
|
||||
: getDocumentsDbColumns()
|
||||
: getIndexesColumns();
|
||||
@@ -382,7 +382,7 @@
|
||||
|
||||
{#snippet noSqlEditor()}
|
||||
{#if showNoSqlEditor}
|
||||
{#if type === 'documentsdb' && mode === 'records'}
|
||||
{#if (type === 'documentsdb' || type === 'vectorsdb') && mode === 'records'}
|
||||
<NoSqlEditor loading />
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -411,7 +411,7 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if showActions && actions}
|
||||
{@const isOnlyIndexes = mode === 'indexes' && type === 'documentsdb'}
|
||||
{@const isOnlyIndexes = mode === 'indexes' && (type === 'documentsdb' || type === 'vectorsdb')}
|
||||
{@const inline = mode === 'records-filtered' || isOnlyIndexes}
|
||||
<div class="controlled-width" class:single-mode={isOnlyIndexes}>
|
||||
<Layout.Stack
|
||||
@@ -504,7 +504,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[data-mode='records'][data-type='documentsdb'] {
|
||||
&[data-mode='records'][data-type='documentsdb'],
|
||||
&[data-mode='records'][data-type='vectorsdb'] {
|
||||
position: unset;
|
||||
// disable animation when not loading!
|
||||
&[data-loading='false'] :global(.skeleton) {
|
||||
|
||||
+2
-1
@@ -49,6 +49,7 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { copy } from '$lib/helpers/copy';
|
||||
import { isSmallViewport } from '$lib/stores/viewport';
|
||||
import { isMac } from '$lib/helpers/platform';
|
||||
|
||||
import { makeErrorMessage } from './helpers/errorMessages';
|
||||
import { customTheme, customSyntaxHighlighting } from './helpers/theme';
|
||||
@@ -1512,7 +1513,7 @@
|
||||
gap="xxxs"
|
||||
alignItems="center"
|
||||
style="height: fit-content">
|
||||
<Badge content="⌘" variant="secondary" size="xs" />
|
||||
<Badge content={isMac() ? '⌘' : 'Ctrl'} variant="secondary" size="xs" />
|
||||
<Badge content="G" variant="secondary" size="xs" />
|
||||
</Layout.Stack>
|
||||
<Typography.Caption variant="400" color="--fgcolor-neutral-secondary">
|
||||
|
||||
+2
-1
@@ -53,6 +53,7 @@
|
||||
RecordActivity,
|
||||
CreateIndex,
|
||||
useDatabaseSdk,
|
||||
DEFAULT_VECTOR_DIMENSION,
|
||||
type Field,
|
||||
type Index
|
||||
} from '$database/(entity)';
|
||||
@@ -277,7 +278,7 @@
|
||||
|
||||
const dbType = data.database?.type;
|
||||
const isVectorsDb = dbType === 'vectorsdb';
|
||||
const dimension = collection?.dimension ?? 768;
|
||||
const dimension = collection?.dimension ?? DEFAULT_VECTOR_DIMENSION;
|
||||
|
||||
// For vectorsdb, wrap fields in metadata and add empty embeddings
|
||||
const documents = isVectorsDb
|
||||
|
||||
+1
-1
@@ -260,7 +260,7 @@
|
||||
{/snippet}
|
||||
</EmptySheet>
|
||||
{:else}
|
||||
<EmptySheet mode="records" type="documentsdb" showActions={$canWriteRows}>
|
||||
<EmptySheet mode="records" type={data.database.type} showActions={$canWriteRows}>
|
||||
{#snippet actions()}
|
||||
<EmptySheetCards
|
||||
icon={IconViewBoards}
|
||||
|
||||
+4
-3
@@ -1,12 +1,12 @@
|
||||
import { Dependencies, SPREADSHEET_PAGE_LIMIT } from '$lib/constants';
|
||||
import { getLimit, getPage, getQuery, getView, pageToOffset, View } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { queries, queryParamToMap } from '$lib/components/filters';
|
||||
import { buildGridQueries, extractSortFromQueries } from '$database/store';
|
||||
import { getCollectionService } from '$database/(entity)';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url, route, parent }) => {
|
||||
const { collection } = await parent();
|
||||
const { collection, database } = await parent();
|
||||
depends(Dependencies.DOCUMENTS);
|
||||
|
||||
const page = getPage(url);
|
||||
@@ -20,6 +20,7 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
|
||||
queries.set(parsedQueries);
|
||||
|
||||
const currentSort = extractSortFromQueries(parsedQueries);
|
||||
const collectionSdk = getCollectionService(params.region, params.project, database.type);
|
||||
|
||||
return {
|
||||
offset,
|
||||
@@ -28,7 +29,7 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
|
||||
query,
|
||||
currentSort,
|
||||
parsedQueries,
|
||||
documents: await sdk.forProject(params.region, params.project).documentsDB.listDocuments({
|
||||
documents: await collectionSdk.listDocuments({
|
||||
databaseId: params.database,
|
||||
collectionId: params.collection,
|
||||
queries: buildGridQueries(limit, offset, parsedQueries, collection)
|
||||
|
||||
+3
-6
@@ -1,8 +1,8 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { getCollectionService } from '$database/(entity)';
|
||||
|
||||
export const load: PageLoad = async ({ params, url, route, parent }) => {
|
||||
const { database } = await parent();
|
||||
@@ -10,15 +10,12 @@ export const load: PageLoad = async ({ params, url, route, parent }) => {
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
const projectSdk = sdk.forProject(params.region, params.project);
|
||||
const logsFn = database.type === 'vectorsdb'
|
||||
? projectSdk.vectorsDB.listCollectionLogs.bind(projectSdk.vectorsDB)
|
||||
: projectSdk.documentsDB.listCollectionLogs.bind(projectSdk.documentsDB);
|
||||
const collectionSdk = getCollectionService(params.region, params.project, database.type);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await logsFn({
|
||||
logs: await collectionSdk.listCollectionLogs({
|
||||
databaseId: params.database,
|
||||
collectionId: params.collection,
|
||||
queries: [Query.limit(limit), Query.offset(offset)]
|
||||
|
||||
+3
-6
@@ -1,7 +1,7 @@
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { UsageRange } from '@appwrite.io/console';
|
||||
import type { PageLoad } from './$types';
|
||||
import { getCollectionService } from '$database/(entity)';
|
||||
|
||||
export const load: PageLoad = async ({ params, parent }) => {
|
||||
const { database } = await parent();
|
||||
@@ -9,13 +9,10 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
? params.period
|
||||
: UsageRange.ThirtyDays;
|
||||
|
||||
const projectSdk = sdk.forProject(params.region, params.project);
|
||||
const usageFn = database.type === 'vectorsdb'
|
||||
? projectSdk.vectorsDB.getCollectionUsage.bind(projectSdk.vectorsDB)
|
||||
: projectSdk.documentsDB.getCollectionUsage.bind(projectSdk.documentsDB);
|
||||
const collectionSdk = getCollectionService(params.region, params.project, database.type);
|
||||
|
||||
return {
|
||||
...(await usageFn({
|
||||
...(await collectionSdk.getCollectionUsage({
|
||||
databaseId: params.database,
|
||||
collectionId: params.collection,
|
||||
range: period
|
||||
|
||||
Reference in New Issue
Block a user