Streamline url add api
This commit is contained in:
parent
3b5b8fc559
commit
c2f9ddf6b6
@ -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) {
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user