mirror of
https://github.com/immich-app/immich.git
synced 2025-12-19 17:23:21 +03:00
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:
@@ -26,7 +26,7 @@ import { BASE_PATH } from './open-api/base';
|
||||
import { DUMMY_BASE_URL, toPathString } from './open-api/common';
|
||||
import type { ApiParams } from './types';
|
||||
|
||||
export class ImmichApi {
|
||||
class ImmichApi {
|
||||
public activityApi: ActivityApi;
|
||||
public albumApi: AlbumApi;
|
||||
public libraryApi: LibraryApi;
|
||||
|
||||
5
web/src/app.d.ts
vendored
5
web/src/app.d.ts
vendored
@@ -3,11 +3,6 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare namespace App {
|
||||
interface Locals {
|
||||
user?: import('@api').UserResponseDto;
|
||||
api: import('@api').ImmichApi;
|
||||
}
|
||||
|
||||
interface PageData {
|
||||
meta: {
|
||||
title: string;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
</script>
|
||||
<link rel="stylesheet" href="/custom.css" />
|
||||
</head>
|
||||
|
||||
<body class="bg-immich-bg dark:bg-immich-dark-bg">
|
||||
|
||||
40
web/src/hooks.client.ts
Normal file
40
web/src/hooks.client.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { HandleClientError } from '@sveltejs/kit';
|
||||
import type { AxiosError, AxiosResponse } from 'axios';
|
||||
|
||||
const LOG_PREFIX = '[hooks.client.ts]';
|
||||
const DEFAULT_MESSAGE = 'Hmm, not sure about that. Check the logs or open a ticket?';
|
||||
|
||||
const parseError = (error: unknown) => {
|
||||
const httpError = error as AxiosError;
|
||||
const request = httpError?.request as Request & { path: string };
|
||||
const response = httpError?.response as AxiosResponse<{
|
||||
message: string;
|
||||
statusCode: number;
|
||||
error: string;
|
||||
}>;
|
||||
|
||||
let code = response?.data?.statusCode || response?.status || httpError.code || '500';
|
||||
if (response) {
|
||||
code += ` - ${response.data?.error || response.statusText}`;
|
||||
}
|
||||
|
||||
if (request && response) {
|
||||
console.log({
|
||||
status: response.status,
|
||||
url: `${request.method} ${request.path}`,
|
||||
response: response.data || 'No data',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
message: response?.data?.message || httpError?.message || DEFAULT_MESSAGE,
|
||||
code,
|
||||
stack: httpError?.stack,
|
||||
};
|
||||
};
|
||||
|
||||
export const handleError: HandleClientError = ({ error }) => {
|
||||
const result = parseError(error);
|
||||
console.error(`${LOG_PREFIX}:handleError ${result.message}`);
|
||||
return result;
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
import { env } from '$env/dynamic/public';
|
||||
import type { Handle, HandleServerError } from '@sveltejs/kit';
|
||||
import type { AxiosError, AxiosResponse } from 'axios';
|
||||
import { ImmichApi } from './api/api';
|
||||
|
||||
const LOG_PREFIX = '[hooks.server.ts]';
|
||||
|
||||
export const handle = (async ({ event, resolve }) => {
|
||||
const basePath = env.PUBLIC_IMMICH_SERVER_URL || 'http://immich-server:3001';
|
||||
const accessToken = event.cookies.get('immich_access_token');
|
||||
const api = new ImmichApi({ basePath, accessToken });
|
||||
|
||||
// API instance that should be used for all server-side requests.
|
||||
event.locals.api = api;
|
||||
|
||||
if (accessToken) {
|
||||
try {
|
||||
const { data: user } = await api.userApi.getMyUserInfo();
|
||||
event.locals.user = user;
|
||||
} catch (err) {
|
||||
console.log(`${LOG_PREFIX} Unable to get my user`, parseError(err));
|
||||
|
||||
const apiError = err as AxiosError;
|
||||
// Ignore 401 unauthorized errors and log all others.
|
||||
if (apiError.response?.status && apiError.response?.status !== 401) {
|
||||
console.error(`${LOG_PREFIX}:handle`, err);
|
||||
} else if (!apiError.response?.status) {
|
||||
console.error(`${LOG_PREFIX}:handle`, apiError?.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const res = await resolve(event);
|
||||
|
||||
// The link header can grow quite big and has caused issues with our nginx
|
||||
// proxy returning a 502 Bad Gateway error. Therefore the header gets deleted.
|
||||
res.headers.delete('Link');
|
||||
|
||||
return res;
|
||||
}) satisfies Handle;
|
||||
|
||||
const DEFAULT_MESSAGE = 'Hmm, not sure about that. Check the logs or open a ticket?';
|
||||
|
||||
const parseError = (error: unknown) => {
|
||||
const httpError = error as AxiosError;
|
||||
const request = httpError?.request as Request & { path: string };
|
||||
const response = httpError?.response as AxiosResponse<{
|
||||
message: string;
|
||||
statusCode: number;
|
||||
error: string;
|
||||
}>;
|
||||
|
||||
let code = response?.data?.statusCode || response?.status || httpError.code || '500';
|
||||
if (response) {
|
||||
code += ` - ${response.data?.error || response.statusText}`;
|
||||
}
|
||||
|
||||
if (request && response) {
|
||||
console.log({
|
||||
status: response.status,
|
||||
url: `${request.method} ${request.path}`,
|
||||
response: response.data || 'No data',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
message: response?.data?.message || httpError?.message || DEFAULT_MESSAGE,
|
||||
code,
|
||||
stack: httpError?.stack,
|
||||
};
|
||||
};
|
||||
|
||||
export const handleError: HandleServerError = ({ error }) => {
|
||||
const result = parseError(error);
|
||||
console.error(`${LOG_PREFIX}:handleError ${result.message}`);
|
||||
return result;
|
||||
};
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
const logOut = async () => {
|
||||
const { data } = await api.authenticationApi.logout();
|
||||
|
||||
await fetch('/auth/logout', { method: 'POST' });
|
||||
|
||||
goto(data.redirectUri || '/auth/login?autoLaunch=0');
|
||||
};
|
||||
</script>
|
||||
|
||||
34
web/src/lib/utils/auth.ts
Normal file
34
web/src/lib/utils/auth.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { api } from '@api';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { AppRoute } from '../constants';
|
||||
|
||||
export interface AuthOptions {
|
||||
admin?: true;
|
||||
}
|
||||
|
||||
export const getAuthUser = async () => {
|
||||
try {
|
||||
const { data: user } = await api.userApi.getMyUserInfo();
|
||||
return user;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: re-use already loaded user (once) instead of fetching on each page navigation
|
||||
export const authenticate = async (options?: AuthOptions) => {
|
||||
options = options || {};
|
||||
|
||||
const user = await getAuthUser();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
if (options.admin && !user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
export const isLoggedIn = async () => getAuthUser().then((user) => !!user);
|
||||
@@ -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
web/src/routes/(user)/albums/+page.ts
Normal file
16
web/src/routes/(user)/albums/+page.ts
Normal 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;
|
||||
16
web/src/routes/(user)/albums/[albumId]/+page.ts
Normal file
16
web/src/routes/(user)/albums/[albumId]/+page.ts
Normal file
@@ -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
web/src/routes/(user)/archive/+page.ts
Normal file
13
web/src/routes/(user)/archive/+page.ts
Normal 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
web/src/routes/(user)/explore/+page.ts
Normal file
17
web/src/routes/(user)/explore/+page.ts
Normal 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
web/src/routes/(user)/favorites/+page.ts
Normal file
12
web/src/routes/(user)/favorites/+page.ts
Normal 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);
|
||||
}
|
||||
};
|
||||
7
web/src/routes/(user)/favorites/[assetId]/+page.ts
Normal file
7
web/src/routes/(user)/favorites/[assetId]/+page.ts
Normal file
@@ -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);
|
||||
};
|
||||
@@ -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
web/src/routes/(user)/map/+page.ts
Normal file
12
web/src/routes/(user)/map/+page.ts
Normal 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
web/src/routes/(user)/memory/+page.ts
Normal file
12
web/src/routes/(user)/memory/+page.ts
Normal 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);
|
||||
}
|
||||
};
|
||||
9
web/src/routes/(user)/memory/photos/+page.ts
Normal file
9
web/src/routes/(user)/memory/photos/+page.ts
Normal file
@@ -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);
|
||||
}
|
||||
};
|
||||
7
web/src/routes/(user)/memory/photos/[assetId]/+page.ts
Normal file
7
web/src/routes/(user)/memory/photos/[assetId]/+page.ts
Normal file
@@ -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',
|
||||
},
|
||||
};
|
||||
};
|
||||
17
web/src/routes/(user)/partners/[userId]/+page.ts
Normal file
17
web/src/routes/(user)/partners/[userId]/+page.ts
Normal file
@@ -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
web/src/routes/(user)/people/+page.ts
Normal file
16
web/src/routes/(user)/people/+page.ts
Normal 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;
|
||||
19
web/src/routes/(user)/people/[personId]/+page.ts
Normal file
19
web/src/routes/(user)/people/[personId]/+page.ts
Normal file
@@ -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
web/src/routes/(user)/photos/+page.ts
Normal file
12
web/src/routes/(user)/photos/+page.ts
Normal 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);
|
||||
}
|
||||
};
|
||||
7
web/src/routes/(user)/photos/[assetId]/+page.ts
Normal file
7
web/src/routes/(user)/photos/[assetId]/+page.ts
Normal file
@@ -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
web/src/routes/(user)/search/+page.ts
Normal file
20
web/src/routes/(user)/search/+page.ts
Normal 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;
|
||||
15
web/src/routes/(user)/share/[key]/photos/[assetId]/+page.ts
Normal file
15
web/src/routes/(user)/share/[key]/photos/[assetId]/+page.ts
Normal file
@@ -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
web/src/routes/(user)/sharing/+page.ts
Normal file
18
web/src/routes/(user)/sharing/+page.ts
Normal 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;
|
||||
12
web/src/routes/(user)/sharing/sharedlinks/+page.ts
Normal file
12
web/src/routes/(user)/sharing/sharedlinks/+page.ts
Normal 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: '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
web/src/routes/(user)/trash/+page.ts
Normal file
12
web/src/routes/(user)/trash/+page.ts
Normal 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;
|
||||
19
web/src/routes/(user)/user-settings/+page.ts
Normal file
19
web/src/routes/(user)/user-settings/+page.ts
Normal file
@@ -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;
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { LayoutServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
return { user };
|
||||
}) satisfies LayoutServerLoad;
|
||||
@@ -24,7 +24,10 @@
|
||||
export let data: LayoutData;
|
||||
let albumId: string | undefined;
|
||||
|
||||
if ($page.route.id?.startsWith('/(user)/share/[key]')) {
|
||||
const isSharedLinkRoute = (route: string | null) => route?.startsWith('/(user)/share/[key]');
|
||||
const isAuthRoute = (route?: string) => route?.startsWith('/auth');
|
||||
|
||||
if (isSharedLinkRoute($page.route?.id)) {
|
||||
api.setKey($page.params.key);
|
||||
}
|
||||
|
||||
@@ -32,11 +35,11 @@
|
||||
const fromRoute = from?.route?.id || '';
|
||||
const toRoute = to?.route?.id || '';
|
||||
|
||||
if (fromRoute.startsWith('/auth') && !toRoute.startsWith('/auth')) {
|
||||
if (isAuthRoute(fromRoute) && !isAuthRoute(toRoute)) {
|
||||
openWebsocketConnection();
|
||||
}
|
||||
|
||||
if (!fromRoute.startsWith('/auth') && toRoute.startsWith('/auth')) {
|
||||
if (!isAuthRoute(fromRoute) && isAuthRoute(toRoute)) {
|
||||
closeWebsocketConnection();
|
||||
}
|
||||
|
||||
@@ -80,7 +83,6 @@
|
||||
<svelte:head>
|
||||
<title>{$page.data.meta?.title || 'Web'} - Immich</title>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="stylesheet" href="/custom.css" />
|
||||
<meta name="theme-color" content="currentColor" />
|
||||
<FaviconHeader />
|
||||
<AppleHeader />
|
||||
|
||||
25
web/src/routes/+layout.ts
Normal file
25
web/src/routes/+layout.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { api } from '../api';
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
const getUser = async () => {
|
||||
try {
|
||||
const { data: user } = await api.userApi.getMyUserInfo();
|
||||
return user;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const ssr = false;
|
||||
export const csr = true;
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await getUser();
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Immich',
|
||||
},
|
||||
};
|
||||
}) satisfies LayoutLoad;
|
||||
@@ -1,17 +1,19 @@
|
||||
export const prerender = false;
|
||||
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { api } from '../api';
|
||||
import { isLoggedIn } from '../lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
if (user) {
|
||||
export const ssr = false;
|
||||
export const csr = true;
|
||||
|
||||
export const load = (async () => {
|
||||
const authenticated = await isLoggedIn();
|
||||
if (authenticated) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data } = await api.serverInfoApi.getServerConfig();
|
||||
|
||||
if (data.isInitialized) {
|
||||
// Redirect to login page if there exists an admin account (i.e. server is initialized)
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
@@ -23,4 +25,4 @@ export const load = (async ({ parent, locals: { api } }) => {
|
||||
description: 'Immich Web Interface',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,11 +0,0 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
const endpoint = process.env.IMMICH_API_URL_EXTERNAL || '/api';
|
||||
|
||||
export const GET = async () => {
|
||||
return json({
|
||||
api: {
|
||||
endpoint,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
throw redirect(302, AppRoute.ADMIN_USER_MANAGEMENT);
|
||||
};
|
||||
7
web/src/routes/admin/+page.ts
Normal file
7
web/src/routes/admin/+page.ts
Normal file
@@ -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.ADMIN_USER_MANAGEMENT);
|
||||
}) 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: { user, api } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: jobs } = await api.jobApi.getAllJobsStatus();
|
||||
|
||||
return {
|
||||
user,
|
||||
jobs,
|
||||
meta: {
|
||||
title: 'Job Status',
|
||||
},
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('[jobs] > getAllJobsStatus', err);
|
||||
throw err;
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
17
web/src/routes/admin/jobs-status/+page.ts
Normal file
17
web/src/routes/admin/jobs-status/+page.ts
Normal 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({ admin: true });
|
||||
|
||||
const { data: jobs } = await api.jobApi.getAllJobsStatus();
|
||||
|
||||
return {
|
||||
user,
|
||||
jobs,
|
||||
meta: {
|
||||
title: 'Job Status',
|
||||
},
|
||||
};
|
||||
}) 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 ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const {
|
||||
data: { orphans, extras },
|
||||
} = await api.auditApi.getAuditFiles();
|
||||
|
||||
return {
|
||||
user,
|
||||
orphans,
|
||||
extras,
|
||||
meta: {
|
||||
title: 'Repair',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
19
web/src/routes/admin/repair/+page.ts
Normal file
19
web/src/routes/admin/repair/+page.ts
Normal file
@@ -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({ admin: true });
|
||||
const {
|
||||
data: { orphans, extras },
|
||||
} = await api.auditApi.getAuditFiles();
|
||||
|
||||
return {
|
||||
user,
|
||||
orphans,
|
||||
extras,
|
||||
meta: {
|
||||
title: 'Repair',
|
||||
},
|
||||
};
|
||||
}) 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 ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data: stats } = await api.serverInfoApi.getServerStatistics();
|
||||
|
||||
return {
|
||||
user,
|
||||
stats,
|
||||
meta: {
|
||||
title: 'Server Stats',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
16
web/src/routes/admin/server-status/+page.ts
Normal file
16
web/src/routes/admin/server-status/+page.ts
Normal 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({ admin: true });
|
||||
const { data: stats } = await api.serverInfoApi.getServerStatistics();
|
||||
|
||||
return {
|
||||
user,
|
||||
stats,
|
||||
meta: {
|
||||
title: 'Server Stats',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data: configs } = await api.systemConfigApi.getConfig();
|
||||
|
||||
return {
|
||||
user,
|
||||
configs,
|
||||
meta: {
|
||||
title: 'System Settings',
|
||||
},
|
||||
};
|
||||
};
|
||||
16
web/src/routes/admin/system-settings/+page.ts
Normal file
16
web/src/routes/admin/system-settings/+page.ts
Normal 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({ admin: true });
|
||||
const { data: configs } = await api.systemConfigApi.getConfig();
|
||||
|
||||
return {
|
||||
user,
|
||||
configs,
|
||||
meta: {
|
||||
title: 'System Settings',
|
||||
},
|
||||
};
|
||||
}) 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 ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data: allUsers } = await api.userApi.getAllUsers({ isAll: false });
|
||||
|
||||
return {
|
||||
user,
|
||||
allUsers,
|
||||
meta: {
|
||||
title: 'User Management',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
16
web/src/routes/admin/user-management/+page.ts
Normal file
16
web/src/routes/admin/user-management/+page.ts
Normal 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({ admin: true });
|
||||
const { data: allUsers } = await api.userApi.getAllUsers({ isAll: false });
|
||||
|
||||
return {
|
||||
user,
|
||||
allUsers,
|
||||
meta: {
|
||||
title: 'User Management',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,18 +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);
|
||||
} else if (!user.shouldChangePassword) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Change Password',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
18
web/src/routes/auth/change-password/+page.ts
Normal file
18
web/src/routes/auth/change-password/+page.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
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 () => {
|
||||
const user = await authenticate();
|
||||
if (!user.shouldChangePassword) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Change Password',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,8 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { api } from '@api';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api } }) => {
|
||||
export const load = (async () => {
|
||||
const { data } = await api.serverInfoApi.getServerConfig();
|
||||
if (!data.isInitialized) {
|
||||
// Admin not registered
|
||||
@@ -14,4 +15,4 @@ export const load = (async ({ locals: { api } }) => {
|
||||
title: 'Login',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,12 +0,0 @@
|
||||
import { api } from '@api';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
export const POST = (async ({ cookies }) => {
|
||||
api.removeAccessToken();
|
||||
|
||||
cookies.delete('immich_auth_type', { path: '/' });
|
||||
cookies.delete('immich_access_token', { path: '/' });
|
||||
|
||||
return json({ ok: true });
|
||||
}) satisfies RequestHandler;
|
||||
@@ -1,8 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { api } from '@api';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api } }) => {
|
||||
export const load = (async () => {
|
||||
const { data } = await api.serverInfoApi.getServerConfig();
|
||||
if (data.isInitialized) {
|
||||
// Admin has been registered, redirect to login
|
||||
@@ -14,4 +15,4 @@ export const load = (async ({ locals: { api } }) => {
|
||||
title: 'Admin Registration',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,11 +0,0 @@
|
||||
import { RequestHandler, text } from '@sveltejs/kit';
|
||||
export const GET = (async ({ locals: { api } }) => {
|
||||
const {
|
||||
data: { customCss },
|
||||
} = await api.serverInfoApi.getTheme();
|
||||
return text(customCss, {
|
||||
headers: {
|
||||
'Content-Type': 'text/css',
|
||||
},
|
||||
});
|
||||
}) satisfies RequestHandler;
|
||||
Reference in New Issue
Block a user