* Make /db top-level module * Create Album type * Pin pnpm version * Generalize query modules * Finalize album postgres data type * Remove temp albums prop * Create basic album primitives * Fix temporary album bugs * Add albums to sidebar * Disambiguate string date utilities * Localize album language * Add album join option to core photo queries * Tweak album icon placement * Add album photo detail page * Refine Album data model * Display album subhead when available * Generate album og images * Finalize album share modal * Add albums to sitemap * Statically pre-render albums * Display tags on albums * Add albums to cmd-k menu * Handle album tag overflow * Stop truncating album subheads * Create core admin album views * Make albums editable * Create/edit albums on photo save, add delete album
103 lines
2.7 KiB
TypeScript
103 lines
2.7 KiB
TypeScript
import { PARAM_UPLOAD_TITLE, PATH_ADMIN } from '@/app/path';
|
|
import { extractImageDataFromBlobPath } from '@/photo/server';
|
|
import { redirect } from 'next/navigation';
|
|
import {
|
|
getUniqueFilmsCached,
|
|
getUniqueRecipesCached,
|
|
getUniqueTagsCached,
|
|
} from '@/photo/cache';
|
|
import UploadPageClient from '@/photo/UploadPageClient';
|
|
import {
|
|
AI_TEXT_AUTO_GENERATED_FIELDS,
|
|
AI_CONTENT_GENERATION_ENABLED,
|
|
BLUR_ENABLED,
|
|
} from '@/app/config';
|
|
import ErrorNote from '@/components/ErrorNote';
|
|
import { getRecipeTitleForData } from '@/photo/query';
|
|
import { getAlbumsWithMeta } from '@/album/query';
|
|
|
|
export const maxDuration = 60;
|
|
|
|
interface Params {
|
|
params: Promise<{ uploadPath: string }>
|
|
searchParams: Promise<Record<string, string | string[] | undefined>>
|
|
}
|
|
|
|
export default async function UploadPage({ params, searchParams }: Params) {
|
|
const uploadPath = (await params).uploadPath;
|
|
const title = (await searchParams)[PARAM_UPLOAD_TITLE];
|
|
|
|
const {
|
|
blobId,
|
|
formDataFromExif,
|
|
imageResizedBase64: imageThumbnailBase64,
|
|
shouldStripGpsData,
|
|
error,
|
|
} = await extractImageDataFromBlobPath(uploadPath, {
|
|
includeInitialPhotoFields: true,
|
|
generateBlurData: BLUR_ENABLED,
|
|
generateResizedImage: AI_CONTENT_GENERATION_ENABLED,
|
|
});
|
|
|
|
const isDataMissing =
|
|
!formDataFromExif ||
|
|
(AI_CONTENT_GENERATION_ENABLED && !imageThumbnailBase64);
|
|
|
|
if (isDataMissing && !error) {
|
|
// Only redirect if there's no error to report
|
|
redirect(PATH_ADMIN);
|
|
}
|
|
|
|
const [
|
|
albums,
|
|
uniqueTags,
|
|
uniqueRecipes,
|
|
uniqueFilms,
|
|
recipeTitle,
|
|
] = await Promise.all([
|
|
getAlbumsWithMeta(),
|
|
getUniqueTagsCached(),
|
|
getUniqueRecipesCached(),
|
|
getUniqueFilmsCached(),
|
|
formDataFromExif?.recipeData && formDataFromExif.film
|
|
? getRecipeTitleForData(
|
|
formDataFromExif.recipeData,
|
|
formDataFromExif.film,
|
|
)
|
|
: undefined,
|
|
]);
|
|
|
|
const hasAiTextGeneration = AI_CONTENT_GENERATION_ENABLED;
|
|
let textFieldsToAutoGenerate = AI_TEXT_AUTO_GENERATED_FIELDS;
|
|
|
|
if (formDataFromExif) {
|
|
if (recipeTitle) {
|
|
formDataFromExif.recipeTitle = recipeTitle;
|
|
}
|
|
if (typeof title === 'string') {
|
|
formDataFromExif.title = title;
|
|
textFieldsToAutoGenerate = textFieldsToAutoGenerate
|
|
.filter(field => field !== 'title');
|
|
}
|
|
}
|
|
|
|
return (
|
|
!isDataMissing
|
|
? <UploadPageClient {...{
|
|
blobId,
|
|
formDataFromExif,
|
|
albums,
|
|
uniqueTags,
|
|
uniqueRecipes,
|
|
uniqueFilms,
|
|
hasAiTextGeneration,
|
|
textFieldsToAutoGenerate,
|
|
imageThumbnailBase64,
|
|
shouldStripGpsData,
|
|
}} />
|
|
: <ErrorNote>
|
|
{error ?? 'Unknown error'}
|
|
</ErrorNote>
|
|
);
|
|
};
|