Improve loading of "details" panel (#7921)

- Remove suspenses
- remove global loading lock
- Improves "responsiveness" feel
This commit is contained in:
Oliver 2024-08-19 16:33:30 +10:00 committed by GitHub
parent d7d908b74f
commit d6218b76ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 27 deletions

View File

@ -2,15 +2,16 @@ import { t } from '@lingui/macro';
import { import {
Anchor, Anchor,
Badge, Badge,
Group,
Paper, Paper,
Skeleton, Skeleton,
Stack, Stack,
Table, Table,
Text Text
} from '@mantine/core'; } from '@mantine/core';
import { useSuspenseQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { getValueAtPath } from 'mantine-datatable'; import { getValueAtPath } from 'mantine-datatable';
import { Suspense, useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { api } from '../../App'; import { api } from '../../App';
@ -96,7 +97,7 @@ type FieldProps = {
* Badge appends icon to describe type of Owner * Badge appends icon to describe type of Owner
*/ */
function NameBadge({ pk, type }: { pk: string | number; type: BadgeType }) { function NameBadge({ pk, type }: { pk: string | number; type: BadgeType }) {
const { data } = useSuspenseQuery({ const { data } = useQuery({
queryKey: ['badge', type, pk], queryKey: ['badge', type, pk],
queryFn: async () => { queryFn: async () => {
let path: string = ''; let path: string = '';
@ -111,6 +112,8 @@ function NameBadge({ pk, type }: { pk: string | number; type: BadgeType }) {
case 'group': case 'group':
path = ApiEndpoints.group_list; path = ApiEndpoints.group_list;
break; break;
default:
return {};
} }
const url = apiUrl(path, pk); const url = apiUrl(path, pk);
@ -133,9 +136,13 @@ function NameBadge({ pk, type }: { pk: string | number; type: BadgeType }) {
const settings = useGlobalSettingsState(); const settings = useGlobalSettingsState();
if (!data || data.isLoading || data.isFetching) {
return <Skeleton height={12} radius="md" />;
}
// Rendering a user's rame for the badge // Rendering a user's rame for the badge
function _render_name() { function _render_name() {
if (!data) { if (!data || !data.pk) {
return ''; return '';
} else if (type === 'user' && settings.isSet('DISPLAY_FULL_NAMES')) { } else if (type === 'user' && settings.isSet('DISPLAY_FULL_NAMES')) {
if (data.first_name || data.last_name) { if (data.first_name || data.last_name) {
@ -151,18 +158,16 @@ function NameBadge({ pk, type }: { pk: string | number; type: BadgeType }) {
} }
return ( return (
<Suspense fallback={<Skeleton width={200} height={20} radius="xl" />}> <Group wrap="nowrap" gap="sm" justify="right">
<div style={{ display: 'flex', alignItems: 'center' }}> <Badge
<Badge color="dark"
color="dark" variant="filled"
variant="filled" style={{ display: 'flex', alignItems: 'center' }}
style={{ display: 'flex', alignItems: 'center' }} >
> {data?.name ?? _render_name()}
{data?.name ?? _render_name()} </Badge>
</Badge> <InvenTreeIcon icon={type === 'user' ? type : data.label} />
<InvenTreeIcon icon={type === 'user' ? type : data.label} /> </Group>
</div>
</Suspense>
); );
} }
@ -195,15 +200,15 @@ function TableStringValue(props: Readonly<FieldProps>) {
alignItems: 'flex-start' alignItems: 'flex-start'
}} }}
> >
<Suspense fallback={<Skeleton width={200} height={20} radius="xl" />}> <Group wrap="nowrap" gap="xs" justify="space-apart">
<span> <Group wrap="nowrap" gap="xs" justify="left">
{value ? value : props.field_data?.unit && '0'}{' '} {value ? value : props.field_data?.unit && '0'}{' '}
{props.field_data.unit == true && props.unit} {props.field_data.unit == true && props.unit}
</span> </Group>
</Suspense> {props.field_data.user && (
{props.field_data.user && ( <NameBadge pk={props.field_data?.user} type="user" />
<NameBadge pk={props.field_data?.user} type="user" /> )}
)} </Group>
</div> </div>
); );
} }
@ -215,7 +220,7 @@ function BooleanValue(props: Readonly<FieldProps>) {
function TableAnchorValue(props: Readonly<FieldProps>) { function TableAnchorValue(props: Readonly<FieldProps>) {
const navigate = useNavigate(); const navigate = useNavigate();
const { data } = useSuspenseQuery({ const { data } = useQuery({
queryKey: ['detail', props.field_data.model, props.field_value], queryKey: ['detail', props.field_data.model, props.field_value],
queryFn: async () => { queryFn: async () => {
if (!props.field_data?.model) { if (!props.field_data?.model) {
@ -260,6 +265,10 @@ function TableAnchorValue(props: Readonly<FieldProps>) {
[detailUrl] [detailUrl]
); );
if (!data || data.isLoading || data.isFetching) {
return <Skeleton height={12} radius="md" />;
}
if (props.field_data.external) { if (props.field_data.external) {
return ( return (
<Anchor <Anchor
@ -294,7 +303,7 @@ function TableAnchorValue(props: Readonly<FieldProps>) {
} }
return ( return (
<Suspense fallback={<Skeleton width={200} height={20} radius="xl" />}> <div>
{make_link ? ( {make_link ? (
<Anchor href="#" onClick={handleLinkClick}> <Anchor href="#" onClick={handleLinkClick}>
<Text>{value}</Text> <Text>{value}</Text>
@ -302,7 +311,7 @@ function TableAnchorValue(props: Readonly<FieldProps>) {
) : ( ) : (
<Text>{value}</Text> <Text>{value}</Text>
)} )}
</Suspense> </div>
); );
} }

View File

@ -375,7 +375,7 @@ export default function PartDetail() {
]; ];
// Add in price range data // Add in price range data
id && if (id) {
br.push({ br.push({
type: 'string', type: 'string',
name: 'pricing', name: 'pricing',
@ -412,6 +412,7 @@ export default function PartDetail() {
); );
} }
}); });
}
// Add in stocktake information // Add in stocktake information
if (id && part.last_stocktake) { if (id && part.last_stocktake) {