Merge remote-tracking branch 'origin/main' into feat-csv-export

This commit is contained in:
Jake Barnby
2025-10-24 00:08:43 +13:00
8 changed files with 92 additions and 30 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
"PUBLIC_CONSOLE_MODE=cloud"
"PUBLIC_CONSOLE_FEATURE_FLAGS="
"PUBLIC_APPWRITE_MULTI_REGION=true"
"PUBLIC_CONSOLE_EMAIL_VERIFICATION=false"
"PUBLIC_CONSOLE_EMAIL_VERIFICATION=true"
"PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS=false"
"PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}"
"PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY }}"
+2 -2
View File
@@ -24,9 +24,9 @@
"@ai-sdk/svelte": "^1.1.24",
"@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@14f6db1",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@8f82877",
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@10305c4",
"@appwrite.io/pink-legacy": "^1.0.3",
"@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@8f82877",
"@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@10305c4",
"@faker-js/faker": "^9.9.0",
"@popperjs/core": "^2.11.8",
"@sentry/sveltekit": "^8.38.0",
+10 -10
View File
@@ -18,14 +18,14 @@ importers:
specifier: 0.25.0
version: 0.25.0
'@appwrite.io/pink-icons-svelte':
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@8f82877
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@8f82877(svelte@5.25.3)
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@10305c4
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@10305c4(svelte@5.25.3)
'@appwrite.io/pink-legacy':
specifier: ^1.0.3
version: 1.0.3
'@appwrite.io/pink-svelte':
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@8f82877
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@8f82877(svelte@5.25.3)
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@10305c4
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@10305c4(svelte@5.25.3)
'@faker-js/faker':
specifier: ^9.9.0
version: 9.9.0
@@ -269,8 +269,8 @@ packages:
peerDependencies:
svelte: ^4.0.0
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@8f82877':
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@8f82877}
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@10305c4':
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@10305c4}
version: 2.0.0-RC.1
peerDependencies:
svelte: ^4.0.0
@@ -284,8 +284,8 @@ packages:
'@appwrite.io/pink-legacy@1.0.3':
resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==}
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@8f82877':
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@8f82877}
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@10305c4':
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@10305c4}
version: 2.0.0-RC.2
peerDependencies:
svelte: ^4.0.0
@@ -3709,7 +3709,7 @@ snapshots:
dependencies:
svelte: 5.25.3
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@8f82877(svelte@5.25.3)':
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@10305c4(svelte@5.25.3)':
dependencies:
svelte: 5.25.3
@@ -3722,7 +3722,7 @@ snapshots:
'@appwrite.io/pink-icons': 1.0.0
the-new-css-reset: 1.11.3
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@8f82877(svelte@5.25.3)':
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@10305c4(svelte@5.25.3)':
dependencies:
'@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.25.3)
'@floating-ui/dom': 1.6.13
@@ -135,7 +135,8 @@
title="Verify your email address"
{onSubmit}
dismissible={false}
autoClose={false}>
autoClose={false}
backdrop={false}>
<Card.Base variant="secondary" padding="s">
<Layout.Stack gap="xxs">
<Typography.Text gap="m">
+2 -1
View File
@@ -14,6 +14,7 @@
};
export let title = '';
export let hideFooter = false;
export let backdrop: boolean = true;
let alert: HTMLElement;
@@ -29,7 +30,7 @@
</script>
<Form isModal {onSubmit}>
<Modal {size} {title} bind:open={show} {hideFooter} {dismissible}>
<Modal {backdrop} {size} {title} bind:open={show} {hideFooter} {dismissible}>
<slot slot="description" name="description" />
{#if error}
<div bind:this={alert}>
@@ -16,7 +16,7 @@
const dispatch = createEventDispatcher();
let id: string;
let id: string = '';
let error: string;
let showCustomId = false;
let disabled: boolean = false;
@@ -28,7 +28,7 @@
disabled = true;
showSubmissionLoader = true;
const project = await sdk.forConsole.projects.create({
projectId: id ?? ID.unique(),
projectId: id || ID.unique(),
name,
teamId
});
@@ -35,7 +35,8 @@
spreadsheetRenderKey,
expandTabs,
databaseRelatedRowSheetOptions,
rowPermissionSheet
rowPermissionSheet,
type Columns
} from './store';
import { addSubPanel, registerCommands, updateCommandGroupRanks } from '$lib/commandCenter';
import CreateColumn from './createColumn.svelte';
@@ -56,7 +57,6 @@
import { Button, Seekbar } from '$lib/elements/forms';
import { generateFakeRecords, generateColumns } from '$lib/helpers/faker';
import { addNotification } from '$lib/stores/notifications';
import { sleep } from '$lib/helpers/promises';
import CreateIndex from './indexes/createIndex.svelte';
import { hash } from '$lib/helpers/string';
import { preferences } from '$lib/stores/preferences';
@@ -66,6 +66,7 @@
import IndexesSuggestions from '../(suggestions)/indexes.svelte';
import { showIndexesSuggestions, tableColumnSuggestions } from '../(suggestions)';
import type { RealtimeResponseEvent } from '@appwrite.io/console';
let editRow: EditRow;
let editRelatedRow: EditRelatedRow;
@@ -82,6 +83,8 @@
*/
let isWaterfallFromFaker = false;
let columnCreationHandler: ((response: RealtimeResponseEvent<unknown>) => void) | null = null;
onMount(() => {
expandTabs.set(preferences.getKey('tableHeaderExpanded', true));
@@ -92,6 +95,10 @@
response.events.includes('databases.*.tables.*.columns.*') ||
response.events.includes('databases.*.tables.*.indexes.*')
) {
if (isWaterfallFromFaker) {
columnCreationHandler?.(response);
}
// don't invalidate when -
// 1. from faker
// 2. ai columns creation
@@ -253,21 +260,76 @@
indexes: 700
});
function setupColumnObserver() {
let expectedCount = 0;
let resolvePromise: () => void;
let timeout: ReturnType<typeof setTimeout>;
const availableColumns = new Set<string>();
const waitPromise = new Promise<void>((resolve) => (resolvePromise = resolve));
columnCreationHandler = (response) => {
const { events, payload } = response;
if (
events.includes('databases.*.tables.*.columns.*.create') ||
events.includes('databases.*.tables.*.columns.*.update')
) {
const asColumn = payload as Columns;
const columnId = asColumn.key;
const status = asColumn.status;
if (status === 'available') {
availableColumns.add(columnId);
if (expectedCount > 0 && availableColumns.size >= expectedCount) {
clearTimeout(timeout);
columnCreationHandler = null;
resolvePromise();
}
}
}
};
// return function to start waiting!
const startWaiting = (count: number) => {
expectedCount = count;
timeout = setTimeout(() => {
columnCreationHandler = null;
resolvePromise();
}, 10000);
if (availableColumns.size >= expectedCount) {
clearTimeout(timeout);
columnCreationHandler = null;
resolvePromise();
}
};
return { startWaiting, waitPromise };
}
async function createFakeData() {
isWaterfallFromFaker = true;
$spreadsheetLoading = true;
$randomDataModalState.show = false;
let columns = $table.columns;
let columns = page.data.table.columns as Columns[];
const hasAnyRelationships = columns.some((column) => isRelationship(column));
const filteredColumns = columns.filter((col) => col.type !== 'relationship');
if (!filteredColumns.length) {
try {
const { startWaiting, waitPromise } = setupColumnObserver();
columns = await generateColumns($project, page.params.database, page.params.table);
startWaiting(columns.length);
await waitPromise;
await invalidate(Dependencies.TABLE);
columns = page.data.table.columns as Columns[];
trackEvent(Submit.ColumnCreate, { type: 'faker' });
} catch (e) {
addNotification({
@@ -279,9 +341,6 @@
}
}
/* let the columns be processed! */
await sleep(1250);
let rowIds = [];
try {
const { rows, ids } = generateFakeRecords(columns, $randomDataModalState.value);
@@ -306,8 +306,8 @@
<SpreadsheetContainer>
<Spreadsheet.Root
let:root
allowSelection
height="100%"
allowSelection
emptyCells={emptyCellsCount}
bind:selectedRows={selectedColumns}
columns={spreadsheetColumns}
@@ -323,6 +323,7 @@
</svelte:fragment>
{#each updatedColumnsForSheet as column, index (column.key)}
{@const isId = column.key === '$id'}
{@const option = columnOptions.find((option) => option.type === column.type)}
{@const isSelectable =
column['system'] || column.type === 'relationship' ? 'disabled' : true}
@@ -425,11 +426,12 @@
{columnType.toLowerCase()}
</Spreadsheet.Cell>
<Spreadsheet.Cell column="indexed" {root} isEditable={false}>
{@const isActuallyIndexed = $indexes.some((index) =>
index.columns.includes(column.key)
)}
<!-- $id is always indexed internally -->
{@const isActuallyIndexed =
isId || $indexes.some((index) => index.columns.includes(column.key))}
{@const checked = isActuallyIndexed || !!columnIndexMap[column.key]}
<!-- $id is always indexed internally -->
{@const checked = isId || isActuallyIndexed || !!columnIndexMap[column.key]}
<Selector.Checkbox
size="s"
@@ -467,8 +469,7 @@
<Icon icon={IconDotsHorizontal} size="s" />
</Button>
</CsvDisabled>
{:else if column.key !== '$sequence'}
<!-- TODO: no portal, rather see if we can fix the cell -->
{:else if !isId}
<Popover let:toggle padding="none" placement="bottom-end" portal>
<Button text icon ariaLabel="more options" on:click={toggle}>
<Icon icon={IconDotsHorizontal} size="s" />