Skip to content

Commit 01e11f5

Browse files
authored
Merge pull request #2326 from appwrite/table-actions-on-subnav
2 parents 7745037 + fb03419 commit 01e11f5

7 files changed

Lines changed: 123 additions & 27 deletions

File tree

src/lib/components/breadcrumbs.svelte

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import { type Models, Query } from '@appwrite.io/console';
2626
import { sdk } from '$lib/stores/sdk';
2727
import { page } from '$app/state';
28+
import { BillingPlan } from '$lib/constants';
2829
2930
type Organization = {
3031
name: string;
@@ -226,6 +227,9 @@
226227
$: if (shouldReloadProjects) {
227228
projectsBottomSheet = createProjectsBottomSheet(selectedOrg);
228229
}
230+
231+
let badgeType: 'success' | undefined;
232+
$: badgeType = $currentPlan && $currentPlan.name !== BillingPlan.FREE ? 'success' : undefined;
229233
</script>
230234

231235
<svelte:window on:resize={onResize} />
@@ -240,10 +244,13 @@
240244
use:melt={$triggerOrganizations}
241245
aria-label="Open organizations tab">
242246
<span class="orgName">{selectedOrg?.name ?? 'Organization'}</span>
243-
<span class="not-mobile"
247+
<span class="not-mobile" style="padding-inline-start: 2px"
244248
>{#if correctPlanName}<Badge
249+
size="xs"
245250
variant="secondary"
246-
content={correctPlanName} />{/if}</span>
251+
type={badgeType}
252+
content={correctPlanName} />
253+
{/if}</span>
247254
<Icon icon={IconChevronDown} size="s" color="--fgcolor-neutral-secondary" />
248255
</button>
249256
{:else}
@@ -257,7 +264,11 @@
257264
<span class="orgName" class:noProjects={!currentProject}
258265
>{selectedOrg?.name ?? 'Organization'}</span>
259266
<span class="not-mobile"
260-
><Badge variant="secondary" content={correctPlanName ?? ''} /></span>
267+
><Badge
268+
size="xs"
269+
variant="secondary"
270+
type={badgeType}
271+
content={correctPlanName ?? ''} /></span>
261272
<Icon icon={IconChevronDown} size="s" color="--fgcolor-neutral-secondary" />
262273
</button>
263274
{/if}
@@ -476,6 +487,7 @@
476487
border-radius: var(--border-radius-S, 8px);
477488
background: var(--overlay-neutral-hover, rgba(25, 25, 28, 0.03));
478489
}
490+
479491
.trigger {
480492
display: inline-flex;
481493
align-items: center;

src/lib/components/sidebar.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@
591591
@media (min-width: 1024px) {
592592
width: 166px;
593593
}
594+
594595
.info {
595596
position: absolute;
596597
display: flex;

src/lib/layout/animatedTitle.svelte

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,32 @@
33
import { IconChevronLeft } from '@appwrite.io/pink-icons-svelte';
44
import { Button, Icon, Layout } from '@appwrite.io/pink-svelte';
55
import type { Snippet } from 'svelte';
6+
import type { HTMLAttributes } from 'svelte/elements';
67
78
let {
89
href = null,
910
collapsed = false,
10-
children
11+
children,
12+
...restProps
1113
}: {
1214
href?: string | null;
1315
collapsed?: boolean;
1416
children: Snippet;
15-
} = $props();
17+
} & HTMLAttributes<HTMLDivElement> = $props();
1618
1719
const buttonSize = $derived(collapsed ? 'xs' : 's');
1820
const currentLineHeight = $derived(collapsed ? '130%' : '140%');
1921
const currentLetterSpacing = $derived(collapsed ? '0' : '-0.144px');
20-
const currentFontSize = $derived(collapsed ? 'var(--font-size-l)' : 'var(--font-size-xxxl)');
22+
const currentFontSize = $derived(collapsed ? 'var(--font-size-l)' : 'var(--font-size-xxl)');
2123
</script>
2224

23-
<Layout.Stack justifyContent="center" alignItems="center" direction="row" gap="xs" inline>
25+
<Layout.Stack
26+
inline
27+
gap="xs"
28+
direction="row"
29+
alignItems="center"
30+
justifyContent="center"
31+
{...restProps}>
2432
{#if href && !$isSmallViewport}
2533
<span style:position="relative">
2634
<Button.Anchor size={buttonSize} icon variant="text" {href} aria-label="page back">

src/lib/layout/coverTitle.svelte

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@
33
import { IconChevronLeft } from '@appwrite.io/pink-icons-svelte';
44
import { Typography, Button, Icon, Layout } from '@appwrite.io/pink-svelte';
55
6-
export let href: string = null;
6+
export let href: string | null = null;
77
</script>
88

9-
<Layout.Stack justifyContent="center" alignItems="center" direction="row" gap="xs" inline>
9+
<Layout.Stack
10+
inline
11+
gap="xs"
12+
direction="row"
13+
alignItems="center"
14+
justifyContent="center"
15+
{...$$restProps}>
1016
{#if href}
1117
<span style:position="relative">
1218
<Button.Anchor size="s" icon variant="text" {href} aria-label="page back">
1319
<Icon icon={IconChevronLeft} />
1420
</Button.Anchor>
1521
</span>
1622
{/if}
23+
1724
<Typography.Title
1825
truncate
1926
color="--fgcolor-neutral-primary"

src/routes/(console)/project-[region]-[project]/databases/database-[database]/header.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,12 @@
4040

4141
<Cover databasesMainScreen>
4242
<svelte:fragment slot="header">
43-
<CoverTitle href={`${base}/project-${page.params.region}-${projectId}/databases`}>
43+
<CoverTitle
44+
style="margin-inline-start: -2.5rem;"
45+
href={`${base}/project-${page.params.region}-${projectId}/databases`}>
4446
{$database.name}
4547
</CoverTitle>
48+
4649
<Id value={$database.$id}>{$database.$id}</Id>
4750
</svelte:fragment>
4851

src/routes/(console)/project-[region]-[project]/databases/database-[database]/store.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { page } from '$app/stores';
22
import type { Column } from '$lib/helpers/types';
33
import type { Models } from '@appwrite.io/console';
44
import { derived, writable } from 'svelte/store';
5+
import { IconChartBar, IconCloudUpload, IconCog } from '@appwrite.io/pink-icons-svelte';
56

67
export const database = derived(page, ($page) => $page.data.database as Models.Database);
78
export const showCreate = writable(false);
@@ -29,3 +30,9 @@ export const customRetainingOptions = [
2930
{ label: 'Weeks', value: 7, max: 4 },
3031
{ label: 'Months', value: 30, max: 12 }
3132
];
33+
34+
export const databaseSubNavigationItems = [
35+
{ title: 'Backups', href: 'backups', icon: IconCloudUpload },
36+
{ title: 'Usage', href: 'usage', icon: IconChartBar },
37+
{ title: 'Settings', href: 'settings', icon: IconCog }
38+
];

src/routes/(console)/project-[region]-[project]/databases/database-[database]/subNavigation.svelte

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
<script lang="ts">
22
import { base } from '$app/paths';
33
import { page } from '$app/state';
4-
import { showCreate } from './store';
4+
import { showCreate, databaseSubNavigationItems } from './store';
55
import type { PageData } from './$types';
66
import { showSubNavigation } from '$lib/stores/layout';
7-
import { Icon, Sidebar, Navbar, Layout, Link, Typography } from '@appwrite.io/pink-svelte';
7+
import {
8+
Icon,
9+
Sidebar,
10+
Navbar,
11+
Layout,
12+
Link,
13+
Typography,
14+
Divider
15+
} from '@appwrite.io/pink-svelte';
816
import {
917
IconChevronDown,
1018
IconDatabase,
@@ -41,6 +49,10 @@
4149
sortedTables?.find((table: Models.Table) => table.$id === tableId)
4250
);
4351
52+
const isTablesScreen = $derived(page.route.id.endsWith('table-[table]'));
53+
54+
const isMainDatabaseScreen = $derived(page.route.id.endsWith('database-[database]'));
55+
4456
async function loadTables() {
4557
tables = await sdk.forProject(region, project).tablesDB.listTables({
4658
databaseId: databaseId,
@@ -66,12 +78,14 @@
6678
<Sidebar.Base state="open" resizable={false}>
6779
<section class="list-container" slot="top" style:width="100%">
6880
<a
81+
class:is-selected={!isTablesScreen}
6982
href={`${base}/project-${region}-${project}/databases/database-${databaseId}`}
70-
class="database-name u-flex u-cross-center body-text-2 u-gap-8 is-not-mobile is-selected">
83+
class="database-name u-flex u-cross-center body-text-2 u-gap-8 is-not-mobile u-padding-block-8 u-padding-inline-start-4">
7184
<Icon icon={IconDatabase} size="s" color="--fgcolor-neutral-weak" />
85+
7286
{data.database?.name}
7387
</a>
74-
<div class="collection-content">
88+
<div class="table-content">
7589
{#if tables?.total}
7690
<ul class="drop-list u-margin-inline-start-8 u-margin-block-start-4">
7791
{#each sortedTables as table, index}
@@ -94,7 +108,7 @@
94108
color={isSelected
95109
? '--fgcolor-neutral-tertiary'
96110
: '--fgcolor-neutral-weak'} />
97-
<span class="text collection-name" data-private
111+
<span class="text table-name" data-private
98112
>{table.name}</span>
99113
</a>
100114
</li>
@@ -132,9 +146,37 @@
132146
</Button>
133147
</Layout.Stack>
134148
</div>
149+
150+
<Layout.Stack direction="column" gap="xxs" style="bottom: 1rem; position: sticky;">
151+
<div class="action-menu-divider">
152+
<Divider />
153+
</div>
154+
155+
<ul
156+
style="margin-inline-start: -1.25rem"
157+
class="drop-list bottom-nav u-margin-block-start-4">
158+
{#each databaseSubNavigationItems as action}
159+
{@const href = `${base}/project-${region}-${project}/databases/database-${databaseId}/${action.href}`}
160+
161+
<Layout.Stack gap="s" direction="row" alignItems="center">
162+
<li>
163+
<a
164+
{href}
165+
class="u-padding-block-8 u-padding-inline-end-4 u-padding-inline-start-8 u-flex u-cross-center u-gap-8">
166+
<Icon
167+
size="s"
168+
icon={action.icon}
169+
color="--fgcolor-neutral-weak" />
170+
<span class="text table-name">{action.title}</span>
171+
</a>
172+
</li>
173+
</Layout.Stack>
174+
{/each}
175+
</ul>
176+
</Layout.Stack>
135177
</section>
136178
</Sidebar.Base>
137-
{:else if data?.database?.name}
179+
{:else if data?.database?.name && !isMainDatabaseScreen}
138180
<Navbar.Base>
139181
<div slot="left">
140182
<Layout.Stack direction="row" alignItems="center" gap="s">
@@ -194,12 +236,18 @@
194236
}
195237
196238
.database-name {
197-
margin-block-end: 8px;
239+
margin-block-end: 4px;
198240
font-size: var(--font-size-sm);
199241
color: var(--fgcolor-neutral-secondary);
242+
243+
&:hover {
244+
color: var(--fgcolor-neutral-primary);
245+
border-radius: var(--border-radius-s, 6px);
246+
background: var(--bgcolor-neutral-secondary);
247+
}
200248
}
201249
202-
.collection-content {
250+
.table-content {
203251
flex: 1;
204252
overflow-y: auto;
205253
overflow-x: hidden;
@@ -232,13 +280,13 @@
232280
233281
.drop-list {
234282
flex: 1;
235-
gap: 8px;
283+
gap: 4px;
236284
padding-left: 4px;
237285
position: relative;
238286
font-size: var(--font-size-sm);
239287
color: var(--fgcolor-neutral-secondary);
240288
241-
&::before {
289+
&:not(.bottom-nav)::before {
242290
content: '';
243291
right: 99%;
244292
top: 0.2rem;
@@ -248,37 +296,36 @@
248296
}
249297
250298
// first item
251-
&:has(li.is-first)::before {
299+
&:not(.bottom-nav):has(li.is-first)::before {
252300
top: 0.8rem;
253301
}
254302
255303
// last item
256-
&:has(li.is-last)::before {
304+
&:not(.bottom-nav):has(li.is-last)::before {
257305
bottom: 0.85rem;
258306
}
259307
260308
// the only item
261-
&:has(li.is-first.is-last)::before {
309+
&:not(.bottom-nav):has(li.is-first.is-last)::before {
262310
top: 0.6rem;
263311
bottom: 0.6rem;
264312
}
265313
266314
li {
315+
width: 100%;
267316
overflow: hidden;
268317
position: relative;
269318
padding-inline-end: 0.5rem;
270319
margin-inline-start: 0.5rem;
271320
}
272321
273-
.is-selected,
274322
li:hover {
275-
width: 100%;
276323
color: var(--fgcolor-neutral-primary);
277-
border-radius: var(--border-radius-xs, 4px);
324+
border-radius: var(--border-radius-s, 6px);
278325
background: var(--bgcolor-neutral-secondary);
279326
}
280327
281-
.collection-name {
328+
.table-name {
282329
white-space: nowrap;
283330
overflow: hidden;
284331
text-overflow: ellipsis;
@@ -287,6 +334,12 @@
287334
}
288335
}
289336
337+
.is-selected {
338+
color: var(--fgcolor-neutral-primary);
339+
border-radius: var(--border-radius-s, 6px);
340+
background: var(--bgcolor-neutral-secondary);
341+
}
342+
290343
:global(.sub-navigation header) {
291344
top: 48px !important;
292345
}
@@ -310,4 +363,9 @@
310363
font-weight: 400;
311364
line-height: 150%; /* 21px */
312365
}
366+
367+
.action-menu-divider {
368+
margin-inline: -1.2rem;
369+
padding-block-end: 0.25rem;
370+
}
313371
</style>

0 commit comments

Comments
 (0)