Skip to content

Commit 47087aa

Browse files
authored
feat: command prompt (#177)
feat: command palette
1 parent b439082 commit 47087aa

File tree

11 files changed

+499
-75
lines changed

11 files changed

+499
-75
lines changed
Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
import { goto } from '$app/navigation';
2-
import { loadOpenApi } from '$lib/api/services/open-api';
31
import type { LayoutLoad } from './$types';
42

5-
export const load = (async ({ fetch }) => {
6-
try {
7-
await loadOpenApi(fetch);
8-
} catch (error) {
9-
console.log('Failed to load open-api specification', error);
10-
await goto('/');
11-
}
3+
export const load = (async ({ parent }) => {
4+
await parent();
125
}) satisfies LayoutLoad;

apps/api.immich.app/routes/(docs)/permissions/+page.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
>
1515
<Text>
1616
Most of the <Link href={ApiPage.Endpoints}>endpoints</Link> require a specific permission to access. You can find the
17-
required permission for each endpoint on the <Link href={ApiPage.Endpoints}>endpoints</Link> overview page, as well as
18-
each endpoint's detail page.
17+
required permission for each endpoint in each endpoint's detail page, towards the top.
1918
</Text>
2019
</ApiPageContent>

apps/api.immich.app/routes/+layout.svelte

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
<script lang="ts">
22
import { afterNavigate, beforeNavigate } from '$app/navigation';
33
import { page } from '$app/state';
4+
import { getOpenApi } from '$lib/api/services/open-api';
45
import '$lib/app.css';
5-
import { initializeTheme } from '@immich/ui';
6+
import CommandPalette from '$lib/components/CommandPalette.svelte';
7+
import { commandPaletteManager } from '$lib/services/command-palette-manager.svelte';
8+
import { ApiPage } from '$lib/utils/api';
9+
import { initializeTheme, onThemeChange, Theme, theme } from '@immich/ui';
10+
import { mdiApi, mdiScriptText, mdiSend, mdiTag, mdiTagMultiple } from '@mdi/js';
611
import { onMount, type Snippet } from 'svelte';
712
813
interface Props {
@@ -30,6 +35,130 @@
3035
}
3136
window.scrollTo({ top: 0, behavior: 'auto' });
3237
});
38+
39+
const handleToggleTheme = () => {
40+
theme.value = theme.value === Theme.Dark ? Theme.Light : Theme.Dark;
41+
onThemeChange();
42+
};
43+
44+
const asText = (...items: unknown[]) => {
45+
return items
46+
.filter((item) => item !== undefined && item !== null)
47+
.map((items) => String(items))
48+
.join('|')
49+
.toLowerCase();
50+
};
51+
52+
const { tags, models } = getOpenApi();
53+
54+
commandPaletteManager.reset();
55+
56+
for (const tag of tags) {
57+
commandPaletteManager.addCommands({
58+
icon: mdiTagMultiple,
59+
iconClass: 'text-pink-700 dark:text-pink-200',
60+
type: 'Tag',
61+
title: tag.name,
62+
href: tag.href,
63+
text: asText(tag.name),
64+
});
65+
66+
for (const endpoint of tag.endpoints) {
67+
commandPaletteManager.addCommands({
68+
icon: mdiApi,
69+
type: 'Endpoint',
70+
iconClass: 'text-indigo-700 dark:text-indigo-200',
71+
title: endpoint.operationId,
72+
description: endpoint.description,
73+
href: endpoint.href,
74+
text: asText(endpoint.operationId, endpoint.name, endpoint.description),
75+
});
76+
}
77+
}
78+
79+
for (const model of models) {
80+
commandPaletteManager.addCommands({
81+
icon: mdiTag,
82+
iconClass: 'text-violet-700 dark:text-violet-200',
83+
type: 'Model',
84+
title: model.name,
85+
description: model.description,
86+
href: model.href,
87+
text: asText(model.name, model.title, model.description),
88+
});
89+
}
90+
91+
commandPaletteManager.addCommands(
92+
[
93+
{
94+
title: 'Introduction',
95+
description: 'Overview of Immich API',
96+
href: ApiPage.Introduction,
97+
text: asText('introduction'),
98+
},
99+
{
100+
title: 'Getting Started',
101+
description: 'Learn how to get started with Immich API',
102+
href: ApiPage.GettingStarted,
103+
text: asText('getting', 'started'),
104+
},
105+
{
106+
title: 'Authentication',
107+
description: 'Learn how authentication works in the Immich API',
108+
href: ApiPage.Authentication,
109+
text: asText('authentication', 'authorization'),
110+
},
111+
{
112+
title: 'Permissions',
113+
description: 'Learn how permissions work with the Immich API',
114+
href: ApiPage.Permissions,
115+
text: asText('permissions'),
116+
},
117+
{
118+
title: 'SDK',
119+
description: 'Learn about the @immich/sdk generated client',
120+
href: ApiPage.Sdk,
121+
text: asText('@immich/sdk'),
122+
},
123+
{
124+
title: 'Endpoints',
125+
description: 'A list of all the endpoints in the Immich API',
126+
href: ApiPage.Endpoints,
127+
text: asText('overview', 'endpoints'),
128+
},
129+
{
130+
title: 'Models',
131+
description: 'A list of all the models in the Immich API',
132+
href: ApiPage.Models,
133+
text: asText('overview', 'models'),
134+
},
135+
].map((item) => ({
136+
icon: mdiScriptText,
137+
iconClass: 'text-teal-800 dark:text-teal-200',
138+
type: 'Page',
139+
...item,
140+
})),
141+
);
142+
143+
commandPaletteManager.addCommands(
144+
[
145+
{
146+
title: 'Toggle theme',
147+
description: 'Toggle between light and dark theme',
148+
onclick: () => handleToggleTheme(),
149+
text: asText('theme', 'toggle', 'dark', 'light'),
150+
},
151+
].map((item) => ({
152+
icon: mdiSend,
153+
iconClass: 'text-purple-800 dark:text-purple-200',
154+
type: 'Action',
155+
...item,
156+
})),
157+
);
158+
159+
commandPaletteManager.enable();
33160
</script>
34161

162+
<CommandPalette />
163+
35164
{@render children?.()}

apps/api.immich.app/routes/+layout.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1+
import { goto } from '$app/navigation';
2+
import { loadOpenApi } from '$lib/api/services/open-api';
3+
import type { LayoutLoad } from './$types';
4+
15
export const ssr = false;
6+
7+
export const load = (async ({ fetch }) => {
8+
try {
9+
await loadOpenApi(fetch);
10+
} catch (error) {
11+
console.log('Failed to load open-api specification', error);
12+
await goto('/');
13+
}
14+
}) satisfies LayoutLoad;

0 commit comments

Comments
 (0)