Make photo titles optional

This commit is contained in:
Sam Becker 2023-09-09 18:17:11 -05:00
parent 8f984e69ef
commit c4044801a1
11 changed files with 36 additions and 22 deletions

View File

@ -63,7 +63,10 @@ export default async function AdminPage() {
href={routeForPhoto(photo)}
className="grow flex items-center gap-2"
>
{photo.title}
{photo.title ||
<span className="text-gray-400 dark:text-gray-500">
Untitled
</span>}
{photo.priorityOrder !== null &&
<span className={cc(
'text-xs leading-none px-1.5 py-1 rounded-sm',
@ -101,7 +104,7 @@ function AdminGrid ({
title: string,
children: ReactNode,
}) {
return <div className="space-y-2">
return <div className="space-y-4">
<div className="font-bold">
{title}
</div>

View File

@ -2,7 +2,11 @@ import { PropsWithChildren } from 'react';
import AnimateItems from '@/components/AnimateItems';
import PhotoLinks from '@/photo/PhotoLinks';
import SiteGrid from '@/components/SiteGrid';
import { ogImageDescriptionForPhoto, ogImageUrlForPhoto } from '@/photo';
import {
ogImageDescriptionForPhoto,
ogImageUrlForPhoto,
titleForPhoto,
} from '@/photo';
import PhotoGrid from '@/photo/PhotoGrid';
import PhotoLarge from '@/photo/PhotoLarge';
import { cc } from '@/utility/css';
@ -24,7 +28,7 @@ export async function generateMetadata(
if (!photo) { return {}; }
const title = photo.title;
const title = titleForPhoto(photo);
const description = ogImageDescriptionForPhoto(photo);
const images = ogImageUrlForPhoto(photo);

View File

@ -72,9 +72,8 @@ export default function PhotoForm({
};
}, [url, type]);
const isFormValid =
Boolean(formData.blurData) &&
Boolean(formData.title);
const isFormValid = FORM_METADATA_ENTRIES.every(([key, { required }]) =>
!required || Boolean(formData[key]));
return (
<div className="space-y-8 max-w-[38rem]">

View File

@ -1,4 +1,4 @@
import { Photo } from '.';
import { Photo, titleForPhoto } from '.';
import SiteGrid from '@/components/SiteGrid';
import ImageLarge from '@/components/ImageLarge';
import { cc } from '@/utility/css';
@ -30,7 +30,7 @@ export default function PhotoLarge({
contentMain={
<ImageLarge
className="w-full"
alt={photo.title ?? 'Photo'}
alt={titleForPhoto(photo)}
href={routeForPhoto(photo)}
src={photo.url}
aspectRatio={photo.aspectRatio}
@ -50,7 +50,7 @@ export default function PhotoLarge({
href={routeForPhoto(photo)}
className="font-bold uppercase"
>
{photo.title}
{titleForPhoto(photo)}
</Link>
<div className="uppercase">
{photo.make} {photo.model}

View File

@ -1,7 +1,12 @@
'use client';
import { useEffect, useState } from 'react';
import { Photo, ogImageDescriptionForPhoto, ogImageUrlForPhoto } from '@/photo';
import {
Photo,
ogImageDescriptionForPhoto,
ogImageUrlForPhoto,
titleForPhoto,
} from '@/photo';
import { cc } from '@/utility/css';
import Link from 'next/link';
import { BiError } from 'react-icons/bi';
@ -111,7 +116,7 @@ export default function PhotoOGTile({
'border-t border-gray-200 dark:border-gray-800',
)}>
<div className="text-gray-800 dark:text-white font-medium">
{photo.title}
{titleForPhoto(photo)}
</div>
<div className="text-gray-500">
{ogImageDescriptionForPhoto(photo)}

View File

@ -1,4 +1,4 @@
import { Photo } from '.';
import { Photo, titleForPhoto } from '.';
import ImageSmall from '@/components/ImageSmall';
import Link from 'next/link';
import { cc } from '@/utility/css';
@ -24,7 +24,7 @@ export default function PhotoSmall({
aspectRatio={photo.aspectRatio}
blurData={photo.blurData}
className="w-full"
alt={photo.title ?? 'Photo'}
alt={titleForPhoto(photo)}
/>
</Link>
);

View File

@ -1,4 +1,4 @@
import { Photo } from '.';
import { Photo, titleForPhoto } from '.';
import ImageTiny from '@/components/ImageTiny';
import Link from 'next/link';
import { cc } from '@/utility/css';
@ -27,7 +27,7 @@ export default function PhotoTiny({
src={photo.url}
aspectRatio={photo.aspectRatio}
blurData={photo.blurData}
alt={photo.title ?? 'Photo'}
alt={titleForPhoto(photo)}
/>
</Link>
);

View File

@ -18,13 +18,13 @@ type FormMeta = {
};
const FORM_METADATA: Record<keyof PhotoFormData, FormMeta> = {
title: { label: 'title', required: true },
title: { label: 'title' },
id: { label: 'id', readOnly: true, hideIfEmpty: true },
idShort: { label: 'short id', readOnly: true, hideIfEmpty: true },
url: { label: 'url', readOnly: true },
extension: { label: 'extension', readOnly: true },
aspectRatio: { label: 'aspect ratio', readOnly: true },
blurData: { label: 'blur data', readOnly: true },
blurData: { label: 'blur data', readOnly: true, required: true },
make: { label: 'camera make' },
model: { label: 'camera model' },
focalLength: { label: 'focal length' },

View File

@ -1,5 +1,5 @@
import { getNextImageUrlForRequest } from '@/utility/image';
import { Photo } from '..';
import { Photo, titleForPhoto } from '..';
const IMAGE_WIDTH = 400;
@ -38,7 +38,7 @@ export default function PhotoGridImageResponse({
request,
IMAGE_WIDTH,
)}
alt={photo.title}
alt={titleForPhoto(photo)}
width={IMAGE_WIDTH}
height={IMAGE_WIDTH / photo.aspectRatio}
style={{

View File

@ -1,4 +1,4 @@
import { Photo } from '..';
import { Photo, titleForPhoto } from '..';
import { getNextImageUrlForRequest } from '@/utility/image';
import { formatModelShort } from '@/utility/exif';
import { AiFillApple } from 'react-icons/ai';
@ -34,7 +34,7 @@ export default function PhotoOGImageResponse({
)}
width={width}
height={width / photo.aspectRatio}
alt={photo.title}
alt={titleForPhoto(photo)}
/>
<div style={{
display: 'flex',

View File

@ -140,3 +140,6 @@ export const translatePhotoId = (shortId: string) => {
const id = PHOTO_ID_FORWARDING_TABLE[shortId] || shortId;
return id.length === 22 ? translator.toUUID(id) : id;
};
export const titleForPhoto = (photo: Photo) =>
photo.title || 'Untitled';