Make links consistent across insights and config

This commit is contained in:
Sam Becker 2025-02-15 18:16:23 -06:00
parent 7027e85530
commit af40abeb97
5 changed files with 88 additions and 66 deletions

View File

@ -4,9 +4,7 @@ import {
ComponentProps, ComponentProps,
ReactNode, ReactNode,
} from 'react'; } from 'react';
import { clsx } from 'clsx/lite';
import ChecklistRow from '../components/ChecklistRow'; import ChecklistRow from '../components/ChecklistRow';
import { FiExternalLink } from 'react-icons/fi';
import { import {
BiData, BiData,
BiHide, BiHide,
@ -29,6 +27,7 @@ import { PiPaintBrushHousehold } from 'react-icons/pi';
import { IoMdGrid } from 'react-icons/io'; import { IoMdGrid } from 'react-icons/io';
import { CgDebug } from 'react-icons/cg'; import { CgDebug } from 'react-icons/cg';
import EnvVar from '@/components/EnvVar'; import EnvVar from '@/components/EnvVar';
import AdminLink from './AdminLink';
export default function AdminAppConfigurationClient({ export default function AdminAppConfigurationClient({
// Storage // Storage
@ -110,27 +109,6 @@ export default function AdminAppConfigurationClient({
simplifiedView?: boolean simplifiedView?: boolean
isAnalyzingConfiguration?: boolean isAnalyzingConfiguration?: boolean
}) { }) {
const renderLink = (href: string, text: string, external = true) =>
<>
<a {...{
href,
...external && { target: '_blank', rel: 'noopener noreferrer' },
className: clsx(
'underline hover:no-underline',
),
}}>
{text}
</a>
{external &&
<>
&nbsp;
<FiExternalLink
size={14}
className='inline translate-y-[-1.5px]'
/>
</>}
</>;
const renderEnvVars = (variables: string[]) => const renderEnvVars = (variables: string[]) =>
<div className="pt-1 flex flex-col gap-1"> <div className="pt-1 flex flex-col gap-1">
{variables.map(envVar => {variables.map(envVar =>
@ -158,7 +136,7 @@ export default function AdminAppConfigurationClient({
renderSubStatus( renderSubStatus(
type, type,
renderEnvVars([variable]), renderEnvVars([variable]),
'translate-y-[5px]', 'translate-y-[3px]',
); );
const renderError = ({ const renderError = ({
@ -211,11 +189,13 @@ export default function AdminAppConfigurationClient({
: renderSubStatus('optional', <> : renderSubStatus('optional', <>
Vercel Postgres: Vercel Postgres:
{' '} {' '}
{renderLink( <AdminLink
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
'https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database', href="https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database"
'create store', externalIcon
)} >
create store
</AdminLink>
{' '} {' '}
and connect to project and connect to project
</>)} </>)}
@ -247,11 +227,13 @@ export default function AdminAppConfigurationClient({
: renderSubStatus('optional', <> : renderSubStatus('optional', <>
{labelForStorage('vercel-blob')}: {labelForStorage('vercel-blob')}:
{' '} {' '}
{renderLink( <AdminLink
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
'https://vercel.com/docs/storage/vercel-blob/quickstart#create-a-blob-store', href="https://vercel.com/docs/storage/vercel-blob/quickstart#create-a-blob-store"
'create store', externalIcon
)} >
create store
</AdminLink>
{' '} {' '}
and connect to project and connect to project
</>, </>,
@ -261,20 +243,25 @@ export default function AdminAppConfigurationClient({
: renderSubStatus('optional', <> : renderSubStatus('optional', <>
{labelForStorage('cloudflare-r2')}: {labelForStorage('cloudflare-r2')}:
{' '} {' '}
{renderLink( <AdminLink
'https://github.com/sambecker/exif-photo-blog#cloudflare-r2', // eslint-disable-next-line max-len
'create/configure bucket', href="https://github.com/sambecker/exif-photo-blog#cloudflare-r2"
)} externalIcon
>
create/configure bucket
</AdminLink>
</>)} </>)}
{hasAwsS3Storage {hasAwsS3Storage
? renderSubStatus('checked', 'AWS S3: connected') ? renderSubStatus('checked', 'AWS S3: connected')
: renderSubStatus('optional', <> : renderSubStatus('optional', <>
{labelForStorage('aws-s3')}: {labelForStorage('aws-s3')}:
{' '} {' '}
{renderLink( <AdminLink
'https://github.com/sambecker/exif-photo-blog#aws-s3', href="https://github.com/sambecker/exif-photo-blog#aws-s3"
'create/configure bucket', externalIcon
)} >
create/configure bucket
</AdminLink>
</>)} </>)}
</ChecklistRow> </ChecklistRow>
</ChecklistGroup> </ChecklistGroup>
@ -385,11 +372,13 @@ export default function AdminAppConfigurationClient({
{kvError && renderError({ {kvError && renderError({
connection: { provider: 'Vercel KV', error: kvError}, connection: { provider: 'Vercel KV', error: kvError},
})} })}
{renderLink( <AdminLink
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
'https://vercel.com/docs/storage/vercel-kv/quickstart#create-a-kv-database', href="https://vercel.com/docs/storage/vercel-kv/quickstart#create-a-kv-database"
'Create Vercel KV store', externalIcon
)} >
Create Vercel KV store
</AdminLink>
{' '} {' '}
and connect to project in order to enable rate limiting and connect to project in order to enable rate limiting
</ChecklistRow> </ChecklistRow>

38
src/admin/AdminLink.tsx Normal file
View File

@ -0,0 +1,38 @@
import clsx from 'clsx/lite';
import Link from 'next/link';
import { ComponentProps } from 'react';
import { FiExternalLink } from 'react-icons/fi';
export default function AdminLink({
href,
className,
children,
externalIcon,
...props
}: ComponentProps<typeof Link> & {
externalIcon?: boolean
}) {
return (
<>
<Link
{...props}
href={href}
target="blank"
className={clsx(
'underline underline-offset-4',
'decoration-gray-300 dark:decoration-gray-700',
className,
)}
>
{children}
</Link>
{externalIcon &&
<>
&nbsp;
<FiExternalLink
size={14}
className="inline translate-y-[-1.5px]"
/>
</>}
</>
);
}

View File

@ -30,26 +30,17 @@ import { PATH_ADMIN_OUTDATED } from '@/app-core/paths';
import { LiaBroomSolid } from 'react-icons/lia'; import { LiaBroomSolid } from 'react-icons/lia';
import { IoMdGrid } from 'react-icons/io'; import { IoMdGrid } from 'react-icons/io';
import { RiSpeedMiniLine } from 'react-icons/ri'; import { RiSpeedMiniLine } from 'react-icons/ri';
import AdminLink from '../AdminLink';
const DEBUG_COMMIT_SHA = '4cd29ed'; const DEBUG_COMMIT_SHA = '4cd29ed';
const DEBUG_COMMIT_MESSAGE = 'Long commit message for debugging purposes'; const DEBUG_COMMIT_MESSAGE = 'Long commit message for debugging purposes';
const DEBUG_BEHIND_BY = 9; const DEBUG_BEHIND_BY = 9;
const DEBUG_PHOTOS_COUNT_OUTDATED = 7; const DEBUG_PHOTOS_COUNT_OUTDATED = 7;
const renderLink = (text: string, href = '') =>
<a
href={href}
target="blank"
className="underline underline-offset-4 decoration-gray-300"
>
{text}
</a>;
const readmeAnchor = (anchor: string) => const readmeAnchor = (anchor: string) =>
renderLink( <AdminLink href={`${TEMPLATE_REPO_URL_README}#${anchor}`}>
`README/${anchor}`, README/{anchor}
`${TEMPLATE_REPO_URL_README}#${anchor}`, </AdminLink>;
);
const renderLabeledEnvVar = (label: string, envVar: string, value = '1') => const renderLabeledEnvVar = (label: string, envVar: string, value = '1') =>
<div className="flex flex-col gap-1.5"> <div className="flex flex-col gap-1.5">
@ -112,7 +103,9 @@ export default function AdminAppInsightsClient({
/>} />}
content="This template is not forked" content="This template is not forked"
expandContent={<> expandContent={<>
{renderLink('Fork original template', TEMPLATE_REPO_URL_FORK)} <AdminLink href={TEMPLATE_REPO_URL_FORK}>
Fork original template
</AdminLink>
{' '} {' '}
to receive the latest fixes and features. to receive the latest fixes and features.
{' '} {' '}
@ -144,7 +137,9 @@ export default function AdminAppInsightsClient({
behind behind
</>} </>}
expandContent={<> expandContent={<>
{renderLink('Sync your fork', codeMeta?.urlRepo)} <AdminLink href={codeMeta?.urlRepo ?? ''}>
Sync your fork
</AdminLink>
{' '} {' '}
to receive the latest fixes and features. to receive the latest fixes and features.
</>} </>}
@ -190,7 +185,7 @@ export default function AdminAppInsightsClient({
target="blank" target="blank"
className="flex items-center gap-2" className="flex items-center gap-2"
> >
<span className="text-medium"> <span className="text-medium hidden sm:inline-block">
{VERCEL_GIT_COMMIT_SHA_SHORT ?? DEBUG_COMMIT_SHA} {VERCEL_GIT_COMMIT_SHA_SHORT ?? DEBUG_COMMIT_SHA}
</span> </span>
<span className="truncate"> <span className="truncate">
@ -270,18 +265,18 @@ export default function AdminAppInsightsClient({
{' '} {' '}
portrait and landscape photos appear more consistent portrait and landscape photos appear more consistent
{' '} {' '}
<EnvVar variable="NEXT_PUBLIC_MATTE_PHOTOS" value="1" /> <EnvVar variable="NEXT_PUBLIC_MATTE_PHOTOS" value="1" />.
</>} </>}
/>} />}
{(gridFirst || debug) && <ScoreCardRow {(gridFirst || debug) && <ScoreCardRow
icon={<IoMdGrid size={18} className="translate-y-[-1px]" />} icon={<IoMdGrid size={18} className="translate-y-[-1px]" />}
content="Grid homepage" content="Grid homepage"
expandContent={<> expandContent={<>
Now that you have a sufficient amount of photos, you can Now that you have enough photos, consider switching your
{' '} {' '}
enable grid homepage by setting default view to grid by setting
{' '} {' '}
<EnvVar variable="NEXT_PUBLIC_GRID_HOMEPAGE_ENABLED" value="1" /> <EnvVar variable="NEXT_PUBLIC_GRID_HOMEPAGE_ENABLED" value="1" />.
</>} </>}
/>} />}
</ScoreCard>} </ScoreCard>}

View File

@ -2,7 +2,7 @@ import clsx from 'clsx/lite';
import { LuLightbulb } from 'react-icons/lu'; import { LuLightbulb } from 'react-icons/lu';
export default function AdminAppInsightsIcon({ export default function AdminAppInsightsIcon({
indicator = 'blue', indicator,
}: { }: {
indicator?: 'blue' | 'yellow' indicator?: 'blue' | 'yellow'
}) { }) {

View File

@ -42,7 +42,7 @@ export default function ChecklistRow({
{experimental && {experimental &&
<ExperimentalBadge className="translate-y-[-0.5px]" />} <ExperimentalBadge className="translate-y-[-0.5px]" />}
</div> </div>
<div> <div className="leading-relaxed">
{children} {children}
</div> </div>
</div> </div>