feat(web)!: SPA (#5069)

* feat(web): SPA

* chore: remove unnecessary prune

* feat(web): merge with immich-server

* Correct method name

* fix: bugs, docs, workflows, etc.

* chore: keep dockerignore for dev

* chore: remove license

* fix: expose 2283

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jason Rasmussen
2023-11-17 23:13:36 -05:00
committed by GitHub
parent 5118d261ab
commit adae5dd758
115 changed files with 730 additions and 1446 deletions
@@ -1,23 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { api, user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
try {
const { data: albums } = await api.albumApi.getAllAlbums();
return {
user: user,
albums: albums,
meta: {
title: 'Albums',
},
};
} catch (e) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
}) satisfies PageServerLoad;
+16
View File
@@ -0,0 +1,16 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
const { data: albums } = await api.albumApi.getAllAlbums();
return {
user,
albums,
meta: {
title: 'Albums',
},
};
}) satisfies PageLoad;
@@ -1,23 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ params, locals: { api, user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
try {
const { data: album } = await api.albumApi.getAlbumInfo({ id: params.albumId, withoutAssets: true });
return {
album,
user,
meta: {
title: album.albumName,
},
};
} catch (e) {
throw redirect(302, AppRoute.ALBUMS);
}
}) satisfies PageServerLoad;
@@ -0,0 +1,16 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async ({ params }) => {
const user = await authenticate();
const { data: album } = await api.albumApi.getAlbumInfo({ id: params.albumId, withoutAssets: true });
return {
album,
user,
meta: {
title: album.albumName,
},
};
}) satisfies PageLoad;
@@ -1,15 +1,9 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const prerender = false;
export const load: PageLoad = async ({ params, parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const albumId = params['albumId'];
export const load: PageLoad = async ({ params }) => {
const albumId = params.albumId;
if (albumId) {
throw redirect(302, `${AppRoute.ALBUMS}/${albumId}`);
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Archive',
},
};
}) satisfies PageServerLoad;
+13
View File
@@ -0,0 +1,13 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Archive',
},
};
}) satisfies PageLoad;
@@ -1,13 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const prerender = false;
export const load: PageLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
export const load: PageLoad = async () => {
throw redirect(302, AppRoute.ARCHIVE);
};
@@ -1,21 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals, parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const { data: items } = await locals.api.searchApi.getExploreData();
const { data: response } = await locals.api.personApi.getAllPeople({ withHidden: false });
return {
user,
items,
response,
meta: {
title: 'Explore',
},
};
}) satisfies PageServerLoad;
+17
View File
@@ -0,0 +1,17 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
const { data: items } = await api.searchApi.getExploreData();
const { data: response } = await api.personApi.getAllPeople({ withHidden: false });
return {
user,
items,
response,
meta: {
title: 'Explore',
},
};
}) satisfies PageLoad;
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Favorites',
},
};
}) satisfies PageServerLoad;
+12
View File
@@ -0,0 +1,12 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Favorites',
},
};
}) satisfies PageLoad;
@@ -1,15 +0,0 @@
import { redirect } from '@sveltejs/kit';
export const prerender = false;
import { AppRoute } from '$lib/constants';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
} else {
throw redirect(302, AppRoute.FAVORITES);
}
};
@@ -0,0 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = async () => {
throw redirect(302, AppRoute.FAVORITES);
};
-16
View File
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Map',
},
};
}) satisfies PageServerLoad;
+12
View File
@@ -0,0 +1,12 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Map',
},
};
}) satisfies PageLoad;
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Memory',
},
};
}) satisfies PageServerLoad;
+12
View File
@@ -0,0 +1,12 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Memory',
},
};
}) satisfies PageLoad;
@@ -1,15 +0,0 @@
import { redirect } from '@sveltejs/kit';
export const prerender = false;
import { AppRoute } from '$lib/constants';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
} else {
throw redirect(302, AppRoute.MEMORY);
}
};
@@ -0,0 +1,9 @@
import { AppRoute } from '$lib/constants';
import { authenticate } from '$lib/utils/auth';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
await authenticate();
throw redirect(302, AppRoute.MEMORY);
}) satisfies PageLoad;
@@ -1,15 +0,0 @@
import { redirect } from '@sveltejs/kit';
export const prerender = false;
import { AppRoute } from '$lib/constants';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
} else {
throw redirect(302, AppRoute.MEMORY);
}
};
@@ -0,0 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
throw redirect(302, AppRoute.PHOTOS);
}) satisfies PageLoad;
@@ -1,21 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ params, parent, locals: { api } }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const { data: partner } = await api.userApi.getUserById({ id: params['userId'] });
return {
user,
partner,
meta: {
title: 'Partner',
},
};
};
@@ -0,0 +1,17 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async ({ params }) => {
const user = await authenticate();
const { data: partner } = await api.userApi.getUserById({ id: params.userId });
return {
user,
partner,
meta: {
title: 'Partner',
},
};
}) satisfies PageLoad;
@@ -1,19 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals, parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const { data: people } = await locals.api.personApi.getAllPeople({ withHidden: true });
return {
user,
people,
meta: {
title: 'People',
},
};
}) satisfies PageServerLoad;
+16
View File
@@ -0,0 +1,16 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
const { data: people } = await api.personApi.getAllPeople({ withHidden: true });
return {
user,
people,
meta: {
title: 'People',
},
};
}) satisfies PageLoad;
@@ -1,22 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals, parent, params }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const { data: person } = await locals.api.personApi.getPerson({ id: params.personId });
const { data: statistics } = await locals.api.personApi.getPersonStatistics({ id: params.personId });
return {
user,
person,
statistics,
meta: {
title: person.name || 'Person',
},
};
}) satisfies PageServerLoad;
@@ -0,0 +1,19 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async ({ params }) => {
const user = await authenticate();
const { data: person } = await api.personApi.getPerson({ id: params.personId });
const { data: statistics } = await api.personApi.getPersonStatistics({ id: params.personId });
return {
user,
person,
statistics,
meta: {
title: person.name || 'Person',
},
};
}) satisfies PageLoad;
@@ -1,14 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const prerender = false;
export const load: PageLoad = async ({ params, parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const personId = params['personId'];
throw redirect(302, `${AppRoute.PEOPLE}/${personId}`);
};
export const load = (async ({ params }) => {
throw redirect(302, `${AppRoute.PEOPLE}/${params.personId}`);
}) satisfies PageLoad;
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Photos',
},
};
}) satisfies PageServerLoad;
+12
View File
@@ -0,0 +1,12 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Photos',
},
};
}) satisfies PageLoad;
@@ -1,15 +0,0 @@
import { redirect } from '@sveltejs/kit';
export const prerender = false;
import { AppRoute } from '$lib/constants';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
} else {
throw redirect(302, AppRoute.PHOTOS);
}
};
@@ -0,0 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
throw redirect(302, AppRoute.PHOTOS);
}) satisfies PageLoad;
@@ -1,23 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals, parent, url }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const term = url.searchParams.get('q') || url.searchParams.get('query') || undefined;
const { data: results } = await locals.api.searchApi.search({}, { params: url.searchParams });
return {
user,
term,
results,
meta: {
title: 'Search',
},
};
}) satisfies PageServerLoad;
+20
View File
@@ -0,0 +1,20 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
const url = new URL(location.href);
const term = url.searchParams.get('q') || url.searchParams.get('query') || undefined;
const { data: results } = await api.searchApi.search({}, { params: url.searchParams });
return {
user,
term,
results,
meta: {
title: 'Search',
},
};
}) satisfies PageLoad;
@@ -1,13 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const prerender = false;
export const load: PageLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
export const load = (async () => {
throw redirect(302, AppRoute.SEARCH);
};
}) satisfies PageLoad;
@@ -1,31 +1,32 @@
import featurePanelUrl from '$lib/assets/feature-panel.png';
import { api as clientApi, ThumbnailFormat } from '@api';
import { getAuthUser } from '$lib/utils/auth';
import { api, ThumbnailFormat } from '@api';
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import type { AxiosError } from 'axios';
import type { PageLoad } from './$types';
export const load = (async ({ params, locals: { api }, cookies }) => {
export const load = (async ({ params }) => {
const { key } = params;
const token = cookies.get('immich_shared_link_token');
const user = await getAuthUser();
try {
const { data: sharedLink } = await api.sharedLinkApi.getMySharedLink({ key, token });
const { data: sharedLink } = await api.sharedLinkApi.getMySharedLink({ key });
const assetCount = sharedLink.assets.length;
const assetId = sharedLink.album?.albumThumbnailAssetId || sharedLink.assets[0]?.id;
return {
user,
sharedLink,
meta: {
title: sharedLink.album ? sharedLink.album.albumName : 'Public Share',
description: sharedLink.description || `${assetCount} shared photos & videos.`,
imageUrl: assetId
? clientApi.getAssetThumbnailUrl(assetId, ThumbnailFormat.Webp, sharedLink.key)
: featurePanelUrl,
imageUrl: assetId ? api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Webp, sharedLink.key) : featurePanelUrl,
},
};
} catch (e) {
// handle unauthorized error
// TODO this doesn't allow for 404 shared links anymore
if ((e as AxiosError).response?.status === 401) {
return {
passwordRequired: true,
@@ -40,4 +41,4 @@ export const load = (async ({ params, locals: { api }, cookies }) => {
message: 'Invalid shared link',
});
}
}) satisfies PageServerLoad;
}) satisfies PageLoad;
@@ -1,19 +0,0 @@
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ params, locals: { api } }) => {
const { key, assetId } = params;
const { data: asset } = await api.assetApi.getAssetById({ id: assetId, key });
if (!asset) {
throw error(404, 'Asset not found');
}
return {
asset,
key,
meta: {
title: 'Public Share',
},
};
}) satisfies PageServerLoad;
@@ -0,0 +1,15 @@
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async ({ params }) => {
const { key, assetId } = params;
const { data: asset } = await api.assetApi.getAssetById({ id: assetId, key });
return {
asset,
key,
meta: {
title: 'Public Share',
},
};
}) satisfies PageLoad;
@@ -1,26 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { api, user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
try {
const { data: sharedAlbums } = await api.albumApi.getAllAlbums({ shared: true });
const { data: partners } = await api.partnerApi.getPartners({ direction: 'shared-with' });
return {
user,
sharedAlbums,
partners,
meta: {
title: 'Sharing',
},
};
} catch (e) {
console.log(e);
throw redirect(302, AppRoute.AUTH_LOGIN);
}
}) satisfies PageServerLoad;
+18
View File
@@ -0,0 +1,18 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
const { data: sharedAlbums } = await api.albumApi.getAllAlbums({ shared: true });
const { data: partners } = await api.partnerApi.getPartners({ direction: 'shared-with' });
return {
user,
sharedAlbums,
partners,
meta: {
title: 'Sharing',
},
};
}) satisfies PageLoad;
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Shared Links',
},
};
}) satisfies PageServerLoad;
@@ -0,0 +1,12 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Shared Links',
},
};
}) satisfies PageLoad;
@@ -1,16 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
return {
user,
meta: {
title: 'Trash',
},
};
}) satisfies PageServerLoad;
+12
View File
@@ -0,0 +1,12 @@
import { authenticate } from '$lib/utils/auth';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
return {
user,
meta: {
title: 'Trash',
},
};
}) satisfies PageLoad;
@@ -1,13 +1,7 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const prerender = false;
export const load: PageLoad = async ({ parent }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
export const load = (async () => {
throw redirect(302, AppRoute.TRASH);
};
}) satisfies PageLoad;
@@ -1,22 +0,0 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ parent, locals }) => {
const { user } = await parent();
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
}
const { data: keys } = await locals.api.keyApi.getApiKeys();
const { data: devices } = await locals.api.authenticationApi.getAuthDevices();
return {
user,
keys,
devices,
meta: {
title: 'Settings',
},
};
}) satisfies PageServerLoad;
@@ -0,0 +1,19 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
const user = await authenticate();
const { data: keys } = await api.keyApi.getApiKeys();
const { data: devices } = await api.authenticationApi.getAuthDevices();
return {
user,
keys,
devices,
meta: {
title: 'Settings',
},
};
}) satisfies PageLoad;