Skip to content

Commit 86048c1

Browse files
authored
Merge branch 'main' into feat-add-pagination-archive-project-sectiin
2 parents cc9a62c + 5b98696 commit 86048c1

76 files changed

Lines changed: 840 additions & 416 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"@appwrite.io/pink-icons": "0.25.0",
2727
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0",
2828
"@appwrite.io/pink-legacy": "^1.0.3",
29-
"@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@40fb564",
29+
"@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed",
3030
"@faker-js/faker": "^9.9.0",
3131
"@popperjs/core": "^2.11.8",
3232
"@sentry/sveltekit": "^8.38.0",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/components/archiveProject.svelte

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script lang="ts">
2-
import { Button } from '$lib/elements/forms';
3-
import { DropList, GridItem1, CardContainer } from '$lib/components';
42
import ArchivedPaginationWithLimit from './archivedPaginationWithLimit.svelte';
3+
import { Button, InputText } from '$lib/elements/forms';
4+
import { DropList, GridItem1, CardContainer, Modal } from '$lib/components';
5+
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
56
import {
67
Badge,
78
Icon,
@@ -10,7 +11,8 @@
1011
Accordion,
1112
ActionMenu,
1213
Popover,
13-
Layout
14+
Layout,
15+
Divider
1416
} from '@appwrite.io/pink-svelte';
1517
import {
1618
IconAndroid,
@@ -22,7 +24,8 @@
2224
IconInfo,
2325
IconDotsHorizontal,
2426
IconInboxIn,
25-
IconSwitchHorizontal
27+
IconSwitchHorizontal,
28+
IconTrash
2629
} from '@appwrite.io/pink-icons-svelte';
2730
import { getPlatformInfo } from '$lib/helpers/platform';
2831
import { Status, type Models } from '@appwrite.io/console';
@@ -34,7 +37,7 @@
3437
import { addNotification } from '$lib/stores/notifications';
3538
import { invalidate } from '$app/navigation';
3639
import { Dependencies } from '$lib/constants';
37-
import { Modal } from '$lib/components';
40+
3841
import { isSmallViewport } from '$lib/stores/viewport';
3942
import { isCloud } from '$lib/system';
4043
import { regions as regionsStore } from '$lib/stores/organization';
@@ -64,6 +67,17 @@
6467
let readOnlyInfoOpen = $state<Record<string, boolean>>({});
6568
let showUnarchiveModal = $state(false);
6669
let projectToUnarchive = $state<Models.Project | null>(null);
70+
let showDeleteModal = $state(false);
71+
let projectToDelete = $state<Models.Project | null>(null);
72+
let deleteProjectName = $state<string | null>(null);
73+
let deleteError = $state<string | null>(null);
74+
75+
function resetDeleteState() {
76+
showDeleteModal = false;
77+
projectToDelete = null;
78+
deleteProjectName = null;
79+
deleteError = null;
80+
}
6781
6882
function filterPlatforms(platforms: { name: string; icon: string }[]) {
6983
return platforms.filter(
@@ -114,6 +128,12 @@
114128
showUnarchiveModal = true;
115129
}
116130
131+
function handleDeleteProject(project: Models.Project) {
132+
projectToDelete = project;
133+
deleteProjectName = null;
134+
showDeleteModal = true;
135+
}
136+
117137
// Confirm unarchive action
118138
async function confirmUnarchive() {
119139
if (!projectToUnarchive) return;
@@ -152,6 +172,29 @@
152172
projectToUnarchive = null;
153173
}
154174
175+
async function confirmDelete() {
176+
if (!projectToDelete) return;
177+
178+
try {
179+
await sdk.forConsoleIn(projectToDelete.region).projects.delete({
180+
projectId: projectToDelete.$id
181+
});
182+
183+
await invalidate(Dependencies.ORGANIZATION);
184+
185+
trackEvent(Submit.ProjectDelete);
186+
addNotification({
187+
type: 'success',
188+
message: `${projectToDelete.name} has been deleted`
189+
});
190+
191+
resetDeleteState();
192+
} catch (error) {
193+
deleteError = error.message;
194+
trackError(error, Submit.ProjectDelete);
195+
}
196+
}
197+
155198
function findRegion(project: Models.Project) {
156199
return $regionsStore.regions.find((region) => region.$id === project.region);
157200
}
@@ -237,6 +280,14 @@
237280
leadingIcon={IconSwitchHorizontal}
238281
on:click={() => handleMigrateProject(project)}
239282
>Migrate project</ActionMenu.Item.Button>
283+
<div class="action-menu-divider">
284+
<Divider />
285+
</div>
286+
<ActionMenu.Item.Button
287+
status="danger"
288+
leadingIcon={IconTrash}
289+
on:click={() => handleDeleteProject(project)}
290+
>Delete project</ActionMenu.Item.Button>
240291
</ActionMenu.Root>
241292
</Popover>
242293
</div>
@@ -294,10 +345,51 @@
294345
</svelte:fragment>
295346
</Modal>
296347

348+
<!-- Delete Confirmation Modal -->
349+
<Modal
350+
size="s"
351+
bind:show={showDeleteModal}
352+
title="Delete project"
353+
onSubmit={confirmDelete}
354+
bind:error={deleteError}>
355+
<svelte:fragment slot="description">
356+
The archived project <strong>{projectToDelete?.name}</strong> will be deleted along with all
357+
of its metadata, stats, and other resources.
358+
<b>This action is irreversible.</b>
359+
</svelte:fragment>
360+
361+
<InputText
362+
label={`Enter "${projectToDelete?.name}" to continue`}
363+
placeholder="Enter name"
364+
id="delete-project-name"
365+
autofocus
366+
required
367+
bind:value={deleteProjectName} />
368+
369+
<svelte:fragment slot="footer">
370+
<Button
371+
text
372+
on:click={() => {
373+
resetDeleteState();
374+
}}>Cancel</Button>
375+
<Button
376+
submissionLoader
377+
submit
378+
disabled={(deleteProjectName ?? '') !== projectToDelete?.name}>
379+
Delete
380+
</Button>
381+
</svelte:fragment>
382+
</Modal>
383+
297384
<style>
298385
.archive-projects-margin-top {
299386
margin-top: 36px;
300387
}
388+
.action-menu-divider {
389+
margin-inline: -1rem;
390+
padding-block-start: 0.25rem;
391+
padding-block-end: 0.25rem;
392+
}
301393
302394
.archive-projects-margin {
303395
margin-top: 16px;

src/lib/components/breadcrumbs.svelte

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
import { isCloud } from '$lib/system';
2121
import { goto } from '$app/navigation';
2222
import { base } from '$app/paths';
23-
import { currentPlan, newOrgModal } from '$lib/stores/organization';
23+
import { currentPlan, newOrgModal, organization } from '$lib/stores/organization';
2424
import { Click, trackEvent } from '$lib/actions/analytics';
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,10 @@
226227
$: if (shouldReloadProjects) {
227228
projectsBottomSheet = createProjectsBottomSheet(selectedOrg);
228229
}
230+
231+
let badgeType: 'success' | undefined;
232+
$: badgeType =
233+
$organization && $organization.billingPlan !== BillingPlan.FREE ? 'success' : undefined;
229234
</script>
230235

231236
<svelte:window on:resize={onResize} />
@@ -240,10 +245,13 @@
240245
use:melt={$triggerOrganizations}
241246
aria-label="Open organizations tab">
242247
<span class="orgName">{selectedOrg?.name ?? 'Organization'}</span>
243-
<span class="not-mobile"
248+
<span class="not-mobile" style="padding-inline-start: 2px"
244249
>{#if correctPlanName}<Badge
250+
size="xs"
245251
variant="secondary"
246-
content={correctPlanName} />{/if}</span>
252+
type={badgeType}
253+
content={correctPlanName} />
254+
{/if}</span>
247255
<Icon icon={IconChevronDown} size="s" color="--fgcolor-neutral-secondary" />
248256
</button>
249257
{:else}
@@ -257,7 +265,11 @@
257265
<span class="orgName" class:noProjects={!currentProject}
258266
>{selectedOrg?.name ?? 'Organization'}</span>
259267
<span class="not-mobile"
260-
><Badge variant="secondary" content={correctPlanName ?? ''} /></span>
268+
><Badge
269+
size="xs"
270+
variant="secondary"
271+
type={badgeType}
272+
content={correctPlanName ?? ''} /></span>
261273
<Icon icon={IconChevronDown} size="s" color="--fgcolor-neutral-secondary" />
262274
</button>
263275
{/if}
@@ -476,6 +488,7 @@
476488
border-radius: var(--border-radius-S, 8px);
477489
background: var(--overlay-neutral-hover, rgba(25, 25, 28, 0.03));
478490
}
491+
479492
.trigger {
480493
display: inline-flex;
481494
align-items: center;

src/lib/components/domains/nameserverTable.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
{/if}
2424
</Layout.Stack>
2525
<Typography.Text variant="m-400">
26-
Add the following nameservers on your DNS provider. Note that DNS changes may take time to
27-
propagate fully.
26+
Add the following nameservers on your DNS provider. Note that changes may take up to 48
27+
hours to propagate fully.
2828
</Typography.Text>
2929
</Layout.Stack>
3030

src/lib/components/dropList.svelte

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
export let wrapperFullWidth = false;
1515
export let position: 'relative' | 'static' = 'relative';
1616
export let noMaxWidthList = false;
17+
export let paddingBlock: string = undefined;
18+
export let paddingInline: string = undefined;
19+
export let resetListPadding: boolean = false;
20+
export let gap: string = undefined;
1721
let classes: string = '';
1822
export { classes as class };
1923
</script>
@@ -34,14 +38,20 @@
3438
class="drop is-no-arrow {classes}"
3539
class:u-max-width-100-percent={fullWidth}
3640
style:--drop-width-size-desktop={width ? `${width}rem` : ''}
41+
style:margin-block-start={gap}
3742
style:position>
3843
{#if $$slots.list}
3944
<section
4045
class:u-overflow-y-auto={scrollable}
4146
class:u-max-height-200={scrollable}
4247
class="drop-section"
43-
style={noMaxWidthList ? 'max-inline-size: 100%' : ''}>
44-
<ul class="drop-list">
48+
style={noMaxWidthList ? 'max-inline-size: 100%' : ''}
49+
style:padding-block={paddingBlock}
50+
style:padding-inline={paddingInline}>
51+
<ul
52+
class="drop-list"
53+
style:padding={resetListPadding ? '0' : undefined}
54+
style:margin={resetListPadding ? '0' : undefined}>
4555
<slot name="list" />
4656
</ul>
4757
</section>

src/lib/components/filters/store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function initQueries(initialValue = new Map<TagValue, string>()) {
6363
const currentLocation = window.location.pathname;
6464

6565
if (usableQueries.size) {
66-
const queryParam = mapToQueryParams(get(queries));
66+
const queryParam = mapToQueryParams(usableQueries);
6767
goto(`${currentLocation}?query=${queryParam}`, { noScroll: true });
6868
} else {
6969
goto(currentLocation, { noScroll: true });

src/lib/components/limit.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
const url = new URL(pageStore.url);
2222
const previousLimit = Number(url.searchParams.get('limit'));
2323
url.searchParams.set('limit', limit.toString());
24-
preferences.setLimit(limit);
24+
await preferences.setLimit(limit);
2525
2626
if (url.searchParams.has('page')) {
2727
const page = Number(url.searchParams.get('page'));

src/lib/components/paginationInline.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
{:else}
6767
<Layout.Stack direction="row" inline>
6868
<Button.Button
69+
type="button"
6970
size="s"
7071
variant="compact"
7172
on:click={prev}
@@ -75,6 +76,7 @@
7576
</Button.Button>
7677

7778
<Button.Button
79+
type="button"
7880
size="s"
7981
variant="compact"
8082
on:click={next}

src/lib/components/sidebar.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,6 @@
250250
</Tooltip>
251251
{/each}
252252
{#if project && $isSmallViewport}
253-
<Divider />
254-
255253
<div class="mobile-tablet-settings">
256254
<Tooltip placement="right" disabled={state !== 'icons'}>
257255
<a
@@ -593,6 +591,7 @@
593591
@media (min-width: 1024px) {
594592
width: 166px;
595593
}
594+
596595
.info {
597596
position: absolute;
598597
display: flex;

0 commit comments

Comments
 (0)