diff --git a/src/lib/components/filters/store.ts b/src/lib/components/filters/store.ts index 6be45f6a0..970874334 100644 --- a/src/lib/components/filters/store.ts +++ b/src/lib/components/filters/store.ts @@ -1,10 +1,10 @@ import { goto } from '$app/navigation'; -import { derived, get, writable } from 'svelte/store'; import { page } from '$app/stores'; import deepEqual from 'deep-equal'; -import type { Column, ColumnType } from '$lib/helpers/types'; import { Query } from '@appwrite.io/console'; import { toLocaleDateTime } from '$lib/helpers/date'; +import { derived, get, writable } from 'svelte/store'; +import type { SheetColumn, SheetColumnType } from '$lib/helpers/types'; export type TagValue = { tag: string; @@ -14,7 +14,7 @@ export type TagValue = { export type Operator = { toTag: (attribute: string, input?: string | number | string[], type?: string) => TagValue; toQuery: (attribute: string, input?: string | number | string[]) => string; - types: ColumnType[]; + types: SheetColumnType[]; hideInput?: boolean; }; @@ -33,7 +33,7 @@ function initQueries(initialValue = new Map()) { type AddFilterArgs = { operator: Operator; - column: Column; + column: SheetColumn; value: string | number | string[]; }; @@ -91,14 +91,14 @@ export const tags = derived(queries, ($queries) => Array.from($queries.keys())); /* eslint @typescript-eslint/no-explicit-any: 'off' */ export function addFilter( - columns: Column[], + columns: SheetColumn[], columnId: string, operatorKey: string, value: any, // We cast to any to not cause type errors in the input components arrayValues: string[] = [] ) { const operator = operatorKey ? operators[operatorKey] : null; - const column = columns.find((c) => c.id === columnId) as Column; + const column = columns.find((c) => c.id === columnId) as SheetColumn; if (!column || !operator) return; if (column.array) { queries.addFilter({ column, operator, value: arrayValues }); @@ -135,7 +135,7 @@ const operatorsDefault = new Map< ValidOperators, { query: (attr: string, input: string | number | string[]) => string; - types: ColumnType[]; + types: SheetColumnType[]; hideInput?: boolean; } >([ diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte index e097213a1..ab482f31b 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.svelte @@ -20,11 +20,12 @@ import { addNotification } from '$lib/stores/notifications'; import { Click, Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { isSmallViewport } from '$lib/stores/viewport'; - import { base } from '$app/paths'; import { IconPlus } from '@appwrite.io/pink-icons-svelte'; import type { Models } from '@appwrite.io/console'; - import EmptySheet from './emptySheet.svelte'; + import EmptySheet from './layout/emptySheet.svelte'; import CreateRecord from './createRecord.svelte'; + import { goto } from '$app/navigation'; + import { base } from '$app/paths'; export let data: PageData; @@ -135,7 +136,7 @@ {#if hasAttributes && hasValidAttributes} {#if data.documents.total} - + {:else if $hasPageQueries}
@@ -159,10 +160,30 @@
{:else} - (showRecordsCreateSheet = true)} /> + { + showRecordsCreateSheet = true; + } + } + }} /> {/if} {:else} - (showRecordsCreateSheet = true)} /> + { + await goto( + `${base}/project-${page.params.region}-${page.params.project}/databases/database-${page.params.database}/collection-${page.params.collection}/attributes` + ); + } + } + }} /> {/if} {/key} @@ -186,6 +207,4 @@ }} /> {/if} -{#if showRecordsCreateSheet} - -{/if} + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.ts index 2f22ca60f..a8a40b4c1 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+page.ts @@ -8,7 +8,8 @@ import { queries, queryParamToMap } from '$lib/components/filters'; export const load: PageLoad = async ({ params, depends, url, route }) => { depends(Dependencies.DOCUMENTS); const page = getPage(url); - const limit = getLimit(url, route, 18 /*PAGE_LIMIT*/); + // TODO: apply pagination + const limit = getLimit(url, route, 96 /*PAGE_LIMIT*/); const view = getView(url, route, View.Grid); const offset = pageToOffset(page, limit); const query = getQuery(url); diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte index e94163b7b..211b1dcad 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte @@ -1,7 +1,4 @@ - - - Attributes + + + {#if $canWriteCollections} {/if} + +
{#if $attributes.length} - - - Key - Type - Default value - - - {#each $attributes as attribute, index} - {@const option = attributeOptions.find((option) => option.type === attribute.type)} - - - - {#if isRelationship(attribute)} - - {:else if 'format' in attribute && attribute.format} - {@const icon = attributeFormatIcon[attribute?.format]} - - {:else} - - {/if} - - - {attribute.key} - {#if isString(attribute) && attribute.encrypt} - - -
Encrypted
-
+ + + + Column name + Indexed + Default value + + + + {#each $attributes as attribute, index} + {@const option = attributeOptions.find( + (option) => option.type === attribute.type + )} + + + + {#if isRelationship(attribute)} + + {:else if 'format' in attribute && attribute.format} + {@const icon = attributeFormatIcon[attribute?.format]} + + {:else} + + {/if} + + + {attribute.key} + {#if isString(attribute) && attribute.encrypt} + + +
Encrypted
+
+ {/if} +
+ {#if attribute.status !== 'available'} + + {#if attribute.error} + { + e.preventDefault(); + error = attribute.error; + showFailed = true; + }}>Details + {/if} + {:else if attribute.required} + {/if}
- {#if attribute.status !== 'available'} - - {#if attribute.error} - { - e.preventDefault(); - error = attribute.error; - showFailed = true; - }}>Details - {/if} - {:else if attribute.required} - - {/if}
-
-
- - {#if 'format' in attribute && attribute.format} - {attribute.format} - {:else} -

- {attribute.type} - {#if isRelationship(attribute)} - - with {attribute?.key} - - {/if} -

- {/if} - - {attribute.array ? '[]' : ''} - -
- - {attribute?.default !== null && attribute?.default !== undefined - ? attribute?.default - : '-'} - - - {#if $isCsvImportInProgress} - - - - {:else} - - - - { - toggle(event); - showEdit = true; - selectedAttribute = attribute; - showDropdown[index] = false; - }}> - Update - - {#if !isRelationship(attribute)} + + + {@const isIndexed = $indexes.some((index) => + index.attributes.includes(attribute.key) + )} + + + + {@const _default = + attribute?.default !== null && attribute?.default !== undefined + ? attribute?.default + : null} + + {#if _default === null} + + {:else} + {_default} + {/if} + + + {#if $isCsvImportInProgress} + + + + {:else} + + + + { toggle(event); + showEdit = true; selectedAttribute = attribute; - showCreateIndex = true; showDropdown[index] = false; }}> - Create index + Update - {/if} - {#if attribute.status !== 'processing'} - { - toggle(event); - showDelete = true; - showDropdown[index] = false; - selectedAttribute = attribute; - trackEvent(Click.DatabaseAttributeDelete); - }}> - Delete - - {/if} - - - {/if} - -
- {/each} -
+ {#if !isRelationship(attribute)} + { + toggle(event); + selectedAttribute = attribute; + showCreateIndex = true; + showDropdown[index] = false; + }}> + Create index + + {/if} + {#if attribute.status !== 'processing'} + { + toggle(event); + showDelete = true; + showDropdown[index] = false; + selectedAttribute = attribute; + trackEvent(Click.DatabaseAttributeDelete); + }}> + Delete + + {/if} + + + {/if} + + + {/each} + + + + + {$attributes.length} columns + + + + + {:else} - - - - {#if $canWriteCollections} - - - - {/if} - - + + + {/if} - +
{#if showCreate} @@ -255,8 +273,17 @@ {/if} {#if showEdit} - + await editAttribute.submit() + }}> + + {/if} + {#if showCreateIndex} {/if} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/createAttributeDropdown.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/createAttributeDropdown.svelte index 201ef960f..06a15f7ce 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/createAttributeDropdown.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/createAttributeDropdown.svelte @@ -6,8 +6,8 @@ import CsvDisabled from '../csvDisabled.svelte'; import { isCsvImportInProgress } from '../store'; - export let selectedOption: Option['name'] = null; export let showCreate = false; + export let selectedOption: Option['name'] = null; {#if $isCsvImportInProgress} @@ -20,9 +20,9 @@ {:else} - diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/edit.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/edit.svelte index 9a1b9b3d0..9de4c8943 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/edit.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/edit.svelte @@ -43,7 +43,7 @@ } }) as Option; - async function submit() { + export async function submit() { try { await option.update(databaseId, collectionId, selectedAttribute, originalKey); await invalidate(Dependencies.COLLECTION); @@ -58,6 +58,7 @@ type: 'success', message: `Attribute ${selectedAttribute.key} has been updated` }); + showEdit = false; trackEvent(Submit.AttributeUpdate); diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/create/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/create/+page.svelte deleted file mode 100644 index 4390fc590..000000000 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/create/+page.svelte +++ /dev/null @@ -1,135 +0,0 @@ - - - -
Create document
- -
- -
- -
- -
- - - Choose which permission scopes to grant your application. It is best - practice to allow only the permissions you need to meet your project goals. - - {#if data.collection.documentSecurity} - - Document security is enabled - Users will be able to access this document if they have been granted - either document or collection permissions. - - - {:else} - - Document security is disabled - If you want to assign document permissions, navigate to Collection settings - and enable document security. Otherwise, only collection permissions will - be used. - - {/if} - -
-
-
- - - - - - - - - - -
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/createRecord.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/createRecord.svelte index f082fb3f0..025f0a7ff 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/createRecord.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/createRecord.svelte @@ -1,7 +1,5 @@
- - - - Create document + + create() + }}> + + - + + + Choose which permission scopes to grant your application. It is best practice to + allow only the permissions you need to meet your project goals. + + {#if collection.documentSecurity} + + Document security is enabled + Users will be able to access this document if they have been granted + either document or collection permissions. + + + {:else} + + Document security is disabled + If you want to assign document permissions, navigate to Collection settings and + enable document security. Otherwise, only collection permissions will be used. + + {/if} - - -
- - - - - - - Choose which permission scopes to grant your application. It is best - practice to allow only the permissions you need to meet your project - goals. - - {#if collection.documentSecurity} - - Document security is enabled - Users will be able to access this document if they have been granted - either document or collection permissions. - - - {:else} - - Document security is disabled - If you want to assign document permissions, navigate to Collection settings - and enable document security. Otherwise, only collection permissions - will be used. - - {/if} - - - - - -
-
+ +
- - diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/emptySheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/emptySheet.svelte deleted file mode 100644 index 03a1a5332..000000000 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/emptySheet.svelte +++ /dev/null @@ -1,173 +0,0 @@ - - -
- - - {#each staticColumns as column (column.id)} - {#if column.isAction} - - {}}> - - - - {:else} - - {column.title} - - {/if} - {/each} - - - -
-
- - You have no records yet - - - dispatch('record')}> - - Create record - - - - dispatch('random')}> - Generate random data - - - Yet to be added - - - -
-
-
- - diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte index f9258a35b..bd33d7299 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte @@ -1,5 +1,4 @@ - - - Indexes + + {#if $canWriteCollections} {/if} + +
{#if data.collection?.attributes?.length} {#if data.collection.indexes.length} - - - Key - Type - Attributes - Orders - Lengths - - - {#each data.collection.indexes as index} - - - - {index.key} - {#if index.status !== 'available'} - - {#if index.error} - { - e.preventDefault(); - error = index.error; - showFailed = true; - }}>Details + + + + Key + Type + Attributes + Orders + Lengths + + + {#each data.collection.indexes as index} + + + + {index.key} + {#if index.status !== 'available'} + + {#if index.error} + { + e.preventDefault(); + error = index.error; + showFailed = true; + }}>Details + {/if} {/if} - {/if} - - - {index.type} - - {index.attributes} - - - {index.orders} - - - {index.lengths} - - - - - - { - selectedIndex = index; - showOverview = true; - }}>Overview - { - selectedIndex = index; - showDelete = true; - trackEvent(Click.DatabaseIndexDelete); - }}>Delete - - - - - {/each} - + + + {index.type} + + {index.attributes} + + + {index.orders} + + + {index.lengths} + + + + + + { + selectedIndex = index; + showOverview = true; + }}>Overview + { + selectedIndex = index; + showDelete = true; + trackEvent(Click.DatabaseIndexDelete); + }}>Delete + + + + + {/each} + + {:else} - (showCreateIndex = true)} /> + (showCreateIndex = true), + disabled: !$collection?.attributes?.length + } + }} /> {/if} {:else} - - - - {#if $canWriteCollections} - - - - {/if} - - + + { + await goto( + `${base}/project-${page.params.region}-${page.params.project}/databases/database-${page.params.database}/collection-${page.params.collection}/attributes` + ); + } + } + }} /> {/if} - +
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/emptySheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/emptySheet.svelte new file mode 100644 index 000000000..7cf96f59b --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/emptySheet.svelte @@ -0,0 +1,241 @@ + + +
+ + + {#each spreadsheetColumns as column (column.id)} + + {#if column.isAction} + + + + {:else} + {column.title} + {/if} + + {/each} + + + +
+
+ + {title ?? `You have no ${mode} yet`} + + + + + {cta?.primary?.text ?? `Create ${mode}`} + + + {#if mode === 'records'} + + + {cta?.random?.text ?? `Generate random data`} + + Yet to be added + + {/if} + + +
+
+
+ + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/sidesheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/sidesheet.svelte new file mode 100644 index 000000000..058a7bac4 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/sidesheet.svelte @@ -0,0 +1,91 @@ + + +
+ +
+ + + {title} + + +
+ + + + {@render children()} + + + + +
+
+ + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/spreadsheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/spreadsheet.svelte new file mode 100644 index 000000000..34d70515e --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/layout/spreadsheet.svelte @@ -0,0 +1,24 @@ + + + + +
+ +
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte index 071003b73..3d55795e8 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte @@ -31,9 +31,7 @@ FloatingActionBar, Icon, InteractiveText, - Typography, - Sheet, - Divider + Typography } from '@appwrite.io/pink-svelte'; import { toLocaleDateTime } from '$lib/helpers/date'; import DualTimeView from '$lib/components/dualTimeView.svelte'; @@ -58,30 +56,23 @@ import { type Action } from './sheetOptions.svelte'; import EditAttribute from './attributes/edit.svelte'; import { isSmallViewport } from '$lib/stores/viewport'; + import SideSheet from './layout/sidesheet.svelte'; + import SpreadsheetContainer from './layout/spreadsheet.svelte'; export let data: PageData; + export let showRecordsCreateSheet: boolean; const databaseId = page.params.database; const collectionId = page.params.collection; let displayNames = {}; let showRelationships = false; - let selectedRelationship: Models.AttributeRelationship = null; let relationshipData: Partial[]; - - let spreadsheetHeight = '75vh'; - let spreadsheetWrapper: HTMLDivElement; + let selectedRelationship: Models.AttributeRelationship = null; $: documents = data.documents; - function resizeSheet() { - if (!spreadsheetWrapper) return; - const rect = spreadsheetWrapper.getBoundingClientRect(); - spreadsheetHeight = window.innerHeight - rect.top + 'px'; - } - onMount(async () => { - resizeSheet(); displayNames = preferences.getDisplayNames(); }); @@ -316,7 +307,7 @@ if (type === 'update') { $databaseSheetOptions.show = true; $databaseSheetOptions.isEdit = true; - $databaseSheetOptions.title = 'update column'; + $databaseSheetOptions.title = 'Update column'; } if (type === 'column-left' || type === 'column-right') { @@ -339,13 +330,7 @@ : emptyCellsLimit - data.documents.documents.length; - - -
+ - {}}> + (showRecordsCreateSheet = true)}> @@ -553,7 +541,7 @@
{/if} - + @@ -624,49 +612,19 @@

-
- -
- - - {$databaseSheetOptions.title} - - -
- - - - - - - - -
-
+ $databaseSheetOptions.submitAction() + }}> + +