mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
feat(web): meta tags for share links (#1290)
* feat(web): meta tags for share links * refactor: svelte head tags * chore: clean up * chore: linting
This commit is contained in:
parent
a3688fe642
commit
fa31a6e441
@ -1,10 +1,18 @@
|
||||
import { api, AddAssetsResponseDto, AssetResponseDto } from '@api';
|
||||
import { api, AddAssetsResponseDto, AssetResponseDto, ThumbnailFormat } from '@api';
|
||||
import {
|
||||
notificationController,
|
||||
NotificationType
|
||||
} from '$lib/components/shared-components/notification/notification';
|
||||
import { downloadAssets } from '$lib/stores/download';
|
||||
|
||||
export const getThumbnailUrl = (assetId: string, format: ThumbnailFormat, key?: string) => {
|
||||
let url = `/api/asset/thumbnail/${assetId}?format=${format}`;
|
||||
if (key) {
|
||||
url += `&key=${key}`;
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
export const addAssetsToAlbum = async (
|
||||
albumId: string,
|
||||
assetIds: Array<string>,
|
||||
|
@ -77,6 +77,25 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{$page.data.meta?.title} - Immich</title>
|
||||
{#if $page.data.meta}
|
||||
<meta name="description" content={$page.data.meta.description} />
|
||||
|
||||
<!-- Facebook Meta Tags -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={$page.data.meta.title} />
|
||||
<meta property="og:description" content={$page.data.meta.description} />
|
||||
<meta property="og:image" content={$page.data.meta.imageUrl} />
|
||||
|
||||
<!-- Twitter Meta Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={$page.data.meta.title} />
|
||||
<meta name="twitter:description" content={$page.data.meta.description} />
|
||||
<meta name="twitter:image" content={$page.data.meta.imageUrl} />
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
<main on:dragenter={() => (showUploadCover = true)}>
|
||||
{#if canShow}
|
||||
<div in:fade={{ duration: 100 }}>
|
||||
|
@ -2,11 +2,6 @@
|
||||
import { goto } from '$app/navigation';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Welcome 🎉 - Immich</title>
|
||||
<meta name="description" content="Immich Web Interface" />
|
||||
</svelte:head>
|
||||
|
||||
<section class="h-screen w-screen flex place-items-center place-content-center">
|
||||
<div class="flex flex-col place-items-center gap-8 text-center max-w-[350px]">
|
||||
<div class="flex place-items-center place-content-center ">
|
||||
|
@ -7,4 +7,11 @@ export const load: PageLoad = async ({ parent }) => {
|
||||
if (user) {
|
||||
throw redirect(302, '/photos');
|
||||
}
|
||||
|
||||
return {
|
||||
meta: {
|
||||
title: 'Welcome 🎉',
|
||||
description: 'Immich Web Interface'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -26,10 +26,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Administration - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<NavigationBar user={$page.data.user} />
|
||||
|
||||
<main>
|
||||
|
@ -9,4 +9,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, '/photos');
|
||||
}
|
||||
|
||||
return {
|
||||
meta: {
|
||||
title: 'Job Status'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -2,10 +2,6 @@
|
||||
import JobsPanel from '$lib/components/admin-page/jobs/jobs-panel.svelte';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Jobs Status - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section>
|
||||
<JobsPanel />
|
||||
</section>
|
||||
|
@ -13,5 +13,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
|
||||
const { data: allUsers } = await serverApi.userApi.getAllUsers(false);
|
||||
|
||||
return { allUsers };
|
||||
return {
|
||||
allUsers,
|
||||
meta: {
|
||||
title: 'Server Status'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -3,10 +3,6 @@
|
||||
import { page } from '$app/stores';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Server Status - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if $page.data.allUsers}
|
||||
<ServerStatsPanel allUsers={$page.data.allUsers} />
|
||||
{/if}
|
||||
|
@ -10,5 +10,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
throw redirect(302, '/photos');
|
||||
}
|
||||
|
||||
return { user };
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'System Settings'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -17,10 +17,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>System Settings - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="">
|
||||
{#await getConfig()}
|
||||
<LoadingSpinner />
|
||||
|
@ -13,5 +13,11 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
|
||||
const { data: allUsers } = await serverApi.userApi.getAllUsers(false);
|
||||
|
||||
return { user, allUsers };
|
||||
return {
|
||||
user,
|
||||
allUsers,
|
||||
meta: {
|
||||
title: 'User Management'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -101,10 +101,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>User Management - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section>
|
||||
{#if shouldShowCreateUserForm}
|
||||
<FullScreenModal on:clickOutside={() => (shouldShowCreateUserForm = false)}>
|
||||
|
@ -14,7 +14,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
|
||||
return {
|
||||
user: user,
|
||||
albums: albums
|
||||
albums: albums,
|
||||
meta: {
|
||||
title: 'Albums'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, '/auth/login');
|
||||
|
@ -34,10 +34,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Albums - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section>
|
||||
<NavigationBar user={data.user} shouldShowUploadButton={false} />
|
||||
</section>
|
||||
|
@ -15,7 +15,10 @@ export const load: PageServerLoad = async ({ parent, params }) => {
|
||||
try {
|
||||
const { data: album } = await serverApi.albumApi.getAlbumInfo(albumId);
|
||||
return {
|
||||
album
|
||||
album,
|
||||
meta: {
|
||||
title: album.albumName
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, '/albums');
|
||||
|
@ -5,10 +5,6 @@
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.album.albumName} - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="immich-scrollbar">
|
||||
<AlbumViewer album={data.album} />
|
||||
</div>
|
||||
|
@ -14,10 +14,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Change Password - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="h-screen w-screen flex place-items-center place-content-center">
|
||||
<div in:fade={{ duration: 100 }} out:fade={{ duration: 100 }}>
|
||||
<ChangePasswordForm user={data.user} on:success={onSuccessHandler} />
|
||||
|
@ -10,7 +10,10 @@ export const load: PageLoad = async () => {
|
||||
|
||||
if (userInfo.shouldChangePassword) {
|
||||
return {
|
||||
user: userInfo
|
||||
user: userInfo,
|
||||
meta: {
|
||||
title: 'Change Password'
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw redirect(302, '/photos');
|
||||
|
@ -9,5 +9,9 @@ export const load: PageServerLoad = async () => {
|
||||
throw redirect(302, '/auth/register');
|
||||
}
|
||||
|
||||
return;
|
||||
return {
|
||||
meta: {
|
||||
title: 'Login'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -5,10 +5,6 @@
|
||||
import LoginForm from '$lib/components/forms/login-form.svelte';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Login - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="h-screen w-screen flex place-items-center place-content-center">
|
||||
<div in:fade={{ duration: 100 }} out:fade={{ duration: 100 }}>
|
||||
<LoginForm
|
||||
|
@ -9,5 +9,9 @@ export const load: PageServerLoad = async () => {
|
||||
throw redirect(302, '/auth/login');
|
||||
}
|
||||
|
||||
return;
|
||||
return {
|
||||
meta: {
|
||||
title: 'Admin Registration'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -2,10 +2,6 @@
|
||||
import AdminRegistrationForm from '$lib/components/forms/admin-registration-form.svelte';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Admin Registration - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="h-screen w-screen flex place-items-center place-content-center">
|
||||
<AdminRegistrationForm />
|
||||
</section>
|
||||
|
@ -9,7 +9,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
}
|
||||
|
||||
return {
|
||||
user
|
||||
user,
|
||||
meta: {
|
||||
title: 'Photos'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
console.log('Photo page load error', e);
|
||||
|
@ -116,10 +116,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Photos - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section>
|
||||
{#if $isMultiSelectStoreState}
|
||||
<ControlAppBar
|
||||
|
@ -1,7 +1,8 @@
|
||||
export const prerender = false;
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
import { serverApi } from '@api';
|
||||
import { getThumbnailUrl } from '$lib/utils/asset-utils';
|
||||
import { serverApi, ThumbnailFormat } from '@api';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
@ -9,7 +10,20 @@ export const load: PageServerLoad = async ({ params }) => {
|
||||
|
||||
try {
|
||||
const { data: sharedLink } = await serverApi.shareApi.getMySharedLink({ params: { key } });
|
||||
return { sharedLink };
|
||||
|
||||
const assetCount = sharedLink.assets.length;
|
||||
const assetId = sharedLink.album?.albumThumbnailAssetId || sharedLink.assets[0]?.id;
|
||||
|
||||
return {
|
||||
sharedLink,
|
||||
meta: {
|
||||
title: sharedLink.album ? sharedLink.album.albumName : 'Public Share',
|
||||
description: sharedLink.description || `${assetCount} shared photos & videos.`,
|
||||
imageUrl: assetId
|
||||
? getThumbnailUrl(assetId, ThumbnailFormat.Webp, sharedLink.key)
|
||||
: 'feature-panel.png'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw error(404, {
|
||||
message: 'Invalid shared link'
|
||||
|
@ -1,22 +1,20 @@
|
||||
<script lang="ts">
|
||||
import AlbumViewer from '$lib/components/album-page/album-viewer.svelte';
|
||||
import { AlbumResponseDto } from '../../../api';
|
||||
import { AlbumResponseDto } from '@api';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const { sharedLink } = data;
|
||||
|
||||
let album: AlbumResponseDto | null = null;
|
||||
if (data.sharedLink.album) {
|
||||
album = { ...data.sharedLink.album, assets: data.sharedLink.assets };
|
||||
if (sharedLink.album) {
|
||||
album = { ...sharedLink.album, assets: sharedLink.assets };
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.sharedLink.album?.albumName || 'Public Shared'} - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if album}
|
||||
<div class="immich-scrollbar">
|
||||
<AlbumViewer {album} sharedLink={data.sharedLink} />
|
||||
<AlbumViewer {album} {sharedLink} />
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -15,7 +15,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
|
||||
return {
|
||||
user: user,
|
||||
sharedAlbums: sharedAlbums
|
||||
sharedAlbums,
|
||||
meta: {
|
||||
title: 'Albums'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, '/auth/login');
|
||||
|
@ -33,10 +33,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Albums - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section>
|
||||
<NavigationBar user={data.user} shouldShowUploadButton={false} />
|
||||
</section>
|
||||
|
@ -10,7 +10,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
}
|
||||
|
||||
return {
|
||||
user
|
||||
user,
|
||||
meta: {
|
||||
title: 'Shared Links'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, '/auth/login');
|
||||
|
@ -67,10 +67,6 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Shared links - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<ControlAppBar backIcon={ArrowLeft} on:close-button-click={() => goto('/sharing')}>
|
||||
<svelte:fragment slot="leading">Shared links</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
|
@ -10,7 +10,10 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
}
|
||||
|
||||
return {
|
||||
user: user
|
||||
user,
|
||||
meta: {
|
||||
title: 'Settings'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, '/auth/login');
|
||||
|
@ -7,10 +7,6 @@
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Settings - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
<section>
|
||||
<NavigationBar user={data.user} shouldShowUploadButton={false} />
|
||||
</section>
|
||||
|
BIN
web/static/feature-panel.png
Normal file
BIN
web/static/feature-panel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Loading…
Reference in New Issue
Block a user