Streamline url add api

This commit is contained in:
Sam Becker 2024-07-06 14:04:03 -05:00
parent 3b5b8fc559
commit c2f9ddf6b6
4 changed files with 36 additions and 40 deletions

View File

@ -21,7 +21,7 @@ import { useRouter } from 'next/navigation';
import { Dispatch, SetStateAction, useRef, useState } from 'react';
import { BiCheckCircle, BiImageAdd } from 'react-icons/bi';
import ProgressButton from '@/components/primitives/ProgressButton';
import { AddedUrlStatus } from './AdminUploadsClient';
import { UrlAddStatus } from './AdminUploadsClient';
const UPLOAD_BATCH_SIZE = 4;
@ -30,13 +30,13 @@ export default function AdminAddAllUploads({
uniqueTags,
isAdding,
setIsAdding,
setAddedUrlStatuses,
setUrlAddStatuses,
}: {
storageUrls: string[]
uniqueTags?: Tags
isAdding: boolean
setIsAdding: (isAdding: boolean) => void
setAddedUrlStatuses: Dispatch<SetStateAction<AddedUrlStatus[]>>
setUrlAddStatuses: Dispatch<SetStateAction<UrlAddStatus[]>>
}) {
const divRef = useRef<HTMLDivElement>(null);
@ -64,7 +64,7 @@ export default function AdminAddAllUploads({
? `Adding 1 of ${storageUrls.length}`
: `Adding ${addedUploadCount.current + 1} of ${storageUrls.length}`
);
setAddedUrlStatuses(current => {
setUrlAddStatuses(current => {
const update = current.map(status =>
status.url === data?.url
? {
@ -166,9 +166,10 @@ export default function AdminAddAllUploads({
// eslint-disable-next-line max-len
if (confirm(`Are you sure you want to add all ${storageUrls.length} uploads?`)) {
setIsAdding(true);
setAddedUrlStatuses(current => current.map((url, index) =>
index === 0 ? { ...url, status: 'adding' } : url
));
setUrlAddStatuses(current => current.map((url, index) => ({
...url,
status: index === 0 ? 'adding' : 'waiting',
})));
const uploadsToAdd = storageUrls.slice();
try {
while (uploadsToAdd.length > 0) {

View File

@ -2,11 +2,11 @@
import { StorageListResponse } from '@/services/storage';
import AdminAddAllUploads from './AdminAddAllUploads';
import { useState } from 'react';
import { useMemo, useState } from 'react';
import { Tags } from '@/tag';
import AdminUploadsTable from './AdminUploadsTable';
export type AddedUrlStatus = {
export type UrlAddStatus = {
url: string
uploadedAt?: Date
status?: 'waiting' | 'adding' | 'added'
@ -22,24 +22,21 @@ export default function AdminUploadsClient({
uniqueTags?: Tags
}) {
const [isAdding, setIsAdding] = useState(false);
const [addedUrlStatuses, setAddedUrlStatuses] =
useState<AddedUrlStatus[]>(urls.map(({ url, uploadedAt }) => ({
url,
uploadedAt,
status: 'waiting',
})));
const [urlAddStatuses, setUrlAddStatuses] = useState<UrlAddStatus[]>(urls);
const storageUrls = useMemo(() => urls.map(({ url }) => url), [urls]);
return (
<div className="space-y-4">
{urls.length > 1 &&
<AdminAddAllUploads
storageUrls={urls.map(({ url }) => url)}
uniqueTags={uniqueTags}
isAdding={isAdding}
setIsAdding={setIsAdding}
setAddedUrlStatuses={setAddedUrlStatuses}
/>}
<AdminUploadsTable {...{ isAdding, urls: addedUrlStatuses }} />
<AdminAddAllUploads {...{
storageUrls,
uniqueTags,
isAdding,
setIsAdding,
setUrlAddStatuses,
}} />}
<AdminUploadsTable {...{ isAdding, urlAddStatuses }} />
</div>
);
}

View File

@ -11,21 +11,21 @@ import AddButton from './AddButton';
import FormWithConfirm from '@/components/FormWithConfirm';
import { deleteBlobPhotoAction } from '@/photo/actions';
import DeleteButton from './DeleteButton';
import { AddedUrlStatus } from './AdminUploadsClient';
import { UrlAddStatus } from './AdminUploadsClient';
import ResponsiveDate from '@/components/ResponsiveDate';
export default function AdminUploadsTable({
isAdding,
urls,
urlAddStatuses,
}: {
isAdding?: boolean
urls: AddedUrlStatus[]
urlAddStatuses: UrlAddStatus[]
}) {
const isComplete = urls.every(({ status }) => status === 'added');
const isComplete = urlAddStatuses.every(({ status }) => status === 'added');
return (
<div className="space-y-4">
{urls.map(({ url, status, statusMessage, uploadedAt }) => {
{urlAddStatuses.map(({ url, status, statusMessage, uploadedAt }) => {
const addUploadPath = pathForAdminUploadUrl(url);
return <div key={url}>
<div className={clsx(
@ -33,14 +33,12 @@ export default function AdminUploadsTable({
)}>
<motion.div
className="flex items-center grow gap-2"
animate={isAdding
animate={isAdding && !isComplete
? {
opacity: status === 'adding' || isComplete ? 1 : 0.5,
translateX: isComplete
? 0
: status === 'adding' || isComplete ? -4 : 4,
translateX: status === 'adding' ? -4 : 4,
opacity: status === 'adding' ? 1 : 0.5,
}
: { opacity: 1, translateX: 0 }}
: { translateX: 0, opacity: 1 }}
>
<ImageSmall
src={url}
@ -55,7 +53,7 @@ export default function AdminUploadsTable({
<div className="text-dim overflow-hidden text-ellipsis">
{isAdding || isComplete
? status === 'added'
? 'Complete'
? 'Added'
: status === 'adding'
? statusMessage ?? 'Adding ...'
: 'Waiting'
@ -88,7 +86,7 @@ export default function AdminUploadsTable({
<input
type="hidden"
name="redirectToPhotos"
value={urls.length < 2 ? 'true' : 'false'}
value={urlAddStatuses.length < 2 ? 'true' : 'false'}
readOnly
/>
<input

View File

@ -46,7 +46,7 @@ import {
import { generateAiImageQueries } from './ai/server';
import { createStreamableValue } from 'ai/rsc';
import { convertUploadToPhoto } from './storage';
import { AddedUrlStatus } from '@/admin/AdminUploadsClient';
import { UrlAddStatus } from '@/admin/AdminUploadsClient';
// Private actions
@ -88,11 +88,11 @@ export const addAllUploadsAction = async ({
let currentUploadUrl = '';
let progress = 0;
const stream = createStreamableValue<AddedUrlStatus>();
const stream = createStreamableValue<UrlAddStatus>();
const streamUpdate = (
statusMessage: string,
status: AddedUrlStatus['status'] = 'adding',
status: UrlAddStatus['status'] = 'adding',
) =>
stream.update({
url: currentUploadUrl,
@ -144,7 +144,7 @@ export const addAllUploadsAction = async ({
takenAtNaive: photoFormExif.takenAtNaive || takenAtNaiveLocal,
};
streamUpdate('Moving upload to photo storage');
streamUpdate('Transferring to photo storage');
const updatedUrl = await convertUploadToPhoto({
urlOrigin: url,