Add loading status to admin sub-menu
This commit is contained in:
parent
a96abdb6f0
commit
00b058c812
@ -1,7 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import LinkWithStatus from '@/components/LinkWithStatus';
|
||||
import Note from '@/components/Note';
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import Spinner from '@/components/Spinner';
|
||||
import {
|
||||
PATH_ADMIN_CONFIGURATION,
|
||||
checkPathPrefix,
|
||||
@ -11,7 +13,6 @@ import {
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { differenceInMinutes } from 'date-fns';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { BiCog } from 'react-icons/bi';
|
||||
@ -60,40 +61,43 @@ export default function AdminNavClient({
|
||||
contentMain={
|
||||
<div className="space-y-5">
|
||||
<div className={clsx(
|
||||
'flex gap-2 md:gap-4',
|
||||
'border-b border-gray-200 dark:border-gray-800 pb-3',
|
||||
'flex gap-2 pb-3',
|
||||
'border-b border-gray-200 dark:border-gray-800',
|
||||
)}>
|
||||
<div className={clsx(
|
||||
'flex gap-2 md:gap-4',
|
||||
'flex gap-0.5 -mx-1',
|
||||
'flex-grow overflow-x-auto',
|
||||
)}>
|
||||
{items.map(({ label, href, count }) =>
|
||||
<Link
|
||||
<LinkWithStatus
|
||||
key={label}
|
||||
href={href}
|
||||
className={clsx(
|
||||
'flex gap-0.5',
|
||||
checkPathPrefix(pathname, href) ? 'font-bold' : 'text-dim',
|
||||
'px-1 py-0.5 rounded-md',
|
||||
)}
|
||||
loadingClassName="bg-dim"
|
||||
contentClassName="flex gap-1"
|
||||
prefetch={false}
|
||||
>
|
||||
<span>{label}</span>
|
||||
{count > 0 &&
|
||||
<span>({count})</span>}
|
||||
</Link>)}
|
||||
</LinkWithStatus>)}
|
||||
</div>
|
||||
<Link
|
||||
<LinkWithStatus
|
||||
href={PATH_ADMIN_CONFIGURATION}
|
||||
className={isPathAdminConfiguration(pathname)
|
||||
? 'font-bold'
|
||||
: 'text-dim'}
|
||||
loadingElement={<Spinner />}
|
||||
>
|
||||
<BiCog
|
||||
size={18}
|
||||
className="inline-block"
|
||||
className="inline-flex translate-y-0.5"
|
||||
aria-label="App Configuration"
|
||||
/>
|
||||
</Link>
|
||||
</LinkWithStatus>
|
||||
</div>
|
||||
{shouldShowBanner &&
|
||||
<Note icon={<FaRegClock className="flex-shrink-0" />}>
|
||||
|
||||
@ -14,15 +14,19 @@ import clsx from 'clsx/lite';
|
||||
|
||||
// Avoid showing spinner for too short a time
|
||||
const FLICKER_THRESHOLD = 400;
|
||||
// Clear loading status after 10 seconds of inactivity
|
||||
const MAX_LOADING_DURATION = 10_000;
|
||||
// Clear loading status after long duration of inactivity
|
||||
const MAX_LOADING_DURATION = 15_000;
|
||||
|
||||
export type LinkWithStatusProps = ComponentProps<typeof Link> & {
|
||||
loader?: ReactNode
|
||||
loadingElement?: ReactNode
|
||||
loadingClassName?: string
|
||||
contentClassName?: string
|
||||
}
|
||||
|
||||
export default function LinkWithStatus({
|
||||
loader,
|
||||
loadingElement,
|
||||
loadingClassName,
|
||||
contentClassName,
|
||||
href,
|
||||
className,
|
||||
onClick,
|
||||
@ -71,7 +75,11 @@ export default function LinkWithStatus({
|
||||
return <Link
|
||||
{...props }
|
||||
href={href}
|
||||
className={clsx('relative', className)}
|
||||
className={clsx(
|
||||
'relative transition-colors',
|
||||
className,
|
||||
isLoading && loadingClassName,
|
||||
)}
|
||||
onClick={e => {
|
||||
const isOpeningNewTab = e.metaKey || e.ctrlKey;
|
||||
if (!isVisitingLinkHref && !isOpeningNewTab) {
|
||||
@ -92,17 +100,20 @@ export default function LinkWithStatus({
|
||||
>
|
||||
<span className={clsx(
|
||||
'flex transition-opacity',
|
||||
loader
|
||||
contentClassName,
|
||||
loadingElement
|
||||
? isLoading ? 'opacity-0' : 'opacity-100'
|
||||
: isLoading ? 'opacity-50' : 'opacity-100',
|
||||
: loadingClassName
|
||||
? 'opacity-100'
|
||||
: isLoading ? 'opacity-50' : 'opacity-100',
|
||||
)}>
|
||||
{children}
|
||||
</span>
|
||||
{isLoading && loader && <span className={clsx(
|
||||
{isLoading && loadingElement && <span className={clsx(
|
||||
'absolute inset-0',
|
||||
'flex items-center justify-center',
|
||||
)}>
|
||||
{loader}
|
||||
{loadingElement}
|
||||
</span>}
|
||||
</Link>;
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ export default function SwitcherItem({
|
||||
href,
|
||||
className,
|
||||
prefetch,
|
||||
loader: <Spinner />,
|
||||
loadingElement: <Spinner />,
|
||||
}}>
|
||||
{renderContent(icon)}
|
||||
</LinkWithStatus>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user