From b0b2fe8ffda3b526e043011b580263f0a5980613 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 1 Sep 2025 20:50:56 +0200 Subject: [PATCH] feat: embeddable routes The changes in this commit refactor several console pages by extracting the main UI logic into separate view components. This allows the same views to be reused between the main console and embedding contexts. Key changes: - Move page content into view components for auth, database, messaging, and storage sections - Add embedded versions of pages that reuse the view components - Update layout configurations to support embedding - Add new studio theme variations for embedded context The refactoring improves code reuse and maintainability while enabling the same UI components to be used in different contexts. --- src/routes/(console)/+layout.ts | 9 +- .../auth/+page.svelte | 178 +------------ .../auth/security/+page.svelte | 2 - .../auth/settings/+page.svelte | 128 +-------- .../auth/settings/view.svelte | 82 ++++++ .../auth/teams/+page.svelte | 97 +------ .../auth/teams/view.svelte | 104 ++++++++ .../auth/templates/+page.svelte | 148 +---------- .../auth/templates/email2FATemplate.svelte | 2 +- .../auth/templates/emailInviteTemplate.svelte | 2 +- .../templates/emailMagicUrlTemplate.svelte | 2 +- .../templates/emailOtpSessionTemplate.svelte | 2 +- .../templates/emailRecoveryTemplate.svelte | 2 +- .../emailSessionAlertTemplate.svelte | 2 +- .../emailVerificationTemplate.svelte | 2 +- .../auth/templates/resetEmail.svelte | 2 +- .../auth/templates/view.svelte | 101 +++++++ .../auth/user-[user]/+page.svelte | 24 +- .../auth/user-[user]/view.svelte | 24 ++ .../auth/view.svelte | 218 ++++++++++++++++ .../databases/+page.svelte | 109 ++------ .../database-[database]/+page.svelte | 94 +------ .../databases/database-[database]/view.svelte | 95 +++++++ .../databases/view.svelte | 143 ++++++++++ .../messaging/+page.svelte | 242 +---------------- .../messaging/view.svelte | 179 +++++++++++++ .../storage/+page.svelte | 74 +----- .../storage/bucket-[bucket]/+page.svelte | 247 +----------------- .../storage/bucket-[bucket]/view.svelte | 168 ++++++++++++ .../storage/view.svelte | 104 ++++++++ .../auth/+layout.ts | 9 + .../auth/+page.svelte | 15 ++ .../project-[region]-[project]/auth/+page.ts | 26 ++ .../auth/security/+page.svelte | 25 ++ .../auth/settings/+page.svelte | 5 + .../auth/teams/+page.svelte | 12 + .../auth/teams/+page.ts | 26 ++ .../auth/teams/team-[team]/+page.svelte | 6 + .../auth/templates/+page.svelte | 6 + .../auth/user-[user]/+page.svelte | 5 + .../auth/user-[user]/+page.ts | 12 + .../messaging/+page.svelte | 21 ++ .../messaging/+page.ts | 30 +++ src/routes/+layout.svelte | 14 +- src/themes/dark-studio.json | 6 + src/themes/index.ts | 13 +- src/themes/light-studio.json | 5 + 47 files changed, 1515 insertions(+), 1307 deletions(-) create mode 100644 src/routes/(console)/project-[region]-[project]/auth/settings/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/auth/teams/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/auth/templates/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/auth/user-[user]/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/auth/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/databases/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/messaging/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/view.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/storage/view.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/+layout.ts create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.ts create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/security/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/settings/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.ts create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/team-[team]/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/templates/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.ts create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.svelte create mode 100644 src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.ts create mode 100644 src/themes/dark-studio.json create mode 100644 src/themes/light-studio.json diff --git a/src/routes/(console)/+layout.ts b/src/routes/(console)/+layout.ts index 5aa188f90..d6c08c779 100644 --- a/src/routes/(console)/+layout.ts +++ b/src/routes/(console)/+layout.ts @@ -34,11 +34,12 @@ export const load: LayoutLoad = async ({ depends, parent }) => { if (currentOrgId) { try { projectsCount = ( - await sdk.forConsole.projects.list({ - queries: [Query.equal('teamId', currentOrgId), Query.limit(1)] - }) + await sdk.forConsole.projects.list([ + Query.equal('teamId', currentOrgId), + Query.limit(1) + ]) ).total; - } catch (e) { + } catch { projectsCount = 0; } } diff --git a/src/routes/(console)/project-[region]-[project]/auth/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/+page.svelte index 1f2dc4423..b86d2b120 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/+page.svelte @@ -3,178 +3,16 @@ - - - - - - - - - - - - {#if data.users.total} - - - {#each $columns as { id, title } (id)} - {title} - {/each} - - {#each data.users.users as user} - - {#each $columns as { id } (id)} - - {#if id === '$id'} - - - - {user.$id} - - - {:else if id === 'name'} - - {#if user.email || user.phone} - {#if user.name} - - - {user.name} - - {:else} -
- -
- {/if} - {:else} -
- -
- - {user.name} - - {/if} -
- {:else if id === 'identifiers'} - - {user.email && user.phone - ? [user.email, user.phone].join(',') - : user.email || user.phone} - - {:else if id === 'status'} - {#if user.status} - {@const success = - user.emailVerification || user.phoneVerification} - - {:else} - - {/if} - {:else if id === 'labels'} - - {user.labels.join(', ')} - - {:else if id === 'joined'} - {toLocaleDateTime(user.registration)} - {:else if id === 'lastActivity'} - {user.accessedAt ? toLocaleDate(user.accessedAt) : 'never'} - {:else} - {user[id]} - {/if} -
- {/each} -
- {/each} -
- - - {:else if data.search} - - - - {:else} - showCreateUser.set(true)} /> - {/if} -
- - + diff --git a/src/routes/(console)/project-[region]-[project]/auth/security/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/security/+page.svelte index 48718cba3..6a0cc0ec9 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/security/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/security/+page.svelte @@ -1,6 +1,5 @@ -{#if $authMethods && $project} - - - - Auth methods - Enable the authentication methods you wish to use. - - - {#each $authMethods.list as box} -
- authUpdate(box)} /> -
- {/each} -
-
-
- - OAuth2 Providers -
    - {#each $project.oAuthProviders - .filter((p) => p.name !== 'Mock') - .sort( (a, b) => (a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1) ) as provider} - {@const oAuthProvider = oAuthProviders[provider.key]} - {#if oAuthProvider} - { - selectedProvider = provider; - showProvider = true; - trackEvent(`click_select_provider`, { - provider: provider.key.toLowerCase() - }); - }}> - - - - {provider.name} - - {provider.name} - - - - - {/if} - {/each} -
-
-
-
-{/if} - -{#if selectedProvider && showProvider} - {@const oAuthProvider = oAuthProviders[selectedProvider.key]} - { - selectedProvider = null; - showProvider = false; - }} /> -{/if} + diff --git a/src/routes/(console)/project-[region]-[project]/auth/settings/view.svelte b/src/routes/(console)/project-[region]-[project]/auth/settings/view.svelte new file mode 100644 index 000000000..2f2bc6df0 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/auth/settings/view.svelte @@ -0,0 +1,82 @@ + + +{#if $authMethods && $project} + + + + Auth methods + Enable the authentication methods you wish to use. + + + {#each $authMethods.list as box} +
+ authUpdate(box)} /> +
+ {/each} +
+
+
+ + OAuth2 Providers +
    + {#each $project.oAuthProviders.filter((p) => p.name !== 'Mock').sort((a, b) => (a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1)) as provider} + {@const oAuthProvider = oAuthProviders[provider.key]} + {#if oAuthProvider} + { selectedProvider = provider; showProvider = true; trackEvent(`click_select_provider`, { provider: provider.key.toLowerCase() }); }}> + + + + {provider.name} + + {provider.name} + + + + + {/if} + {/each} +
+
+
+
+{/if} + +{#if selectedProvider && showProvider} + {@const oAuthProvider = oAuthProviders[selectedProvider.key]} + { selectedProvider = null; showProvider = false; }} /> +{/if} diff --git a/src/routes/(console)/project-[region]-[project]/auth/teams/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/teams/+page.svelte index cbefb02fb..6166968c1 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/teams/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/teams/+page.svelte @@ -1,96 +1,17 @@ - - - - - - - - - - - {#if data.teams.total} - - - Name - Members - Created - - {#each data.teams.teams as team} - - - - - {team.name} - - - - {team.total} members - - - - - - {/each} - - - - {:else if data.search} - - - - {:else} - ($showCreateTeam = true)} - href="https://appwrite.io/docs/references/cloud/client-web/teams" - target="team" /> - {/if} - - - + diff --git a/src/routes/(console)/project-[region]-[project]/auth/teams/view.svelte b/src/routes/(console)/project-[region]-[project]/auth/teams/view.svelte new file mode 100644 index 000000000..9003e4de3 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/auth/teams/view.svelte @@ -0,0 +1,104 @@ + + + + + + + + + + + + + {#if teams.total} + + + Name + Members + Created + + {#each teams.teams as team} + {@const href = getTeamUrl(team)} + {#if href} + + + + + {team.name} + + + + {team.total} members + + + + + + {:else} + + + + + {team.name} + + + + {team.total} members + + + + + + {/if} + {/each} + + + + {:else if search} + + + + {:else} + (showCreateTeam = true)} + href="https://appwrite.io/docs/references/cloud/client-web/teams" + target="team" /> + {/if} + + + diff --git a/src/routes/(console)/project-[region]-[project]/auth/templates/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/templates/+page.svelte index da7178906..740f6dd70 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/templates/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/templates/+page.svelte @@ -1,150 +1,6 @@ - - - - {#if !data.project.smtpEnabled} - - Configure a custom SMTP server to enable custom email templates and prevent emails from - being labeled as spam. - - - {/if} - - - - Email templates - - Use templates to send and process account management emails. - - Learn more - - - - {#each templates as section (section.key)} - event.detail && toggleAccordion(section.key)}> - - {section.description} - - - - {/each} - - - - - - - {#if isCloud && $currentPlan.emailBranding} - - {/if} - + diff --git a/src/routes/(console)/project-[region]-[project]/auth/templates/email2FATemplate.svelte b/src/routes/(console)/project-[region]-[project]/auth/templates/email2FATemplate.svelte index 536a1aa28..acfe98909 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/templates/email2FATemplate.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/templates/email2FATemplate.svelte @@ -1,7 +1,7 @@ + + + + + {#if !project.smtpEnabled} + + Configure a custom SMTP server to enable custom email templates and prevent emails from being labeled as spam. + + + {/if} + + + + Email templates + + Use templates to send and process account management emails. + Learn more + + + {#each templates as section (section.key)} + event.detail && toggleAccordion(section.key)}> + + {section.description} + + + + {/each} + + + + + + + {#if isCloud && $currentPlan.emailBranding} + + {/if} + diff --git a/src/routes/(console)/project-[region]-[project]/auth/user-[user]/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/user-[user]/+page.svelte index d63f21039..fea38ec91 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/user-[user]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/user-[user]/+page.svelte @@ -1,24 +1,6 @@ - - - - - - - - - - - + diff --git a/src/routes/(console)/project-[region]-[project]/auth/user-[user]/view.svelte b/src/routes/(console)/project-[region]-[project]/auth/user-[user]/view.svelte new file mode 100644 index 000000000..d63f21039 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/auth/user-[user]/view.svelte @@ -0,0 +1,24 @@ + + + + + + + + + + + + + diff --git a/src/routes/(console)/project-[region]-[project]/auth/view.svelte b/src/routes/(console)/project-[region]-[project]/auth/view.svelte new file mode 100644 index 000000000..272335085 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/auth/view.svelte @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + {#if users.total} + + + {#each $columns as { id, title } (id)} + {title} + {/each} + + + {#each users.users as user} + {@const href = getUserUrl(user)} + {#if href} + + {#each $columns as { id } (id)} + + {#if id === '$id'} + + + + {user.$id} + + + {:else if id === 'name'} + + {#if user.email || user.phone} + {#if user.name} + + + {user.name} + + {:else} +
+ +
+ {/if} + {:else} +
+ +
+ + {user.name} + + {/if} +
+ {:else if id === 'identifiers'} + + {user.email && user.phone + ? [user.email, user.phone].join(',') + : user.email || user.phone} + + {:else if id === 'status'} + {#if user.status} + {@const success = user.emailVerification || user.phoneVerification} + + {:else} + + {/if} + {:else if id === 'labels'} + + {user.labels.join(', ')} + + {:else if id === 'joined'} + {toLocaleDateTime(user.registration)} + {:else if id === 'lastActivity'} + {user.accessedAt ? toLocaleDate(user.accessedAt) : 'never'} + {:else} + {user[id]} + {/if} +
+ {/each} +
+ {:else} + + {#each $columns as { id } (id)} + + {#if id === '$id'} + + + + {user.$id} + + + {:else if id === 'name'} + + {#if user.email || user.phone} + {#if user.name} + + + {user.name} + + {:else} +
+ +
+ {/if} + {:else} +
+ +
+ + {user.name} + + {/if} +
+ {:else if id === 'identifiers'} + + {user.email && user.phone + ? [user.email, user.phone].join(',') + : user.email || user.phone} + + {:else if id === 'status'} + {#if user.status} + {@const success = user.emailVerification || user.phoneVerification} + + {:else} + + {/if} + {:else if id === 'labels'} + + {user.labels.join(', ')} + + {:else if id === 'joined'} + {toLocaleDateTime(user.registration)} + {:else if id === 'lastActivity'} + {user.accessedAt ? toLocaleDate(user.accessedAt) : 'never'} + {:else} + {user[id]} + {/if} +
+ {/each} +
+ {/if} + {/each} +
+ + + {:else if search} + + + + {:else} + (showCreateUser = true)} /> + {/if} +
+ + diff --git a/src/routes/(console)/project-[region]-[project]/databases/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/+page.svelte index a8ab5335a..ee0c6729f 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/+page.svelte @@ -1,97 +1,18 @@ - - - - - - - - {#if $canWriteDatabases} - - {/if} - - - - {#if data.databases.total} - {#if data.view === 'grid'} - - {:else} - - {/if} - - - {:else if data.search} - - - - {:else} - (showCreate = true)} /> - {/if} - - - + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/+page.svelte index be123b600..745a4134a 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/+page.svelte @@ -1,94 +1,6 @@ - - - - - - - - - - {#if $canWriteTables} - - {/if} - - - - {#if data.tables.total} - {#if data.view === 'grid'} - - {:else} -
- {/if} - - - {:else if data.search} - - - - {:else} - - - - Create, organize, and query structured data with Tables. - - - - - {#if $canWriteTables} - - {/if} - - - - {/if} - + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/view.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/view.svelte new file mode 100644 index 000000000..312c467be --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/view.svelte @@ -0,0 +1,95 @@ + + + + + + + + + + + + {#if $canWriteTables} + + {/if} + + + + {#if tables.total} + {#if view === 'grid'} + ($showCreate = true)}> + {#each tables.tables as table} + + {table.name} + {table.$id} + + {/each} + + {:else} + + + {#each $tableViewColumns as { id, title }} + {title} + {/each} + + {#each tables.tables as table (table.$id)} + + {#each $tableViewColumns as column} + + {#if column.id === '$id'} + {#key $tableViewColumns} + {table.$id} + {/key} + {:else if column.id === 'name'} + {table.name} + {:else} + {table[column.id]} + {/if} + + {/each} + + {/each} + + {/if} + + + {:else if search} + + + + {:else} + + + Create, organize, and query structured data with Tables. + + + {#if $canWriteTables} + + {/if} + + + + {/if} + diff --git a/src/routes/(console)/project-[region]-[project]/databases/view.svelte b/src/routes/(console)/project-[region]-[project]/databases/view.svelte new file mode 100644 index 000000000..e516dcdf8 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/view.svelte @@ -0,0 +1,143 @@ + + + + + + + + + {#if $canWriteDatabases} + + {/if} + + + +{#if databases.total} + {#if view === 'grid'} + (showCreate = true)}> + {#each databases.databases as database} + {@const href = getDatabaseUrl(database, tables?.[database.$id] ?? null)} + + {database.name} + + {#if lastBackups && lastBackups[database.$id]} + Last backup: {lastBackups[database.$id]} + {:else if !policies || !policies[database.$id]} + No backup policies + {:else} + Last backup: No backups yet + {/if} + + {database.$id} + + {/each} +

Create a database

+
+ {:else} + + + {#each $columns as { id, title }} + {title} + {/each} + + {#each databases.databases as database (database.$id)} + {@const tableId = tables?.[database.$id] ?? null} + {@const href = getDatabaseUrl(database, tableId)} + + {#each $columns as column} + + {#if column.id === '$id'} + {#key $columns} + {database.$id} + {/key} + {:else if column.id === 'name'} + {database.name} + {:else if column.id === 'backup'} + {@const p = policies?.[database.$id] ?? null} + {@const last = lastBackups?.[database.$id] ?? null} + {@const description = p?.map((policy) => getPolicyDescription(policy.schedule)).join(', ')} + + + {#if !p} + + + No backup policies + + {:else} + {description} + {/if} + + Last backup: {last} + + {:else} + {toLocaleDateTime(database[column.id])} + {/if} + + {/each} + + {/each} + + {/if} + + +{:else if search} + + + +{:else} + +{/if} + + + + + diff --git a/src/routes/(console)/project-[region]-[project]/messaging/+page.svelte b/src/routes/(console)/project-[region]-[project]/messaging/+page.svelte index 1931f56ff..d63d15418 100644 --- a/src/routes/(console)/project-[region]-[project]/messaging/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/messaging/+page.svelte @@ -1,244 +1,6 @@ - - - {#if $canWriteMessages} - - {/if} - - - {#if data.messages.total} - - - {#each $columns as { id, title }} - {title} - {/each} - - {#each data.messages.messages as message (message.$id)} - - {#each $columns as column (column.id)} - - {#if column.id === '$id'} - {#key $columns} - {message.$id} - {/key} - {:else if column.id === 'message'} - {#if message.providerType === MessagingProviderType.Push} - {message.data.title} - {:else if message.providerType === MessagingProviderType.Sms} - {message.data.content} - {:else if message.providerType === MessagingProviderType.Email} - {message.data.subject} - {:else} - Invalid provider - {/if} - {:else if column.id === 'providerType'} - - {:else if column.id === 'status'} - - - {#if message.status === 'failed'} - { - e.preventDefault(); - errors = message.deliveryErrors; - showFailed = true; - }}>Details - {/if} - - {:else if column.type === 'datetime'} - {#if !message[column.id]} - - - {:else} - {toLocaleDateTime(message[column.id])} - {/if} - {:else} - {message[column.id]} - {/if} - - {/each} - - {/each} - - - {#if selected.length > 0} - - - - - {selected.length > 1 ? 'messages' : 'message'} - selected - - - - - - - - {/if} - - - {:else if $hasPageQueries} - - {:else if data.search} - -
- Sorry, we couldn't find '{data.search}' -

There are no messages that match your search.

-
-
- - -
-
- {:else} - ($showCreate = true)}> - - - {#if $canWriteMessages} - - - - {/if} - - - {/if} -
- - - - - - Are you sure you want to delete {selected.length} - {selected.length > 1 ? 'messages' : 'message'}? - - + diff --git a/src/routes/(console)/project-[region]-[project]/messaging/view.svelte b/src/routes/(console)/project-[region]-[project]/messaging/view.svelte new file mode 100644 index 000000000..61ee79894 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/messaging/view.svelte @@ -0,0 +1,179 @@ + + + + + {#if $canWriteMessages} + + {/if} + + + {#if messages.total} + + + {#each $columns as { id, title }} + {title} + {/each} + + {#each messages.messages as message (message.$id)} + + {#each $columns as column (column.id)} + + {#if column.id === '$id'} + {#key $columns}{message.$id}{/key} + {:else if column.id === 'message'} + {#if message.providerType === MessagingProviderType.Push} + {message.data.title} + {:else if message.providerType === MessagingProviderType.Sms} + {message.data.content} + {:else if message.providerType === MessagingProviderType.Email} + {message.data.subject} + {:else}Invalid provider{/if} + {:else if column.id === 'providerType'} + + {:else if column.id === 'status'} + + + {#if message.status === 'failed'} + { e.preventDefault(); errors = message.deliveryErrors; showFailed = true; }}>Details + {/if} + + {:else if column.type === 'datetime'} + {#if !message[column.id]}-{:else}{toLocaleDateTime(message[column.id])}{/if} + {:else} + {message[column.id]} + {/if} + + {/each} + + {/each} + + + {#if selected.length > 0} + + + + {selected.length > 1 ? 'messages' : 'message'} selected + + + + + + + {/if} + + + {:else if $hasPageQueries} + + {:else if search} + +
+ Sorry, we couldn't find '{search}' +

There are no messages that match your search.

+
+
+ + +
+
+ {:else} + ($showCreate = true)}> + + + {#if $canWriteMessages} + + + + {/if} + + + {/if} +
+ + + + Are you sure you want to delete {selected.length} {selected.length > 1 ? 'messages' : 'message'}? + diff --git a/src/routes/(console)/project-[region]-[project]/storage/+page.svelte b/src/routes/(console)/project-[region]-[project]/storage/+page.svelte index 7bbac81ce..18ee8115e 100644 --- a/src/routes/(console)/project-[region]-[project]/storage/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/storage/+page.svelte @@ -3,73 +3,15 @@ - - - - - - - - {#if $canWriteBuckets} - - {/if} - - - {#if data.buckets.total} - {#if data.view === 'grid'} - - {:else} -
- {/if} - - - {:else} - showCreateBucket.set(true)} /> - {/if} - - - + diff --git a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/+page.svelte b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/+page.svelte index 5aa634cf5..fc096f174 100644 --- a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/+page.svelte @@ -1,249 +1,6 @@ - - - - - - - - - - - - - {#if data.files.total} - - - Filename - Type - Size - Created - - - {#each data.files.files as file} - {#if file.chunksTotal / file.chunksUploaded !== 1} - - - - - {file.name} -
- -
-
-
- {file.mimeType} - - {calculateSize(file.sizeOriginal)} - - - - - -
- -
-
-
- {:else} - {@const href = `${base}/project-${page.params.region}-${page.params.project}/storage/bucket-${bucketId}/file-${file.$id}`} - - -
- - {file.name} -
-
- {file.mimeType} - - {calculateSize(file.sizeOriginal)} - - - - - - - - - - Update - - { - e.stopPropagation(); - e.preventDefault(); - selectedFile = file; - showDelete = true; - }}> - Delete - - - - -
- {/if} - {/each} -
- - - {:else if data.search} - -
- Sorry, we couldn't find '{data.search}' -

There are no files that match your search.

-
-
- - -
-
- {:else} - - goto( - `${base}/project-${page.params.region}-${page.params.project}/storage/bucket-${page.params.bucket}/create` - )} /> - {/if} -
- -{#if selectedFile} - -{/if} + diff --git a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/view.svelte b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/view.svelte new file mode 100644 index 000000000..8ad36bcf3 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/view.svelte @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + {#if files.total} + + + Filename + Type + Size + Created + + + {#each files.files as file (file.$id)} + {#if $uploader.files.find(({ $id }) => $id === file.$id)} + + + + + {file.name} +
+
+
+ {file.mimeType} + {calculateSize(file.sizeOriginal)} + + +
+ +
+
+
+ {:else} + {@const href = `${base}/project-${page.params.region}-${page.params.project}/storage/bucket-${bucketId}/file-${file.$id}`} + + +
+ + {file.name} +
+
+ {file.mimeType} + {calculateSize(file.sizeOriginal)} + + + + + + Update + { e.stopPropagation(); e.preventDefault(); selectedFile = file; showDelete = true; }}>Delete + + + +
+ {/if} + {/each} +
+ + + {:else if search} + +
+ Sorry, we couldn't find '{search}' +

There are no files that match your search.

+
+
+ + +
+
+ {:else} + goto(`${base}/project-${page.params.region}-${page.params.project}/storage/bucket-${page.params.bucket}/create`)} /> + {/if} +
+ +{#if selectedFile} + +{/if} diff --git a/src/routes/(console)/project-[region]-[project]/storage/view.svelte b/src/routes/(console)/project-[region]-[project]/storage/view.svelte new file mode 100644 index 000000000..624ccbd1f --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/storage/view.svelte @@ -0,0 +1,104 @@ + + + + + + + + + {#if $canWriteBuckets} + + {/if} + + + +{#if buckets.total} + {#if view === 'grid'} + ($showCreateBucket = true)}> + {#each buckets.buckets as bucket} + + {bucket.name} + + {#if !bucket.enabled} +
+ +
+ {/if} +
+ {bucket.$id} + + + + {bucket.encryption ? 'Encryption enabled' : 'Encryption disabled'} + + +
+ {/each} +

Create a bucket

+
+ {:else} + + + {#each $columns as { id, title }} + {title} + {/each} + + {#each buckets.buckets as bucket (bucket.$id)} + + {#each $columns as column} + + {#if column.id === '$id'} + {#key $columns} + {bucket.$id} + {/key} + {:else if column.id === 'name'} + {bucket.name} + {:else} + {toLocaleDateTime(bucket[column.id])} + {/if} + + {/each} + + {/each} + + {/if} + + +{:else} + showCreateBucket.set(true)} /> +{/if} + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+layout.ts b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+layout.ts new file mode 100644 index 000000000..c90dc732a --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+layout.ts @@ -0,0 +1,9 @@ +import type { LayoutLoad } from './$types'; +import { sdk } from '$lib/stores/sdk'; + +export const load: LayoutLoad = async ({ params }) => { + // Minimal layout data for embeds; no UI wrapping. + const project = await sdk.forConsole.projects.get(params.project); + return { project } as const; +}; + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.svelte new file mode 100644 index 000000000..78d82e29a --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.ts b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.ts new file mode 100644 index 000000000..f9439ed26 --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/+page.ts @@ -0,0 +1,26 @@ +import { Query } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load'; +import { PAGE_LIMIT } from '$lib/constants'; +import type { PageLoad } from './$types'; + +export const load: PageLoad = async ({ url, route, params }) => { + const page = getPage(url); + const search = getSearch(url); + const limit = getLimit(url, route, PAGE_LIMIT); + const offset = pageToOffset(page, limit); + + return { + offset, + limit, + search, + page, + users: await sdk.forProject(params.region, params.project).users.list([ + Query.limit(limit), + Query.offset(offset), + Query.orderDesc(''), + ...(search ? [Query.search('name', search)] : []) + ]) + }; +}; + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/security/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/security/+page.svelte new file mode 100644 index 000000000..f91c3911f --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/security/+page.svelte @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/settings/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/settings/+page.svelte new file mode 100644 index 000000000..867411ebb --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/settings/+page.svelte @@ -0,0 +1,5 @@ + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.svelte new file mode 100644 index 000000000..047104fec --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.ts b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.ts new file mode 100644 index 000000000..dcc050a24 --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/+page.ts @@ -0,0 +1,26 @@ +import { Query } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load'; +import { PAGE_LIMIT } from '$lib/constants'; +import type { PageLoad } from './$types'; + +export const load: PageLoad = async ({ url, route, params }) => { + const page = getPage(url); + const search = getSearch(url); + const limit = getLimit(url, route, PAGE_LIMIT); + const offset = pageToOffset(page, limit); + + return { + offset, + limit, + search, + page, + teams: await sdk.forProject(params.region, params.project).teams.list([ + Query.limit(limit), + Query.offset(offset), + Query.orderDesc(''), + ...(search ? [Query.search('name', search)] : []) + ]) + }; +}; + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/team-[team]/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/team-[team]/+page.svelte new file mode 100644 index 000000000..728182a59 --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/teams/team-[team]/+page.svelte @@ -0,0 +1,6 @@ + + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/templates/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/templates/+page.svelte new file mode 100644 index 000000000..cecdd7185 --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/templates/+page.svelte @@ -0,0 +1,6 @@ + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.svelte new file mode 100644 index 000000000..4ad4a392a --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.svelte @@ -0,0 +1,5 @@ + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.ts b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.ts new file mode 100644 index 000000000..a5c106b0b --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/auth/user-[user]/+page.ts @@ -0,0 +1,12 @@ +import type { PageLoad } from './$types'; +import { sdk } from '$lib/stores/sdk'; + +export const load: PageLoad = async ({ params }) => { + const [user, userFactors] = await Promise.all([ + sdk.forProject(params.region, params.project).users.get(params.user), + sdk.forProject(params.region, params.project).users.listMfaFactors(params.user) + ]); + + return { user, userFactors }; +}; + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.svelte b/src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.svelte new file mode 100644 index 000000000..4c296debd --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.ts b/src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.ts new file mode 100644 index 000000000..480068e8b --- /dev/null +++ b/src/routes/(embeddings)/embed/project-[region]-[project]/messaging/+page.ts @@ -0,0 +1,30 @@ +import { queries, queryParamToMap } from '$lib/components/filters'; +import { CARD_LIMIT, Dependencies } from '$lib/constants'; +import { View, getLimit, getPage, getQuery, getSearch, getView, pageToOffset } from '$lib/helpers/load'; +import { sdk } from '$lib/stores/sdk'; +import { Query, type Models } from '@appwrite.io/console'; +import type { PageLoad } from './$types'; + +export const load: PageLoad = async ({ depends, url, route, params }) => { + depends(Dependencies.MESSAGING_MESSAGES); + + const page = getPage(url); + const search = getSearch(url); + const view = getView(url, route, View.Grid); + const limit = getLimit(url, route, CARD_LIMIT); + const offset = pageToOffset(page, limit); + const query = getQuery(url); + + const parsedQueries = queryParamToMap(query || '[]'); + queries.set(parsedQueries); + + const messages = (await sdk.forProject(params.region, params.project).messaging.listMessages({ + queries: [Query.limit(limit), Query.offset(offset), Query.orderDesc(''), ...parsedQueries.values()], + search: search || undefined + })) as { + total: number; + messages: (Models.Message & { data: Record })[]; + }; + + return { offset, limit, search, query, page, view, messages } as const; +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index f5bed4b86..797ed4d38 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -14,16 +14,24 @@ import { user } from '$lib/stores/user'; import { loading } from '$routes/store'; import { Root } from '@appwrite.io/pink-svelte'; - import { ThemeDark, ThemeLight, ThemeDarkCloud, ThemeLightCloud } from '../themes'; + import { + ThemeDark, + ThemeLight, + ThemeDarkCloud, + ThemeLightCloud, + ThemeDarkStudio, + ThemeLightStudio + } from '../themes'; import { isSmallViewport, updateViewport } from '$lib/stores/viewport'; import { feedback } from '$lib/stores/feedback'; function resolveTheme(theme: AppStore['themeInUse']) { + const isEmbedded = page.route.id.includes('/(embeddings)/'); switch (theme) { case 'dark': - return isCloud ? ThemeDarkCloud : ThemeDark; + return isEmbedded ? ThemeDarkStudio : isCloud ? ThemeDarkCloud : ThemeDark; case 'light': - return isCloud ? ThemeLightCloud : ThemeLight; + return isEmbedded ? ThemeLightStudio : isCloud ? ThemeLightCloud : ThemeLight; } } diff --git a/src/themes/dark-studio.json b/src/themes/dark-studio.json new file mode 100644 index 000000000..ae71bdb51 --- /dev/null +++ b/src/themes/dark-studio.json @@ -0,0 +1,6 @@ +{ + "bgcolor-accent": "var(--neutral-50)", + "bgcolor-accent-secondary": "var(--neutral-100)", + "bgcolor-accent-tertiary": "var(--neutral-150)", + "fgcolor-on-accent": "var(--neutral-950)" +} diff --git a/src/themes/index.ts b/src/themes/index.ts index 2b2344244..164928357 100644 --- a/src/themes/index.ts +++ b/src/themes/index.ts @@ -1,5 +1,10 @@ -export { default as ThemeDark } from './dark.json'; -export { default as ThemeLight } from './light.json'; +import ThemeDark from './dark.json'; +import ThemeLight from './light.json'; +import ThemeDarkCloud from './dark-cloud.json'; +import ThemeLightCloud from './light-cloud.json'; +import darkStudio from './dark-studio.json'; +import lightStudio from './light-studio.json'; -export { default as ThemeDarkCloud } from './dark-cloud.json'; -export { default as ThemeLightCloud } from './light-cloud.json'; +export const ThemeDarkStudio = { ...ThemeDarkCloud, ...darkStudio }; +export const ThemeLightStudio = { ...ThemeLightCloud, ...lightStudio }; +export { ThemeDark, ThemeLight, ThemeDarkCloud, ThemeLightCloud }; diff --git a/src/themes/light-studio.json b/src/themes/light-studio.json new file mode 100644 index 000000000..a3fb4240b --- /dev/null +++ b/src/themes/light-studio.json @@ -0,0 +1,5 @@ +{ + "bgcolor-accent": "var(--neutral-1000)", + "bgcolor-accent-secondary": "var(--neutral-900)", + "bgcolor-accent-tertiary": "var(--neutral-850)" +} \ No newline at end of file