|
21 | 21 | import { |
22 | 22 | type ColumnInput, |
23 | 23 | mapSuggestedColumns, |
24 | | - mockSuggestions, |
25 | 24 | type SuggestedColumnSchema, |
26 | 25 | tableColumnSuggestions, |
27 | | - basicColumnOptions |
| 26 | + basicColumnOptions, |
| 27 | + mockSuggestions |
28 | 28 | } from './store'; |
29 | 29 | import { addNotification } from '$lib/stores/notifications'; |
30 | 30 | import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; |
31 | 31 | import { sleep } from '$lib/helpers/promises'; |
32 | 32 | import { invalidate } from '$app/navigation'; |
33 | 33 | import { Dependencies } from '$lib/constants'; |
34 | 34 | import type { Columns } from '../table-[table]/store'; |
35 | | -
|
36 | | - import { isDev } from '$lib/system'; |
37 | 35 | import { columnOptions } from '../table-[table]/columns/store'; |
38 | 36 | import Options from './options.svelte'; |
39 | 37 | import { InputSelect, InputText } from '$lib/elements/forms'; |
40 | 38 | import { Confirm } from '$lib/components'; |
41 | 39 |
|
42 | | - // No props needed - we handle column creation directly |
43 | | -
|
44 | 40 | let resizeObserver: ResizeObserver; |
45 | 41 | let spreadsheetContainer: HTMLElement; |
46 | 42 |
|
|
262 | 258 | size: col.size, |
263 | 259 | min: col.min, |
264 | 260 | max: col.max, |
265 | | - width: 180, |
| 261 | + // TODO: @itznotabug, we should use a dynamic min width based on column's name. |
| 262 | + width: { min: 180 }, |
266 | 263 | icon: columnOption?.icon, |
267 | 264 | draggable: false, |
268 | 265 | resizable: false |
|
323 | 320 | await suggestColumns(); |
324 | 321 | }); |
325 | 322 |
|
| 323 | + function resetSuggestionsStore(fullReset: boolean = true) { |
| 324 | + if (fullReset) { |
| 325 | + // these are referenced in |
| 326 | + // `table-[table]/+page.svelte` |
| 327 | + $tableColumnSuggestions.table = null; |
| 328 | + $tableColumnSuggestions.enabled = false; |
| 329 | + } |
| 330 | +
|
| 331 | + $tableColumnSuggestions.context = null; |
| 332 | + $tableColumnSuggestions.thinking = false; |
| 333 | + } |
| 334 | +
|
| 335 | + /** |
| 336 | + * Mark this as `true` when developing locally, |
| 337 | + * make sure not to spend credits unnecessarily! |
| 338 | + */ |
| 339 | + const useMockSuggestions = false; |
326 | 340 | async function suggestColumns() { |
327 | 341 | $tableColumnSuggestions.thinking = true; |
| 342 | + let suggestedColumns: { |
| 343 | + total: number; |
| 344 | + columns: ColumnInput[]; |
| 345 | + } = { |
| 346 | + total: 0, |
| 347 | + columns: [] |
| 348 | + }; |
328 | 349 |
|
329 | 350 | try { |
330 | | - await sleep(1250); |
331 | | - const suggestedColumns = isDev |
332 | | - ? mockSuggestions |
333 | | - : ((await sdk |
334 | | - .forProject(page.params.region, page.params.project) |
335 | | - .console.suggestColumns({ |
336 | | - databaseId: page.params.database, |
337 | | - tableId: page.params.table, |
338 | | - context: $tableColumnSuggestions.context ?? undefined |
339 | | - })) as unknown as { |
340 | | - total: number; |
341 | | - columns: ColumnInput[]; |
342 | | - }); |
| 351 | + if (useMockSuggestions) { |
| 352 | + /* animation */ |
| 353 | + await sleep(1250); |
| 354 | + suggestedColumns = mockSuggestions; |
| 355 | + } else { |
| 356 | + suggestedColumns = (await sdk |
| 357 | + .forProject(page.params.region, page.params.project) |
| 358 | + .console.suggestColumns({ |
| 359 | + databaseId: page.params.database, |
| 360 | + tableId: page.params.table, |
| 361 | + context: $tableColumnSuggestions.context ?? undefined |
| 362 | + })) as unknown as { |
| 363 | + total: number; |
| 364 | + columns: ColumnInput[]; |
| 365 | + }; |
| 366 | + } |
343 | 367 |
|
| 368 | + const tableName = $tableColumnSuggestions.table?.name ?? undefined; |
344 | 369 | trackEvent(Submit.ColumnSuggestions, { |
345 | | - total: suggestedColumns.total, |
346 | | - tableName: $tableColumnSuggestions.table?.name ?? undefined |
| 370 | + tableName, |
| 371 | + total: suggestedColumns.total |
347 | 372 | }); |
348 | 373 |
|
349 | 374 | customColumns = mapSuggestedColumns(suggestedColumns.columns); |
350 | 375 |
|
351 | | - // Set hasTransitioned to disable future animations after initial state change |
352 | 376 | if (customColumns.length > 0) { |
353 | | - setTimeout(() => (hasTransitioned = true), 300); // After transition completes |
354 | | -
|
355 | | - setTimeout(() => scrollToFirstCustomColumn(), 100); |
| 377 | + setTimeout(scrollToFirstCustomColumn, 100); |
| 378 | + setTimeout(() => (hasTransitioned = true), 300); |
356 | 379 | } |
357 | 380 | } catch (error) { |
358 | 381 | addNotification({ |
|
362 | 385 |
|
363 | 386 | trackError(error, Submit.ColumnSuggestions); |
364 | 387 | } finally { |
365 | | - // $tableColumnSuggestions.table = null; |
366 | | - $tableColumnSuggestions.context = null; |
367 | | - // $tableColumnSuggestions.enabled = false; |
368 | | - $tableColumnSuggestions.thinking = false; |
| 388 | + resetSuggestionsStore(false); |
369 | 389 | } |
370 | 390 | } |
371 | 391 |
|
|
511 | 531 |
|
512 | 532 | await invalidate(Dependencies.TABLE); |
513 | 533 |
|
514 | | - // Reset state |
515 | | - customColumns = []; |
516 | | - $tableColumnSuggestions.context = null; |
517 | | - $tableColumnSuggestions.enabled = false; |
518 | | -
|
519 | 534 | addNotification({ |
520 | 535 | type: 'success', |
521 | 536 | message: 'Columns created successfully' |
|
528 | 543 | type: 'error', |
529 | 544 | message: error.message |
530 | 545 | }); |
531 | | - } finally { |
532 | 546 | creatingColumns = false; |
533 | 547 | } |
534 | 548 | } |
|
539 | 553 | if (scrollAnimationFrame) { |
540 | 554 | cancelAnimationFrame(scrollAnimationFrame); |
541 | 555 | } |
| 556 | +
|
| 557 | + customColumns = []; |
| 558 | + resetSuggestionsStore(); |
542 | 559 | }); |
543 | 560 |
|
544 | 561 | function isCustomColumn(id: string) { |
|
559 | 576 | aria-hidden="true" |
560 | 577 | bind:this={rangeOverlayEl} |
561 | 578 | class="columns-range-overlay" |
562 | | - class:thinking={$tableColumnSuggestions.thinking} |
563 | | - class:no-transition={hasTransitioned && customColumns.length > 0}> |
| 579 | + class:no-transition={hasTransitioned && customColumns.length > 0} |
| 580 | + class:thinking={$tableColumnSuggestions.thinking || creatingColumns}> |
564 | 581 | </div> |
565 | 582 | </div> |
566 | 583 |
|
|
595 | 612 | {#snippet children(toggle)} |
596 | 613 | <Spreadsheet.Header.Cell |
597 | 614 | {root} |
| 615 | + isEditable |
598 | 616 | column={column.id} |
599 | 617 | on:contextmenu={(event) => { |
600 | 618 | if (isColumnInteractable) { |
|
760 | 778 | <Button.Button |
761 | 779 | size="xs" |
762 | 780 | variant="secondary" |
763 | | - on:click={() => { |
764 | | - $tableColumnSuggestions.context = null; |
765 | | - $tableColumnSuggestions.enabled = false; |
766 | | - $tableColumnSuggestions.thinking = false; |
767 | | - }} |
| 781 | + on:click={() => resetSuggestionsStore()} |
768 | 782 | >Cancel |
769 | 783 | </Button.Button> |
770 | 784 | </svelte:fragment> |
771 | 785 | </FloatingActionBar> |
772 | 786 | </div> |
773 | 787 | {:else if customColumns.length > 0 && showFloatingBar} |
774 | | - <div class="floating-action-wrapper expanded"> |
| 788 | + <div |
| 789 | + class="floating-action-wrapper" |
| 790 | + class:expanded={!creatingColumns} |
| 791 | + class:creating-columns={creatingColumns}> |
775 | 792 | <FloatingActionBar> |
776 | 793 | <svelte:fragment slot="start"> |
777 | | - {#if creatingColumns} |
778 | | - <Spinner size="s" /> |
779 | | - {/if} |
| 794 | + <Layout.Stack gap="xl" direction="row" alignItems="center"> |
| 795 | + {#if creatingColumns} |
| 796 | + <Spinner size="s" /> |
| 797 | + {/if} |
780 | 798 |
|
781 | | - <Typography.Text style="white-space: nowrap"> |
782 | | - {creatingColumns |
783 | | - ? 'Creating columns...' |
784 | | - : $isSmallViewport |
785 | | - ? 'Review and edit columns' |
786 | | - : 'Review and edit suggested columns before applying'} |
787 | | - </Typography.Text> |
| 799 | + <Typography.Text style="white-space: nowrap"> |
| 800 | + {creatingColumns |
| 801 | + ? 'Creating columns...' |
| 802 | + : $isSmallViewport |
| 803 | + ? 'Review and edit columns' |
| 804 | + : 'Review and edit suggested columns before applying'} |
| 805 | + </Typography.Text> |
| 806 | + </Layout.Stack> |
788 | 807 | </svelte:fragment> |
789 | 808 |
|
790 | 809 | <svelte:fragment slot="end"> |
|
814 | 833 | bind:open={confirmDismiss} |
815 | 834 | onSubmit={() => { |
816 | 835 | customColumns = []; |
817 | | - $tableColumnSuggestions.context = null; |
818 | | - $tableColumnSuggestions.enabled = false; |
| 836 | + resetSuggestionsStore(); |
819 | 837 | }}> |
820 | 838 | Are you sure you want to dismiss these columns suggested by AI? This action is irreversible. |
821 | 839 | </Confirm> |
|
900 | 918 | max-width: 400px !important; |
901 | 919 | } |
902 | 920 | } |
| 921 | +
|
| 922 | + &.creating-columns :global(:first-child) { |
| 923 | + max-width: 300px !important; |
| 924 | + } |
903 | 925 | } |
904 | 926 |
|
905 | 927 | & :global(.spreadsheet-container) { |
|
0 commit comments