Skip to content

Commit d783811

Browse files
authored
Merge pull request #2765 from appwrite/feat-project-labels
Feat. Project labels
2 parents 5939091 + 8ce5935 commit d783811

9 files changed

Lines changed: 131 additions & 24 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
"dependencies": {
2424
"@ai-sdk/svelte": "^1.1.24",
25-
"@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@f21fc7f",
25+
"@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@9c55755",
2626
"@appwrite.io/pink-icons": "0.25.0",
2727
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc",
2828
"@appwrite.io/pink-legacy": "^1.0.3",

pnpm-lock.yaml

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

src/lib/actions/analytics.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ export enum Submit {
247247
ProjectDelete = 'submit_project_delete',
248248
ProjectUpdateName = 'submit_project_update_name',
249249
ProjectUpdateTeam = 'submit_project_update_team',
250+
ProjectUpdateLabels = 'submit_project_update_labels',
250251
ProjectService = 'submit_project_service',
251252
ProjectUpdateSMTP = 'submit_project_update_smtp',
252253
MemberCreate = 'submit_member_create',

src/routes/(console)/+layout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const load: LayoutLoad = async ({ depends, parent }) => {
1818
sdk.forConsole.account.getPrefs(),
1919
isCloud ? sdk.forConsole.billing.getPlansInfo() : null,
2020
fetch(`${endpoint}/health/version`, {
21-
headers: { 'X-Appwrite-Project': project }
21+
headers: { 'X-Appwrite-Project': project as string }
2222
}).then((response) => response.json() as { version?: string }),
2323
sdk.forConsole.console.variables()
2424
]);

src/routes/(console)/organization-[organization]/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170

171171
<Container>
172172
<Layout.Stack direction="row" justifyContent="space-between" class="common-section">
173-
<SearchQuery bind:this={searchQuery} placeholder="Search by name or ID" />
173+
<SearchQuery bind:this={searchQuery} placeholder="Search by name, label, or ID" />
174174

175175
{#if $canWriteProjects}
176176
{#if projectCreationDisabled && reachedProjectLimit}

src/routes/(console)/organization-[organization]/+page.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ export const load: PageLoad = async ({ params, url, route, depends, parent }) =>
2424
const archivedPage =
2525
Number.isFinite(archivedPageRaw) && archivedPageRaw > 0 ? archivedPageRaw : 1;
2626
const archivedOffset = pageToOffset(archivedPage, limit);
27-
const common = [Query.equal('teamId', params.organization)];
28-
const active = isCloud
27+
28+
const searchQueries = search
29+
? [Query.or([Query.search('search', search), Query.contains('labels', search)])]
30+
: [];
31+
const commonQueries = [Query.equal('teamId', params.organization)];
32+
const activeQueries = isCloud
2933
? [Query.or([Query.equal('status', 'active'), Query.isNull('status')])]
3034
: [];
3135

@@ -35,31 +39,29 @@ export const load: PageLoad = async ({ params, url, route, depends, parent }) =>
3539
Query.offset(offset),
3640
Query.limit(limit),
3741
Query.orderDesc(''),
38-
...common,
39-
...active
40-
],
41-
search: search || undefined
42+
...commonQueries,
43+
...searchQueries,
44+
...activeQueries
45+
]
4246
}),
4347
isCloud
4448
? sdk.forConsole.projects.list({
4549
queries: [
4650
Query.offset(archivedOffset),
4751
Query.limit(limit),
4852
Query.orderDesc(''),
49-
...common,
53+
...commonQueries,
54+
...searchQueries,
5055
Query.equal('status', 'archived')
51-
],
52-
search: search || undefined
56+
]
5357
})
5458
: Promise.resolve({ projects: [], total: 0 }),
5559
sdk.forConsole.projects.list({
56-
queries: [...common, ...active],
57-
search: search || undefined
60+
queries: [...commonQueries, ...activeQueries, ...searchQueries]
5861
}),
5962
isCloud
6063
? sdk.forConsole.projects.list({
61-
queries: [...common, Query.equal('status', 'archived')],
62-
search: search || undefined
64+
queries: [...commonQueries, ...searchQueries, Query.equal('status', 'archived')]
6365
})
6466
: Promise.resolve({ projects: [], total: 0 })
6567
]);

src/routes/(console)/project-[region]-[project]/settings/+page.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import ChangeOrganization from './changeOrganization.svelte';
1616
import UpdateVariables from '../updateVariables.svelte';
1717
import { page } from '$app/state';
18+
import UpdateLabels from './updateLabels.svelte';
1819
1920
export let data;
2021
@@ -84,8 +85,9 @@
8485

8586
<Container>
8687
{#if $project}
87-
<UpdateName />
8888
{#if $canWriteProjects}
89+
<UpdateName />
90+
<UpdateLabels />
8991
<UpdateServices />
9092
<UpdateInstallations {...data.installations} limit={data.limit} offset={data.offset} />
9193
<UpdateVariables
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<script lang="ts">
2+
import { onMount } from 'svelte';
3+
import { invalidate } from '$app/navigation';
4+
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
5+
import { CardGrid } from '$lib/components';
6+
import { Dependencies } from '$lib/constants';
7+
import { Button, Form, InputTags } from '$lib/elements/forms';
8+
import { symmetricDifference } from '$lib/helpers/array';
9+
import { addNotification } from '$lib/stores/notifications';
10+
import { sdk } from '$lib/stores/sdk';
11+
import { project } from '../store';
12+
import { Tag, Input, Layout, Icon } from '@appwrite.io/pink-svelte';
13+
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
14+
15+
const alphaNumericRegExp = /^[a-zA-Z0-9]+$/;
16+
let suggestedLabels = ['live', 'stage', 'internal'];
17+
let labels: string[] = [];
18+
let error = '';
19+
20+
onMount(async () => {
21+
labels = [...$project.labels];
22+
});
23+
24+
async function updateLabels() {
25+
try {
26+
await sdk.forConsole.projects.updateLabels({ projectId: $project.$id, labels });
27+
await invalidate(Dependencies.PROJECT);
28+
isDisabled = true;
29+
addNotification({
30+
type: 'success',
31+
message: 'Project labels have been updated'
32+
});
33+
trackEvent(Submit.ProjectUpdateLabels);
34+
} catch (error) {
35+
addNotification({
36+
message: error.message,
37+
type: 'error'
38+
});
39+
trackError(error, Submit.ProjectUpdateLabels);
40+
}
41+
}
42+
43+
$: isDisabled = !!error || !symmetricDifference(labels, $project.labels).length;
44+
45+
$: if (labels) {
46+
const invalidLabels = [];
47+
48+
labels.forEach((label) => {
49+
if (!alphaNumericRegExp.test(label)) {
50+
invalidLabels.push(label);
51+
}
52+
});
53+
54+
if (invalidLabels.length) {
55+
error = `Invalid labels: ${invalidLabels.join(', ')}`;
56+
} else {
57+
error = '';
58+
}
59+
}
60+
</script>
61+
62+
<Form onSubmit={updateLabels}>
63+
<CardGrid>
64+
<svelte:fragment slot="title">Labels</svelte:fragment>
65+
Categorize and manage your projects for easy searching based on specific criteria by assigning
66+
them customizable labels.
67+
<svelte:fragment slot="aside">
68+
<Layout.Stack gap="s">
69+
{#key labels.length}
70+
<InputTags
71+
id="project-labels"
72+
label="Labels"
73+
placeholder="Select or type project labels"
74+
bind:tags={labels} />
75+
{/key}
76+
<Layout.Stack direction="row">
77+
{#each suggestedLabels as suggestedLabel}
78+
<Tag
79+
size="s"
80+
selected={labels.includes(suggestedLabel)}
81+
on:click={() => {
82+
if (!labels.includes(suggestedLabel)) {
83+
labels = [...labels, suggestedLabel];
84+
} else {
85+
labels = labels.filter((e) => e !== suggestedLabel);
86+
}
87+
}}>
88+
<Icon icon={IconPlus} size="s" slot="start" />
89+
{suggestedLabel}
90+
</Tag>
91+
{/each}
92+
</Layout.Stack>
93+
<Input.Helper state={error ? 'warning' : 'default'}
94+
>{error ? error : 'Only alphanumeric characters are allowed'}</Input.Helper>
95+
</Layout.Stack>
96+
</svelte:fragment>
97+
98+
<svelte:fragment slot="actions">
99+
<Button disabled={isDisabled} submit>Update</Button>
100+
</svelte:fragment>
101+
</CardGrid>
102+
</Form>

src/routes/(public)/(guest)/register/invite/[slug]/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
const res = await fetch(`${endpoint}/account/invite`, {
5858
method: 'POST',
5959
headers: {
60-
'X-Appwrite-Project': project,
60+
'X-Appwrite-Project': project as string,
6161
'Content-Type': 'application/json'
6262
},
6363
body: JSON.stringify({

0 commit comments

Comments
 (0)