Skip to content

Commit 58658a4

Browse files
authored
fix: first schema check landing width & sidenav loading flicker (#7066)
1 parent 8d554dd commit 58658a4

File tree

4 files changed

+83
-36
lines changed

4 files changed

+83
-36
lines changed

.changeset/slow-wasps-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'hive': patch
3+
---
4+
5+
Fix first schema check landing width; fix flickering sidenav on schema check loading"

packages/web/app/src/components/ui/empty-list.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ export const NoSchemaVersion = ({
100100
<EmptyList
101101
title="Hive is waiting for your first schema"
102102
description="You can publish a schema with Hive CLI and Hive Client"
103-
docsUrl="/features/schema-registry#publish-a-schema"
103+
docsUrl={
104+
recommendedAction === 'publish' ? '/features/schema-registry#publish-a-schema' : undefined
105+
}
104106
>
105107
{children}
106108
</EmptyList>

packages/web/app/src/pages/target-checks-single.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useMemo, useState } from 'react';
1+
import { Fragment, useCallback, useMemo, useState } from 'react';
22
import { format } from 'date-fns';
33
import { BadgeCheck, ChevronDown, GitCompareIcon, Loader2 } from 'lucide-react';
44
import { useMutation, useQuery } from 'urql';
@@ -281,20 +281,20 @@ function ConditionalBreakingChangesMetadataSection(props: {
281281
{numberOfTargets <= 3 && (
282282
<>
283283
{allTargets.map((target, index) => (
284-
<>
284+
<Fragment key={target.slug}>
285285
<span className="text-white">{target.slug}</span>
286286
{index === allTargets.length - 1 ? null : ', '}
287-
</>
287+
</Fragment>
288288
))}
289289
</>
290290
)}
291291
{numberOfTargets > 3 && (
292292
<>
293293
{truncatedTargets.map((target, index) => (
294-
<>
294+
<Fragment key={target.slug}>
295295
<span className="text-white">{target.slug}</span>
296296
{index === truncatedTargets.length - 1 ? null : ', '}
297-
</>
297+
</Fragment>
298298
))}
299299
{' and '}
300300
<Popover>
@@ -319,7 +319,7 @@ function ConditionalBreakingChangesMetadataSection(props: {
319319
</PopoverContent>
320320
</Popover>
321321
</>
322-
)}{' '}
322+
)}
323323
. <br />
324324
Usage data ranges from{' '}
325325
<span className="text-white">

packages/web/app/src/pages/target-checks.tsx

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from 'react';
1+
import { useEffect, useRef, useState } from 'react';
22
import { useQuery } from 'urql';
33
import { Page, TargetLayout } from '@/components/layouts/target';
44
import { BadgeRounded } from '@/components/ui/badge';
@@ -230,7 +230,6 @@ function ChecksPageContent(props: {
230230
const [paginationVariables, setPaginationVariables] = useState<Array<string | null>>(() => [
231231
null,
232232
]);
233-
const [hasSchemaChecks, setHasSchemaChecks] = useState(false);
234233
const navigate = useNavigate();
235234
const { schemaCheckId } = useParams({
236235
strict: false /* allows to read the $schemaCheckId param of its child route */,
@@ -266,9 +265,17 @@ function ChecksPageContent(props: {
266265
);
267266
}
268267

269-
if (!hasSchemaChecks && !!query.data?.target?.schemaChecks?.edges?.length) {
270-
setHasSchemaChecks(true);
271-
}
268+
const [isLoading] = useDebouncedLoader(query.fetching || query.stale);
269+
270+
const [hasSchemaChecks, setHasSchemaChecks] = useState(
271+
!!query.data?.target?.schemaChecks?.edges?.length,
272+
);
273+
useEffect(() => {
274+
if (!query.stale && !query.fetching) {
275+
setHasSchemaChecks(!!query.data?.target?.schemaChecks?.edges?.length);
276+
}
277+
}, [query.fetching, query.stale, !query.data?.target?.schemaChecks?.edges?.length]);
278+
272279
const hasFilteredSchemaChecks = !!query.data?.target?.filteredSchemaChecks?.edges?.length;
273280
const hasActiveSchemaCheck = !!schemaCheckId;
274281

@@ -290,9 +297,11 @@ function ChecksPageContent(props: {
290297
});
291298
};
292299

300+
const loadMore = (cursor: string) => setPaginationVariables(cursors => [...cursors, cursor]);
301+
293302
return (
294303
<>
295-
<div>
304+
<div className={cn(!hasActiveSchemaCheck && !hasSchemaChecks && 'w-full')}>
296305
<div className="w-[300px] py-6">
297306
<Title>Schema Checks</Title>
298307
<Subtitle>Recently checked schemas.</Subtitle>
@@ -337,40 +346,46 @@ function ChecksPageContent(props: {
337346
schemaCheckId={schemaCheckId}
338347
after={cursor}
339348
isLastPage={index + 1 === paginationVariables.length}
340-
onLoadMore={cursor => setPaginationVariables(cursors => [...cursors, cursor])}
349+
onLoadMore={loadMore}
341350
key={cursor ?? 'first'}
342351
showOnlyChanged={showOnlyChanged}
343352
showOnlyFailed={showOnlyFailed}
344353
/>
345354
))}
346355
</div>
347-
) : query.fetching || query.stale ? (
348-
<Spinner />
349356
) : (
350-
<div className="my-4 cursor-default text-center text-sm text-gray-400">
351-
No schema checks found with the current filters
352-
</div>
357+
!query.fetching &&
358+
!query.stale && (
359+
<div className="my-4 cursor-default text-center text-sm text-gray-400">
360+
No schema checks found with the current filters
361+
</div>
362+
)
353363
)}
354364
</div>
355-
) : query.fetching ? (
356-
<Spinner />
357365
) : (
358-
<div>
359-
<div className="cursor-default text-sm">
360-
{hasActiveSchemaCheck ? (
361-
'List is empty'
362-
) : (
363-
<NoSchemaVersion
364-
projectType={query.data?.target?.project.type ?? null}
365-
recommendedAction="check"
366-
/>
367-
)}
366+
!query.fetching &&
367+
!query.stale && (
368+
<div>
369+
<div className="cursor-default text-sm">
370+
{!hasActiveSchemaCheck && (
371+
<NoSchemaVersion
372+
projectType={query.data?.target?.project.type ?? null}
373+
recommendedAction="check"
374+
/>
375+
)}
376+
</div>
377+
<DocsLink
378+
href="/features/schema-registry#check-a-schema"
379+
className="flex flex-row items-center"
380+
>
381+
Learn how to check your first schema
382+
</DocsLink>
368383
</div>
369-
<DocsLink href="/features/schema-registry#check-a-schema">
370-
{hasActiveSchemaCheck
371-
? 'Check you first schema'
372-
: 'Learn how to check your first schema with Hive CLI'}
373-
</DocsLink>
384+
)
385+
)}
386+
{isLoading && (
387+
<div className="mt-4 flex w-full grow flex-col items-center">
388+
<Spinner />
374389
</div>
375390
)}
376391
</div>
@@ -410,3 +425,28 @@ export function TargetChecksPage(props: {
410425
</>
411426
);
412427
}
428+
429+
const useDebouncedLoader = (isLoading: boolean, delay = 500) => {
430+
const [showLoadingIcon, setShowLoadingIcon] = useState(false);
431+
const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
432+
433+
useEffect(() => {
434+
if (isLoading) {
435+
// Start a timer to show the loading icon after the delay
436+
timerRef.current = setTimeout(() => {
437+
setShowLoadingIcon(true);
438+
}, delay);
439+
} else {
440+
// If loading finishes, clear any pending timer and hide the icon
441+
clearTimeout(timerRef.current);
442+
setShowLoadingIcon(false);
443+
}
444+
445+
// Cleanup function to clear the timer on unmount or if isLoading changes
446+
return () => {
447+
clearTimeout(timerRef.current);
448+
};
449+
}, [isLoading, delay]);
450+
451+
return [showLoadingIcon];
452+
};

0 commit comments

Comments
 (0)