Allow uploads from CMDK menu
This commit is contained in:
parent
20976aefa7
commit
ee98668727
@ -59,13 +59,7 @@ export default function AdminAppMenu({
|
|||||||
size={15}
|
size={15}
|
||||||
className="translate-x-[0.5px] translate-y-[0.5px]"
|
className="translate-x-[0.5px] translate-y-[0.5px]"
|
||||||
/>,
|
/>,
|
||||||
action: () => new Promise(resolve => {
|
action: startUpload,
|
||||||
if (startUpload) {
|
|
||||||
startUpload(() => resolve());
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
if (uploadsCount) {
|
if (uploadsCount) {
|
||||||
|
|||||||
@ -86,7 +86,7 @@ type CommandKItem = {
|
|||||||
annotation?: ReactNode
|
annotation?: ReactNode
|
||||||
annotationAria?: string
|
annotationAria?: string
|
||||||
path?: string
|
path?: string
|
||||||
action?: () => void | Promise<void>
|
action?: () => void | Promise<void | boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandKSection = {
|
type CommandKSection = {
|
||||||
@ -124,6 +124,7 @@ export default function CommandKClient({
|
|||||||
isUserSignedIn,
|
isUserSignedIn,
|
||||||
clearAuthStateAndRedirect,
|
clearAuthStateAndRedirect,
|
||||||
isCommandKOpen: isOpen,
|
isCommandKOpen: isOpen,
|
||||||
|
startUpload,
|
||||||
photosCountHidden,
|
photosCountHidden,
|
||||||
uploadsCount,
|
uploadsCount,
|
||||||
tagsCount,
|
tagsCount,
|
||||||
@ -151,19 +152,21 @@ export default function CommandKClient({
|
|||||||
|
|
||||||
const isOpenRef = useRef(isOpen);
|
const isOpenRef = useRef(isOpen);
|
||||||
|
|
||||||
|
// Manage action/path waiting state
|
||||||
|
const [keyWaiting, setKeyWaiting] = useState<string>();
|
||||||
const [isPending, startTransition] = useTransition();
|
const [isPending, startTransition] = useTransition();
|
||||||
const [keyPending, setKeyPending] = useState<string>();
|
const [isWaitingForAction, setIsWaitingForAction] = useState(false);
|
||||||
const shouldCloseAfterPending = useRef(false);
|
const isWaiting = isPending || isWaitingForAction;
|
||||||
|
const shouldCloseAfterWaiting = useRef(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPending) {
|
if (!isWaiting) {
|
||||||
setKeyPending(undefined);
|
setKeyWaiting(undefined);
|
||||||
if (shouldCloseAfterPending.current) {
|
if (shouldCloseAfterWaiting.current) {
|
||||||
setIsOpen?.(false);
|
setIsOpen?.(false);
|
||||||
shouldCloseAfterPending.current = false;
|
shouldCloseAfterWaiting.current = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [isPending, setIsOpen]);
|
}, [isWaiting, setIsOpen]);
|
||||||
|
|
||||||
// Raw query values
|
// Raw query values
|
||||||
const [queryLiveRaw, setQueryLive] = useState('');
|
const [queryLiveRaw, setQueryLive] = useState('');
|
||||||
@ -427,6 +430,11 @@ export default function CommandKClient({
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isUserSignedIn) {
|
if (isUserSignedIn) {
|
||||||
|
adminSection.items.push({
|
||||||
|
label: 'Upload Photos',
|
||||||
|
annotation: <IconLock narrow />,
|
||||||
|
action: startUpload,
|
||||||
|
});
|
||||||
if (uploadsCount) {
|
if (uploadsCount) {
|
||||||
adminSection.items.push({
|
adminSection.items.push({
|
||||||
label: `Uploads (${uploadsCount})`,
|
label: `Uploads (${uploadsCount})`,
|
||||||
@ -558,7 +566,6 @@ export default function CommandKClient({
|
|||||||
'max-h-48 sm:max-h-72',
|
'max-h-48 sm:max-h-72',
|
||||||
'mx-3 md:mx-4',
|
'mx-3 md:mx-4',
|
||||||
'pt-3 md:pt-4',
|
'pt-3 md:pt-4',
|
||||||
'pb-4 md:pb-5',
|
|
||||||
)} style={{
|
)} style={{
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
maskImage: 'linear-gradient(to bottom, transparent, black 20px, black calc(100% - 20px), transparent)',
|
maskImage: 'linear-gradient(to bottom, transparent, black 20px, black calc(100% - 20px), transparent)',
|
||||||
@ -613,14 +620,24 @@ export default function CommandKClient({
|
|||||||
keywords={keywords}
|
keywords={keywords}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
if (action) {
|
if (action) {
|
||||||
action();
|
const result = action();
|
||||||
if (!path) { setIsOpen?.(false); }
|
if (result instanceof Promise) {
|
||||||
|
setKeyWaiting(key);
|
||||||
|
setIsWaitingForAction(true);
|
||||||
|
result.then(shouldClose => {
|
||||||
|
shouldCloseAfterWaiting.current =
|
||||||
|
shouldClose === true;
|
||||||
|
setIsWaitingForAction(false);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (!path) { setIsOpen?.(false); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
if (path !== pathname) {
|
if (path !== pathname) {
|
||||||
setKeyPending(key);
|
setKeyWaiting(key);
|
||||||
|
shouldCloseAfterWaiting.current = true;
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
shouldCloseAfterPending.current = true;
|
|
||||||
router.push(path, { scroll: true });
|
router.push(path, { scroll: true });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -631,14 +648,17 @@ export default function CommandKClient({
|
|||||||
accessory={accessory}
|
accessory={accessory}
|
||||||
annotation={annotation}
|
annotation={annotation}
|
||||||
annotationAria={annotationAria}
|
annotationAria={annotationAria}
|
||||||
loading={key === keyPending}
|
loading={key === keyWaiting}
|
||||||
disabled={isPending && key !== keyPending}
|
disabled={isPending && key !== keyWaiting}
|
||||||
/>;
|
/>;
|
||||||
})}
|
})}
|
||||||
</Command.Group>)}
|
</Command.Group>)}
|
||||||
</div>
|
</div>
|
||||||
{footer && !queryLive &&
|
{footer && !queryLive &&
|
||||||
<div className="text-center text-base text-dim pt-3 sm:pt-4">
|
<div className={clsx(
|
||||||
|
'text-center text-base text-dim pt-3 sm:pt-4',
|
||||||
|
'pb-5 md:pb-6',
|
||||||
|
)}>
|
||||||
{footer}
|
{footer}
|
||||||
</div>}
|
</div>}
|
||||||
</Command.List>
|
</Command.List>
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export default function MoreMenuItem({
|
|||||||
href?: string
|
href?: string
|
||||||
hrefDownloadName?: string
|
hrefDownloadName?: string
|
||||||
className?: string
|
className?: string
|
||||||
action?: () => Promise<void> | void
|
action?: () => Promise<void | boolean> | void
|
||||||
dismissMenu?: () => void
|
dismissMenu?: () => void
|
||||||
shouldPreventDefault?: boolean
|
shouldPreventDefault?: boolean
|
||||||
}) {
|
}) {
|
||||||
@ -68,10 +68,18 @@ export default function MoreMenuItem({
|
|||||||
const result = action();
|
const result = action();
|
||||||
if (result instanceof Promise) {
|
if (result instanceof Promise) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await result.finally(() => {
|
await result
|
||||||
setIsLoading(false);
|
.then(shouldClose => {
|
||||||
dismissMenu?.();
|
if (
|
||||||
});
|
shouldClose === undefined ||
|
||||||
|
shouldClose === true
|
||||||
|
) {
|
||||||
|
dismissMenu?.();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
dismissMenu?.();
|
dismissMenu?.();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,14 +135,18 @@ export default function AppStateProvider({
|
|||||||
if (isPathAdmin(pathname)) { router.push(PATH_SIGN_IN); }
|
if (isPathAdmin(pathname)) { router.push(PATH_SIGN_IN); }
|
||||||
}, [router, pathname]);
|
}, [router, pathname]);
|
||||||
|
|
||||||
const startUpload = useCallback((onStart?: () => void) => {
|
// Returns false when an upload is cancelled
|
||||||
|
const startUpload = useCallback(() => new Promise<boolean>(resolve => {
|
||||||
if (uploadInputRef.current) {
|
if (uploadInputRef.current) {
|
||||||
uploadInputRef.current.value = '';
|
uploadInputRef.current.value = '';
|
||||||
uploadInputRef.current.click();
|
uploadInputRef.current.click();
|
||||||
uploadInputRef.current.oninput = onStart ?? null;
|
uploadInputRef.current.oninput = () => resolve(true);
|
||||||
uploadInputRef.current.oncancel = onStart ?? null;
|
uploadInputRef.current.oncancel = () => resolve(false);
|
||||||
|
} else {
|
||||||
|
resolve(false);
|
||||||
}
|
}
|
||||||
}, []);
|
})
|
||||||
|
, []);
|
||||||
const setUploadState = useCallback((uploadState: Partial<UploadState>) => {
|
const setUploadState = useCallback((uploadState: Partial<UploadState>) => {
|
||||||
_setUploadState(prev => ({ ...prev, ...uploadState }));
|
_setUploadState(prev => ({ ...prev, ...uploadState }));
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user