diff --git a/src/frontend/src/components/nav/InstanceDetail.tsx b/src/frontend/src/components/nav/InstanceDetail.tsx index 74584e0b10..d2a95e3a39 100644 --- a/src/frontend/src/components/nav/InstanceDetail.tsx +++ b/src/frontend/src/components/nav/InstanceDetail.tsx @@ -1,37 +1,44 @@ -import { LoadingOverlay } from '@mantine/core'; +import { Center, Container, Loader } from '@mantine/core'; import type { ModelType } from '@lib/enums/ModelType'; import type { UserRoles } from '@lib/enums/Roles'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { useEffect, useState } from 'react'; import { useUserState } from '../../states/UserState'; import ClientError from '../errors/ClientError'; import PermissionDenied from '../errors/PermissionDenied'; import ServerError from '../errors/ServerError'; export default function InstanceDetail({ - status, - loading, + query, children, requiredRole, requiredPermission }: Readonly<{ - status: number; - loading: boolean; + query: UseQueryResult; children: React.ReactNode; requiredRole?: UserRoles; requiredPermission?: ModelType; }>) { const user = useUserState(); - if (loading || !user.isLoggedIn()) { - return ; - } + const [loaded, setLoaded] = useState(false); - if (status >= 500) { - return ; - } + useEffect(() => { + if (query.isSuccess) { + setLoaded(true); + } + }, [query.isSuccess]); - if (status >= 400) { - return ; + if (query.isError) { + const reason = query.failureReason as any; + const statusCode = reason?.response?.status ?? reason?.status ?? 0; + + if (statusCode >= 500) { + return ; + } + + return ; } if (requiredRole && !user.hasViewRole(requiredRole)) { @@ -42,5 +49,16 @@ export default function InstanceDetail({ return ; } + if (!loaded || !user.isLoggedIn()) { + // Return a loader for the first page load + return ( +
+ + + +
+ ); + } + return <>{children}; } diff --git a/src/frontend/src/hooks/UseInstance.tsx b/src/frontend/src/hooks/UseInstance.tsx index b9a81a19ef..4ff36fbc97 100644 --- a/src/frontend/src/hooks/UseInstance.tsx +++ b/src/frontend/src/hooks/UseInstance.tsx @@ -12,7 +12,6 @@ export interface UseInstanceResult { refreshInstance: () => void; refreshInstancePromise: () => Promise>; instanceQuery: any; - requestStatus: number; isLoaded: boolean; } @@ -35,7 +34,6 @@ export function useInstance({ hasPrimaryKey = true, refetchOnMount = true, refetchOnWindowFocus = false, - throwError = false, updateInterval }: { endpoint: ApiEndpoints; @@ -46,15 +44,12 @@ export function useInstance({ defaultValue?: any; refetchOnMount?: boolean; refetchOnWindowFocus?: boolean; - throwError?: boolean; updateInterval?: number; }): UseInstanceResult { const api = useApi(); const [instance, setInstance] = useState(defaultValue); - const [requestStatus, setRequestStatus] = useState(0); - const instanceQuery = useQuery({ queryKey: [ 'instance', @@ -84,7 +79,6 @@ export function useInstance({ params: params }) .then((response) => { - setRequestStatus(response.status); switch (response.status) { case 200: setInstance(response.data); @@ -93,15 +87,6 @@ export function useInstance({ setInstance(defaultValue); return defaultValue; } - }) - .catch((error) => { - setRequestStatus(error.response?.status || 0); - setInstance(defaultValue); - console.error(`ERR: Error fetching instance ${url}:`, error); - - if (throwError) throw error; - - return defaultValue; }); }, refetchOnMount: refetchOnMount, @@ -131,7 +116,6 @@ export function useInstance({ refreshInstance, refreshInstancePromise, instanceQuery, - requestStatus, isLoaded }; } diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index 3f1bf4073b..6d4c43e44b 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -75,8 +75,7 @@ export default function BuildDetail() { const { instance: build, refreshInstance, - instanceQuery, - requestStatus + instanceQuery } = useInstance({ endpoint: ApiEndpoints.build_order_list, pk: id, @@ -621,11 +620,7 @@ export default function BuildDetail() { {holdOrder.modal} {issueOrder.modal} {completeOrder.modal} - + ) { const { instance: company, refreshInstance, - instanceQuery, - requestStatus + instanceQuery } = useInstance({ endpoint: ApiEndpoints.company_list, pk: id, @@ -326,7 +325,10 @@ export default function CompanyDetail(props: Readonly) { <> {editCompany.modal} {deleteCompany.modal} - + + diff --git a/src/frontend/src/pages/core/GroupDetail.tsx b/src/frontend/src/pages/core/GroupDetail.tsx index 2c14f99c7d..4344e36ec4 100644 --- a/src/frontend/src/pages/core/GroupDetail.tsx +++ b/src/frontend/src/pages/core/GroupDetail.tsx @@ -26,7 +26,7 @@ import { useInstance } from '../../hooks/UseInstance'; export default function GroupDetail() { const { id } = useParams(); - const { instance, instanceQuery, requestStatus } = useInstance({ + const { instance, instanceQuery } = useInstance({ endpoint: ApiEndpoints.group_list, pk: id }); @@ -72,7 +72,7 @@ export default function GroupDetail() { }, [instance, id]); return ( - + + diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx index 4b4d7363bd..f14f748e02 100644 --- a/src/frontend/src/pages/part/PartDetail.tsx +++ b/src/frontend/src/pages/part/PartDetail.tsx @@ -130,8 +130,7 @@ export default function PartDetail() { const { instance: part, refreshInstance, - instanceQuery, - requestStatus + instanceQuery } = useInstance({ endpoint: ApiEndpoints.part_list, pk: id, @@ -1028,11 +1027,7 @@ export default function PartDetail() { {orderPartsWizard.wizard} {findBySerialNumber.modal} {transferStockItems.modal} - + {user.hasViewRole(UserRoles.part_category) && ( diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index 74ca9e92a8..10ed323bef 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -59,8 +59,7 @@ export default function ReturnOrderDetail() { const { instance: order, instanceQuery, - refreshInstance, - requestStatus + refreshInstance } = useInstance({ endpoint: ApiEndpoints.return_order_list, pk: id, @@ -499,8 +498,7 @@ export default function ReturnOrderDetail() { {completeOrder.modal} {duplicateReturnOrder.modal} diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx index dca6851ff5..11c7347519 100644 --- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx @@ -68,8 +68,7 @@ export default function SalesOrderDetail() { const { instance: order, instanceQuery, - refreshInstance, - requestStatus + refreshInstance } = useInstance({ endpoint: ApiEndpoints.sales_order_list, pk: id, @@ -563,8 +562,7 @@ export default function SalesOrderDetail() { {editSalesOrder.modal} {duplicateSalesOrder.modal} diff --git a/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx b/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx index 1a4e681e92..bef175b8a4 100644 --- a/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx @@ -52,8 +52,7 @@ export default function SalesOrderShipmentDetail() { const { instance: shipment, instanceQuery: shipmentQuery, - refreshInstance: refreshShipment, - requestStatus: shipmentStatus + refreshInstance: refreshShipment } = useInstance({ endpoint: ApiEndpoints.sales_order_shipment_list, pk: id, @@ -65,8 +64,7 @@ export default function SalesOrderShipmentDetail() { const { instance: customer, instanceQuery: customerQuery, - refreshInstance: refreshCustomer, - requestStatus: customerStatus + refreshInstance: refreshCustomer } = useInstance({ endpoint: ApiEndpoints.company_list, pk: shipment.order_detail?.customer, @@ -351,8 +349,7 @@ export default function SalesOrderShipmentDetail() { {editShipment.modal} {deleteShipment.modal} diff --git a/src/frontend/src/pages/stock/LocationDetail.tsx b/src/frontend/src/pages/stock/LocationDetail.tsx index dcbcaf86d8..64d9d976cd 100644 --- a/src/frontend/src/pages/stock/LocationDetail.tsx +++ b/src/frontend/src/pages/stock/LocationDetail.tsx @@ -64,8 +64,7 @@ export default function Stock() { const { instance: location, refreshInstance, - instanceQuery, - requestStatus + instanceQuery } = useInstance({ endpoint: ApiEndpoints.stock_location_list, hasPrimaryKey: true, @@ -423,8 +422,7 @@ export default function Stock() { {scanInStockItem.dialog} {scanInStockLocation.dialog} diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 56274de468..5abc143d75 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -114,8 +114,7 @@ export default function StockDetail() { instance: stockitem, refreshInstance, refreshInstancePromise, - instanceQuery, - requestStatus + instanceQuery } = useInstance({ endpoint: ApiEndpoints.stock_item_list, pk: id, @@ -1053,9 +1052,8 @@ export default function StockDetail() { {findBySerialNumber.modal} {scanIntoLocation.dialog} {user.hasViewRole(UserRoles.stock_location) && ( diff --git a/src/frontend/src/tables/settings/GroupTable.tsx b/src/frontend/src/tables/settings/GroupTable.tsx index a1be754ccf..110ac32f86 100644 --- a/src/frontend/src/tables/settings/GroupTable.tsx +++ b/src/frontend/src/tables/settings/GroupTable.tsx @@ -45,7 +45,6 @@ export function GroupDrawer({ } = useInstance({ endpoint: ApiEndpoints.group_list, pk: id, - throwError: true, params: { permission_detail: true, role_detail: true, diff --git a/src/frontend/src/tables/settings/TemplateTable.tsx b/src/frontend/src/tables/settings/TemplateTable.tsx index 651219c1e8..3d82f460a1 100644 --- a/src/frontend/src/tables/settings/TemplateTable.tsx +++ b/src/frontend/src/tables/settings/TemplateTable.tsx @@ -80,8 +80,7 @@ export function TemplateDrawer({ } = useInstance({ endpoint: templateEndpoint, hasPrimaryKey: true, - pk: id, - throwError: true + pk: id }); // Editors diff --git a/src/frontend/src/tables/settings/UserTable.tsx b/src/frontend/src/tables/settings/UserTable.tsx index ac4469e51d..e5a3cc146b 100644 --- a/src/frontend/src/tables/settings/UserTable.tsx +++ b/src/frontend/src/tables/settings/UserTable.tsx @@ -68,8 +68,7 @@ export function UserDrawer({ instanceQuery: { isFetching, error } } = useInstance({ endpoint: ApiEndpoints.user_list, - pk: id, - throwError: true + pk: id }); const currentUserPk = useUserState(useShallow((s) => s.user?.pk));