Add visual indicator for important insights
This commit is contained in:
parent
7c98c55853
commit
c64e5b13df
@ -10,25 +10,14 @@ import {
|
||||
APP_CONFIGURATION,
|
||||
GRID_HOMEPAGE_ENABLED,
|
||||
HAS_STATIC_OPTIMIZATION,
|
||||
IS_DEVELOPMENT,
|
||||
IS_PRODUCTION,
|
||||
IS_VERCEL_GIT_PROVIDER_GITHUB,
|
||||
MATTE_PHOTOS,
|
||||
VERCEL_GIT_BRANCH,
|
||||
VERCEL_GIT_COMMIT_SHA,
|
||||
VERCEL_GIT_REPO_OWNER,
|
||||
VERCEL_GIT_REPO_SLUG,
|
||||
} from '@/app-core/config';
|
||||
import { getGitHubMeta } from '../../platforms/github';
|
||||
import { OUTDATED_THRESHOLD } from '@/photo';
|
||||
import { getGitHubMetaForCurrentApp, getSignificantInsights } from '.';
|
||||
|
||||
const BASIC_PHOTO_INSTALLATION_COUNT = 32;
|
||||
|
||||
const owner = VERCEL_GIT_REPO_OWNER;
|
||||
const repo = VERCEL_GIT_REPO_SLUG;
|
||||
const branch = VERCEL_GIT_BRANCH;
|
||||
const commit = VERCEL_GIT_COMMIT_SHA;
|
||||
|
||||
export default async function AdminAppInsights() {
|
||||
const [
|
||||
{ count: photosCount, dateRange },
|
||||
@ -49,30 +38,30 @@ export default async function AdminAppInsights() {
|
||||
getUniqueCameras(),
|
||||
getUniqueFilmSimulations(),
|
||||
getUniqueFocalLengths(),
|
||||
IS_VERCEL_GIT_PROVIDER_GITHUB || IS_DEVELOPMENT
|
||||
? getGitHubMeta({
|
||||
owner,
|
||||
repo,
|
||||
branch,
|
||||
commit,
|
||||
})
|
||||
: undefined,
|
||||
getGitHubMetaForCurrentApp(),
|
||||
]);
|
||||
|
||||
const { isAiTextGenerationEnabled } = APP_CONFIGURATION;
|
||||
|
||||
const {
|
||||
isAiTextGenerationEnabled,
|
||||
hasVercelBlobStorage,
|
||||
} = APP_CONFIGURATION;
|
||||
noFork,
|
||||
forkBehind,
|
||||
noAiRateLimiting,
|
||||
outdatedPhotos,
|
||||
} = getSignificantInsights({
|
||||
codeMeta,
|
||||
photosCountOutdated,
|
||||
});
|
||||
|
||||
return (
|
||||
<AdminAppInsightsClient
|
||||
codeMeta={codeMeta}
|
||||
insights={{
|
||||
noFork: !codeMeta?.isForkedFromBase && !codeMeta?.isBaseRepo,
|
||||
forkBehind: Boolean(codeMeta?.isBehind),
|
||||
noFork,
|
||||
forkBehind,
|
||||
noAi: !isAiTextGenerationEnabled,
|
||||
noAiRateLimiting: isAiTextGenerationEnabled && !hasVercelBlobStorage,
|
||||
outdatedPhotos: Boolean(photosCountOutdated),
|
||||
noAiRateLimiting,
|
||||
outdatedPhotos,
|
||||
photoMatting: photosCountPortrait > 0 && !MATTE_PHOTOS,
|
||||
gridFirst: (
|
||||
photosCount >= BASIC_PHOTO_INSTALLATION_COUNT &&
|
||||
|
||||
@ -11,7 +11,6 @@ import { HiOutlinePhotograph } from 'react-icons/hi';
|
||||
import { MdAspectRatio } from 'react-icons/md';
|
||||
import { PiWarningBold } from 'react-icons/pi';
|
||||
import { TbCone, TbSparkles } from 'react-icons/tb';
|
||||
import { getGitHubMeta } from '../../platforms/github';
|
||||
import { BiGitBranch, BiGitCommit, BiLogoGithub } from 'react-icons/bi';
|
||||
import {
|
||||
TEMPLATE_REPO_BRANCH,
|
||||
@ -22,7 +21,12 @@ import {
|
||||
TEMPLATE_REPO_URL_FORK,
|
||||
TEMPLATE_REPO_URL_README,
|
||||
} from '@/app-core/config';
|
||||
import { AdminAppInsights, hasTemplateRecommendations, PhotoStats } from '.';
|
||||
import {
|
||||
AdminAppInsights,
|
||||
getGitHubMetaForCurrentApp,
|
||||
hasTemplateRecommendations,
|
||||
PhotoStats,
|
||||
} from '.';
|
||||
import EnvVar from '@/components/EnvVar';
|
||||
import { IoSyncCircle } from 'react-icons/io5';
|
||||
import clsx from 'clsx/lite';
|
||||
@ -82,7 +86,7 @@ export default function AdminAppInsightsClient({
|
||||
},
|
||||
debug,
|
||||
}: {
|
||||
codeMeta?: Awaited<ReturnType<typeof getGitHubMeta>>
|
||||
codeMeta?: Awaited<ReturnType<typeof getGitHubMetaForCurrentApp>>
|
||||
insights: AdminAppInsights
|
||||
photoStats: PhotoStats
|
||||
debug?: boolean
|
||||
|
||||
@ -1,26 +1,23 @@
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import clsx from 'clsx/lite';
|
||||
import { LuLightbulb } from 'react-icons/lu';
|
||||
|
||||
export default function AdminAppInsightsIcon({
|
||||
indicator,
|
||||
}: {
|
||||
indicator?: 'blue' | 'yellow'
|
||||
}) {
|
||||
export default function AdminAppInsightsIcon() {
|
||||
const {
|
||||
shouldShowInsightsIndicator,
|
||||
} = useAppState();
|
||||
|
||||
return (
|
||||
<span className="inline-flex relative">
|
||||
<LuLightbulb
|
||||
size={19}
|
||||
className="translate-y-[3px]"
|
||||
/>
|
||||
{indicator && <span className={clsx(
|
||||
{shouldShowInsightsIndicator && <span className={clsx(
|
||||
'absolute',
|
||||
'top-[2px] right-[0.5px]',
|
||||
'size-2 rounded-full',
|
||||
indicator === 'yellow'
|
||||
? 'bg-amber-500'
|
||||
: indicator === 'blue'
|
||||
? 'bg-blue-500'
|
||||
: undefined,
|
||||
'bg-blue-500',
|
||||
)} />}
|
||||
</span>
|
||||
);
|
||||
|
||||
26
src/admin/insights/actions.ts
Normal file
26
src/admin/insights/actions.ts
Normal file
@ -0,0 +1,26 @@
|
||||
'use server';
|
||||
|
||||
import { runAuthenticatedAdminServerAction } from '@/auth';
|
||||
import { getGitHubMetaForCurrentApp, getSignificantInsights } from '.';
|
||||
import { getPhotosMeta } from '@/photo/db/query';
|
||||
import { OUTDATED_THRESHOLD } from '@/photo';
|
||||
|
||||
export const getShouldShowInsightsIndicatorAction = async () =>
|
||||
runAuthenticatedAdminServerAction(async () => {
|
||||
const [
|
||||
codeMeta,
|
||||
{ count: photosCountOutdated },
|
||||
] = await Promise.all([
|
||||
getGitHubMetaForCurrentApp(),
|
||||
getPhotosMeta({ hidden: 'include', updatedBefore: OUTDATED_THRESHOLD }),
|
||||
]);
|
||||
|
||||
const significantInsights = getSignificantInsights({
|
||||
codeMeta,
|
||||
photosCountOutdated,
|
||||
});
|
||||
|
||||
return Object
|
||||
.values(significantInsights)
|
||||
.some(Boolean);
|
||||
});
|
||||
@ -1,4 +1,14 @@
|
||||
import {
|
||||
VERCEL_GIT_BRANCH,
|
||||
VERCEL_GIT_COMMIT_SHA,
|
||||
VERCEL_GIT_REPO_OWNER,
|
||||
VERCEL_GIT_REPO_SLUG,
|
||||
IS_VERCEL_GIT_PROVIDER_GITHUB,
|
||||
IS_DEVELOPMENT,
|
||||
APP_CONFIGURATION,
|
||||
} from '@/app-core/config';
|
||||
import { PhotoDateRange } from '@/photo';
|
||||
import { getGitHubMeta } from '@/platforms/github';
|
||||
|
||||
export type AdminAppInsight =
|
||||
'noFork' |
|
||||
@ -34,11 +44,32 @@ export interface PhotoStats {
|
||||
dateRange?: PhotoDateRange
|
||||
}
|
||||
|
||||
export const getInsightIndicator = ({
|
||||
forkBehind,
|
||||
noAiRateLimiting,
|
||||
outdatedPhotos,
|
||||
}: AdminAppInsights) =>
|
||||
forkBehind ||
|
||||
noAiRateLimiting ||
|
||||
outdatedPhotos;
|
||||
export const getGitHubMetaForCurrentApp = () =>
|
||||
(IS_VERCEL_GIT_PROVIDER_GITHUB || IS_DEVELOPMENT)
|
||||
? getGitHubMeta({
|
||||
owner: VERCEL_GIT_REPO_OWNER,
|
||||
repo: VERCEL_GIT_REPO_SLUG,
|
||||
branch: VERCEL_GIT_BRANCH,
|
||||
commit: VERCEL_GIT_COMMIT_SHA,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
export const getSignificantInsights = ({
|
||||
codeMeta,
|
||||
photosCountOutdated,
|
||||
}: {
|
||||
codeMeta: Awaited<ReturnType<typeof getGitHubMetaForCurrentApp>>
|
||||
photosCountOutdated: number
|
||||
}) => {
|
||||
const {
|
||||
isAiTextGenerationEnabled,
|
||||
hasRedisStorage,
|
||||
} = APP_CONFIGURATION;
|
||||
|
||||
return {
|
||||
noFork: !codeMeta?.isForkedFromBase && !codeMeta?.isBaseRepo,
|
||||
forkBehind: Boolean(codeMeta?.isBehind),
|
||||
noAiRateLimiting: isAiTextGenerationEnabled && !hasRedisStorage,
|
||||
outdatedPhotos: Boolean(photosCountOutdated),
|
||||
};
|
||||
};
|
||||
|
||||
@ -30,6 +30,8 @@ export interface AppStateContext {
|
||||
setSelectedPhotoIds?: Dispatch<SetStateAction<string[] | undefined>>
|
||||
isPerformingSelectEdit?: boolean
|
||||
setIsPerformingSelectEdit?: Dispatch<SetStateAction<boolean>>
|
||||
shouldShowInsightsIndicator?: boolean
|
||||
setShouldShowInsightsIndicator?: Dispatch<SetStateAction<boolean>>
|
||||
// DEBUG
|
||||
isGridHighDensity?: boolean
|
||||
setIsGridHighDensity?: Dispatch<SetStateAction<boolean>>
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
import { getPhotosHiddenMetaCachedAction } from '@/photo/actions';
|
||||
import { ShareModalProps } from '@/share';
|
||||
import { storeTimezoneCookie } from '@/utility/timezone';
|
||||
import { getShouldShowInsightsIndicatorAction } from '@/admin/insights/actions';
|
||||
|
||||
export default function AppStateProvider({
|
||||
children,
|
||||
@ -47,6 +48,8 @@ export default function AppStateProvider({
|
||||
useState<string[] | undefined>();
|
||||
const [isPerformingSelectEdit, setIsPerformingSelectEdit] =
|
||||
useState(false);
|
||||
const [shouldShowInsightsIndicator, setShouldShowInsightsIndicator] =
|
||||
useState(false);
|
||||
// DEBUG
|
||||
const [isGridHighDensity, setIsGridHighDensity] =
|
||||
useState(HIGH_DENSITY_GRID);
|
||||
@ -70,10 +73,12 @@ export default function AppStateProvider({
|
||||
const isUserSignedIn = Boolean(userEmail);
|
||||
useEffect(() => {
|
||||
if (isUserSignedIn) {
|
||||
const timeout = setTimeout(() =>
|
||||
getPhotosHiddenMetaCachedAction().then(({ count }) =>
|
||||
setHiddenPhotosCount(count))
|
||||
, 100);
|
||||
const timeout = setTimeout(() =>{
|
||||
getPhotosHiddenMetaCachedAction()
|
||||
.then(({ count }) => setHiddenPhotosCount(count));
|
||||
getShouldShowInsightsIndicatorAction()
|
||||
.then(setShouldShowInsightsIndicator);
|
||||
}, 100);
|
||||
return () => clearTimeout(timeout);
|
||||
} else {
|
||||
setHiddenPhotosCount(0);
|
||||
@ -119,6 +124,8 @@ export default function AppStateProvider({
|
||||
setSelectedPhotoIds,
|
||||
isPerformingSelectEdit,
|
||||
setIsPerformingSelectEdit,
|
||||
shouldShowInsightsIndicator,
|
||||
setShouldShowInsightsIndicator,
|
||||
// DEBUG
|
||||
isGridHighDensity,
|
||||
setIsGridHighDensity,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user