Merge branch 'main' into static

This commit is contained in:
Sam Becker 2024-03-12 15:39:16 -05:00
commit ed840adb91
8 changed files with 472 additions and 606 deletions

View File

@ -9,20 +9,20 @@
"analyze": "ANALYZE=true next build"
},
"dependencies": {
"@aws-sdk/client-s3": "3.525.0",
"@aws-sdk/s3-request-presigner": "3.525.0",
"@next/bundle-analyzer": "14.1.0",
"@aws-sdk/client-s3": "3.529.1",
"@aws-sdk/s3-request-presigner": "3.529.1",
"@next/bundle-analyzer": "14.1.3",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.7",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.24",
"@types/react": "18.2.61",
"@types/react-dom": "18.2.19",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"@types/node": "^20.11.26",
"@types/react": "18.2.65",
"@types/react-dom": "18.2.21",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vercel/analytics": "^1.2.2",
"@vercel/blob": "^0.22.1",
"@vercel/postgres": "0.7.2",
@ -30,16 +30,16 @@
"autoprefixer": "10.4.18",
"camelcase-keys": "^9.1.3",
"clsx": "^2.1.0",
"cmdk": "^0.2.1",
"date-fns": "^3.3.1",
"cmdk": "^1.0.0",
"date-fns": "^3.4.0",
"eslint": "8.57.0",
"eslint-config-next": "14.1.1",
"eslint-config-next": "14.1.3",
"exifr": "^7.1.3",
"framer-motion": "^11.0.8",
"framer-motion": "^11.0.12",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"nanoid": "^5.0.6",
"next": "14.2.0-canary.16",
"next": "14.2.0-canary.18",
"next-auth": "5.0.0-beta.13",
"next-themes": "^0.2.1",
"postcss": "8.4.35",
@ -49,7 +49,7 @@
"sonner": "^1.4.3",
"tailwindcss": "3.4.1",
"ts-exif-parser": "^0.2.2",
"typescript": "5.3.3",
"typescript": "5.4.2",
"use-debounce": "^10.0.0"
}
}

966
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
import PhotoForm from '@/photo/form/PhotoForm';
import AdminChildPage from '@/components/AdminChildPage';
import { PATH_ADMIN, PATH_ADMIN_UPLOADS } from '@/site/paths';
import { PATH_ADMIN } from '@/site/paths';
import { extractExifDataFromBlobPath } from '@/photo/server';
import { redirect } from 'next/navigation';
import { getUniqueTagsCached } from '@/photo/cache';
import UploadPageClient from '@/photo/UploadPageClient';
interface Params {
params: { uploadPath: string }
@ -20,15 +19,6 @@ export default async function UploadPage({ params: { uploadPath } }: Params) {
if (!photoFormExif) { redirect(PATH_ADMIN); }
return (
<AdminChildPage
backPath={PATH_ADMIN_UPLOADS}
backLabel="Uploads"
breadcrumb={blobId}
>
<PhotoForm
initialPhotoForm={photoFormExif}
uniqueTags={uniqueTags}
/>
</AdminChildPage>
<UploadPageClient {...{ blobId, photoFormExif, uniqueTags }} />
);
};

View File

@ -4,18 +4,21 @@ import { FiArrowLeft } from 'react-icons/fi';
import SiteGrid from './SiteGrid';
import { clsx } from 'clsx/lite';
import Badge from './Badge';
import Spinner from './Spinner';
function AdminChildPage({
backPath,
backLabel,
breadcrumb,
accessory,
isLoading,
children,
}: {
backPath?: string
backLabel?: string
breadcrumb?: ReactNode
accessory?: ReactNode
isLoading?: boolean
children: ReactNode,
}) {
return (
@ -42,10 +45,14 @@ function AdminChildPage({
{breadcrumb &&
<>
<span>/</span>
<Badge>
{breadcrumb}
</Badge>
<span className={clsx(isLoading && 'opacity-50')}>
<Badge>
{breadcrumb}
</Badge>
</span>
</>}
{isLoading &&
<Spinner />}
</div>
{accessory &&
<div>{accessory}</div>}

View File

@ -10,6 +10,7 @@ interface Props extends HTMLProps<HTMLButtonElement> {
icon?: JSX.Element
styleAsLink?: boolean
spinnerColor?: SpinnerColor
onFormStatusChange?: (pending: boolean) => void
onFormSubmitToastMessage?: string
}
@ -17,6 +18,7 @@ export default function SubmitButtonWithStatus({
icon,
styleAsLink,
spinnerColor,
onFormStatusChange,
onFormSubmitToastMessage,
children,
disabled,
@ -24,8 +26,8 @@ export default function SubmitButtonWithStatus({
type: _type,
...buttonProps
}: Props) {
const { pending } = useFormStatus();
const pendingPrevious = useRef(pending);
useEffect(() => {
@ -39,6 +41,10 @@ export default function SubmitButtonWithStatus({
pendingPrevious.current = pending;
}, [pending, onFormSubmitToastMessage]);
useEffect(() => {
onFormStatusChange?.(pending);
}, [onFormStatusChange, pending]);
return (
<button
type="submit"

View File

@ -11,6 +11,7 @@ import { areSimpleObjectsEqual } from '@/utility/object';
import IconGrSync from '@/site/IconGrSync';
import { getExifDataAction } from './actions';
import { TagsWithMeta } from '@/tag';
import { useState } from 'react';
export default function PhotoEditPageClient({
photo,
@ -26,6 +27,8 @@ export default function PhotoEditPageClient({
seedExifData,
);
const [pending, setIsPending] = useState(false);
const hasExifDataBeenFound = !areSimpleObjectsEqual(
updatedExifData,
seedExifData,
@ -47,6 +50,7 @@ export default function PhotoEditPageClient({
EXIF
</SubmitButtonWithStatus>
</form>}
isLoading={pending}
>
<PhotoForm
type="edit"
@ -55,6 +59,7 @@ export default function PhotoEditPageClient({
? updatedExifData
: undefined}
uniqueTags={uniqueTags}
onFormStatusChange={setIsPending}
/>
</AdminChildPage>
);

View File

@ -0,0 +1,35 @@
'use client';
import AdminChildPage from '@/components/AdminChildPage';
import { PATH_ADMIN_UPLOADS } from '@/site/paths';
import { PhotoFormData } from './form';
import { Tags } from '@/tag';
import PhotoForm from './form/PhotoForm';
import { useState } from 'react';
export default function UploadPageClient({
blobId,
photoFormExif,
uniqueTags,
}: {
blobId?: string
photoFormExif: Partial<PhotoFormData>
uniqueTags: Tags
}) {
const [pending, setIsPending] = useState(false);
return (
<AdminChildPage
backPath={PATH_ADMIN_UPLOADS}
backLabel="Uploads"
breadcrumb={blobId}
isLoading={pending}
>
<PhotoForm
initialPhotoForm={photoFormExif}
uniqueTags={uniqueTags}
onFormStatusChange={setIsPending}
/>
</AdminChildPage>
);
}

View File

@ -34,12 +34,14 @@ export default function PhotoForm({
type = 'create',
uniqueTags,
debugBlur,
onFormStatusChange,
}: {
initialPhotoForm: Partial<PhotoFormData>
updatedExifData?: Partial<PhotoFormData>
type?: 'create' | 'edit'
uniqueTags?: TagsWithMeta
debugBlur?: boolean
onFormStatusChange?: (pending: boolean) => void
}) {
const [formData, setFormData] =
useState<Partial<PhotoFormData>>(initialPhotoForm);
@ -206,7 +208,10 @@ export default function PhotoForm({
>
Cancel
</Link>
<SubmitButtonWithStatus disabled={!isFormValid(formData)}>
<SubmitButtonWithStatus
disabled={!isFormValid(formData)}
onFormStatusChange={onFormStatusChange}
>
{type === 'create' ? 'Create' : 'Update'}
</SubmitButtonWithStatus>
</div>