Add hidden, favorite options to bulk uploads
This commit is contained in:
parent
7127bdf354
commit
0f0d9a32e3
@ -46,14 +46,12 @@ export default function ComponentsPage() {
|
||||
'*:inline-flex *:gap-1 [&_input]:-translate-y-0.5',
|
||||
)}>
|
||||
<FieldSetWithStatus
|
||||
id="grid"
|
||||
label="Grid"
|
||||
type="checkbox"
|
||||
value={shouldShowBaselineGrid ? 'true' : 'false'}
|
||||
onChange={e => setShouldShowBaselineGrid?.(e === 'true')}
|
||||
/>
|
||||
<FieldSetWithStatus
|
||||
id="components"
|
||||
label="Components"
|
||||
type="checkbox"
|
||||
value={debugComponents ? 'true' : 'false'}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache';
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import { getUniqueTagsCached, getUniqueRecipesCached } from '@/photo/cache';
|
||||
import { getUniqueTagsCached } from '@/photo/cache';
|
||||
import AdminUploadsClient from '@/admin/AdminUploadsClient';
|
||||
import { redirect } from 'next/navigation';
|
||||
import { PATH_ADMIN_PHOTOS } from '@/app/paths';
|
||||
@ -10,7 +10,6 @@ export const maxDuration = 60;
|
||||
export default async function AdminUploadsPage() {
|
||||
const urls = await getStorageUploadUrlsNoStore();
|
||||
const uniqueTags = await getUniqueTagsCached();
|
||||
const uniqueRecipes = await getUniqueRecipesCached();
|
||||
|
||||
if (urls.length === 0) {
|
||||
redirect(PATH_ADMIN_PHOTOS);
|
||||
@ -21,7 +20,6 @@ export default async function AdminUploadsPage() {
|
||||
<AdminUploadsClient {...{
|
||||
urls,
|
||||
uniqueTags,
|
||||
uniqueRecipes,
|
||||
}} />}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -43,11 +43,14 @@ export default function AdminBatchUploadActions({
|
||||
}) {
|
||||
const { updateAdminData } = useAppState();
|
||||
|
||||
const [buttonText, setButtonText] = useState('Add All Uploads');
|
||||
const [showTags, setShowTags] = useState(false);
|
||||
const [showBulkSettings, setShowBulkSettings] = useState(false);
|
||||
const [tags, setTags] = useState('');
|
||||
const [actionErrorMessage, setActionErrorMessage] = useState('');
|
||||
const [favorite, setFavorite] = useState('false');
|
||||
const [hidden, setHidden] = useState('false');
|
||||
const [tagErrorMessage, setTagErrorMessage] = useState('');
|
||||
|
||||
const [buttonText, setButtonText] = useState('Add All Uploads');
|
||||
const [actionErrorMessage, setActionErrorMessage] = useState('');
|
||||
const [addingProgress, setAddingProgress] = useState<number>();
|
||||
const [isAddingComplete, setIsAddingComplete] = useState(false);
|
||||
|
||||
@ -58,7 +61,11 @@ export default function AdminBatchUploadActions({
|
||||
try {
|
||||
const stream = await addAllUploadsAction({
|
||||
uploadUrls,
|
||||
tags: showTags ? tags : undefined,
|
||||
...showBulkSettings && {
|
||||
tags,
|
||||
favorite,
|
||||
hidden,
|
||||
},
|
||||
takenAtLocal: generateLocalPostgresString(),
|
||||
takenAtNaiveLocal: generateLocalNaivePostgresString(),
|
||||
shouldRevalidateAllKeysAndPaths: isFinalBatch,
|
||||
@ -116,29 +123,43 @@ export default function AdminBatchUploadActions({
|
||||
'grow',
|
||||
tagErrorMessage ? 'text-error' : 'text-main',
|
||||
)}>
|
||||
{showTags
|
||||
? tagErrorMessage || 'Add tags to all uploads'
|
||||
{showBulkSettings
|
||||
? tagErrorMessage || 'Apply to all uploads'
|
||||
: `Found ${storageUrls.length} uploads`}
|
||||
</div>
|
||||
<FieldSetWithStatus
|
||||
id="show-tags"
|
||||
label="Apply tags"
|
||||
label="Apply Bulk Settings"
|
||||
type="checkbox"
|
||||
value={showTags ? 'true' : 'false'}
|
||||
onChange={value => setShowTags(value === 'true')}
|
||||
value={showBulkSettings ? 'true' : 'false'}
|
||||
onChange={value => setShowBulkSettings(value === 'true')}
|
||||
readOnly={isAdding}
|
||||
/>
|
||||
</div>
|
||||
{showTags && !actionErrorMessage &&
|
||||
<PhotoTagFieldset
|
||||
tags={tags}
|
||||
tagOptions={uniqueTags}
|
||||
onChange={setTags}
|
||||
onError={setTagErrorMessage}
|
||||
readOnly={isAdding}
|
||||
openOnLoad
|
||||
hideLabel
|
||||
/>}
|
||||
{showBulkSettings && !actionErrorMessage &&
|
||||
<div className="space-y-3">
|
||||
<PhotoTagFieldset
|
||||
label="Tags"
|
||||
tags={tags}
|
||||
tagOptions={uniqueTags}
|
||||
onChange={setTags}
|
||||
onError={setTagErrorMessage}
|
||||
readOnly={isAdding}
|
||||
/>
|
||||
<FieldSetWithStatus
|
||||
label="Favorite"
|
||||
type="checkbox"
|
||||
value={favorite}
|
||||
onChange={setFavorite}
|
||||
readOnly={isAdding}
|
||||
/>
|
||||
<FieldSetWithStatus
|
||||
label="Hidden"
|
||||
type="checkbox"
|
||||
value={hidden}
|
||||
onChange={setHidden}
|
||||
readOnly={isAdding}
|
||||
/>
|
||||
</div>}
|
||||
<div className="space-y-2">
|
||||
<ProgressButton
|
||||
primary
|
||||
|
||||
@ -35,7 +35,6 @@ export default function AdminRecipeForm({
|
||||
className="space-y-8"
|
||||
>
|
||||
<FieldSetWithStatus
|
||||
id="updatedRecipeRaw"
|
||||
label="New Recipe Name"
|
||||
value={updatedRecipeRaw}
|
||||
onChange={setUpdatedRecipeRaw}
|
||||
|
||||
@ -35,7 +35,6 @@ export default function AdminTagForm({
|
||||
className="space-y-8"
|
||||
>
|
||||
<FieldSetWithStatus
|
||||
id="updatedTagRaw"
|
||||
label="New Tag Name"
|
||||
value={updatedTagRaw}
|
||||
onChange={setUpdatedTagRaw}
|
||||
|
||||
@ -5,7 +5,6 @@ import AdminBatchUploadActions from './AdminBatchUploadActions';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Tags } from '@/tag';
|
||||
import AdminUploadsTable from './AdminUploadsTable';
|
||||
import { Recipes } from '@/recipe';
|
||||
|
||||
export type UrlAddStatus = StorageListItem & {
|
||||
status?: 'waiting' | 'adding' | 'added'
|
||||
@ -19,7 +18,6 @@ export default function AdminUploadsClient({
|
||||
}: {
|
||||
urls: StorageListResponse
|
||||
uniqueTags?: Tags
|
||||
uniqueRecipes?: Recipes
|
||||
}) {
|
||||
const [isAdding, setIsAdding] = useState(false);
|
||||
const [urlAddStatuses, setUrlAddStatuses] = useState<UrlAddStatus[]>(urls);
|
||||
|
||||
@ -15,7 +15,6 @@ export default function PhotoTagFieldset(props: {
|
||||
'tagOptions'
|
||||
>>) {
|
||||
const {
|
||||
id,
|
||||
tags,
|
||||
tagOptions,
|
||||
onChange,
|
||||
@ -42,7 +41,7 @@ export default function PhotoTagFieldset(props: {
|
||||
<FieldSetWithStatus
|
||||
{...rest}
|
||||
inputRef={ref}
|
||||
id={id ?? 'tags'}
|
||||
label="Tags"
|
||||
value={tags}
|
||||
tagOptions={convertTagsForForm(tagOptions)}
|
||||
onChange={tags => {
|
||||
|
||||
@ -7,9 +7,10 @@ import { clsx } from 'clsx/lite';
|
||||
import { FieldSetType, AnnotatedTag } from '@/photo/form';
|
||||
import TagInput from './TagInput';
|
||||
import { FiChevronDown } from 'react-icons/fi';
|
||||
import { parameterize } from '@/utility/string';
|
||||
|
||||
export default function FieldSetWithStatus({
|
||||
id,
|
||||
id: _id,
|
||||
label,
|
||||
note,
|
||||
error,
|
||||
@ -34,8 +35,8 @@ export default function FieldSetWithStatus({
|
||||
hideLabel,
|
||||
checkboxAccessory,
|
||||
}: {
|
||||
id: string
|
||||
label?: string
|
||||
id?: string
|
||||
label: string
|
||||
note?: string
|
||||
error?: string
|
||||
value: string
|
||||
@ -59,6 +60,8 @@ export default function FieldSetWithStatus({
|
||||
hideLabel?: boolean
|
||||
checkboxAccessory?: React.ReactNode
|
||||
}) {
|
||||
const id = _id || parameterize(label);
|
||||
|
||||
const { pending } = useFormStatus();
|
||||
|
||||
const renderInput =
|
||||
@ -66,13 +69,13 @@ export default function FieldSetWithStatus({
|
||||
ref={inputRef}
|
||||
id={id}
|
||||
name={id}
|
||||
type={type}
|
||||
value={value}
|
||||
checked={type === 'checkbox' ? value === 'true' : undefined}
|
||||
placeholder={placeholder}
|
||||
onChange={e => onChange?.(type === 'checkbox'
|
||||
? e.target.value === 'true' ? 'false' : 'true'
|
||||
: e.target.value)}
|
||||
type={type}
|
||||
spellCheck={spellCheck}
|
||||
autoComplete="off"
|
||||
autoCapitalize={!capitalize ? 'off' : undefined}
|
||||
|
||||
@ -89,12 +89,16 @@ export const createPhotoAction = async (formData: FormData) =>
|
||||
export const addAllUploadsAction = async ({
|
||||
uploadUrls,
|
||||
tags,
|
||||
favorite,
|
||||
hidden,
|
||||
takenAtLocal,
|
||||
takenAtNaiveLocal,
|
||||
shouldRevalidateAllKeysAndPaths = true,
|
||||
}: {
|
||||
uploadUrls: string[]
|
||||
tags?: string
|
||||
favorite?: string
|
||||
hidden?: string
|
||||
takenAtLocal: string
|
||||
takenAtNaiveLocal: string
|
||||
shouldRevalidateAllKeysAndPaths?: boolean
|
||||
@ -106,7 +110,7 @@ export const addAllUploadsAction = async ({
|
||||
let currentUploadUrl = '';
|
||||
let progress = 0;
|
||||
|
||||
const stream = createStreamableValue<UrlAddStatus>();
|
||||
const stream = createStreamableValue<Omit<UrlAddStatus, 'fileName'>>();
|
||||
|
||||
const streamUpdate = (
|
||||
statusMessage: string,
|
||||
@ -157,6 +161,8 @@ export const addAllUploadsAction = async ({
|
||||
title,
|
||||
caption,
|
||||
tags: tags || aiTags,
|
||||
hidden,
|
||||
favorite,
|
||||
semanticDescription,
|
||||
takenAt: formDataFromExif.takenAt || takenAtLocal,
|
||||
takenAtNaive: formDataFromExif.takenAtNaive || takenAtNaiveLocal,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user