@@ -7,20 +7,79 @@ import {
77} from '@tanstack/svelte-query' ;
88import { getContext , setContext } from 'svelte' ;
99import type { PartID } from '$lib/part' ;
10- import type { RobotClient } from '@viamrobotics/sdk' ;
10+ import type { PlainMessage , robotApi } from '@viamrobotics/sdk' ;
1111import { usePolling } from './use-polling.svelte' ;
1212import { useQueryLogger } from '$lib/query-logger' ;
1313import { useEnabledQueries } from './use-enabled-queries.svelte' ;
1414
1515const key = Symbol ( 'machine-status-context' ) ;
1616
17- type MachineStatus = Awaited < ReturnType < RobotClient [ 'getMachineStatus' ] > > ;
17+ type MachineStatus = PlainMessage < robotApi . GetMachineStatusResponse > ;
1818type Query = QueryObserverResult < MachineStatus , Error > ;
1919
20+ // TODO: move to ts-sdk
21+ export type ResourceStatus = PlainMessage < robotApi . ResourceStatus > ;
22+
2023interface Context {
2124 current : Record < PartID , Query | undefined > ;
2225}
2326
27+ /**
28+ * sorts machine status resources by local/remote -> type -> name (alphabetical)
29+ * to produce a list like:
30+ *
31+ * component a
32+ * component z
33+ * service b
34+ * component remote:c
35+ * service remote:b
36+ * @param machineStatus
37+ */
38+ const sortResourceStatuses = ( machineStatus : MachineStatus ) => {
39+ const resources = machineStatus . resources . toSorted (
40+ ( { name } , { name : otherName } ) => {
41+ if ( name === undefined && otherName === undefined ) {
42+ return 0 ;
43+ }
44+
45+ if ( name === undefined ) {
46+ return - 1 ;
47+ }
48+
49+ if ( otherName === undefined ) {
50+ return 1 ;
51+ }
52+
53+ const { name : aName , type : aType , subtype : aSubtype } = name ;
54+ const { name : bName , type : bType , subtype : bSubtype } = otherName ;
55+
56+ // sort all non-remote resources before remote resources
57+ if ( aName . includes ( ':' ) !== bName . includes ( ':' ) ) {
58+ return aName . includes ( ':' ) ? 1 : - 1 ;
59+ }
60+
61+ if ( aName === bName && aType === bType ) {
62+ return aSubtype . localeCompare ( bSubtype ) ;
63+ }
64+
65+ if ( aName === bName ) {
66+ return aType . localeCompare ( bType ) ;
67+ }
68+
69+ // sort alphabetically within type
70+ // sort components before services
71+ return aType === bType
72+ ? aName . localeCompare ( bName )
73+ : aType . localeCompare ( bType ) ;
74+ }
75+ ) ;
76+
77+ return {
78+ ...machineStatus ,
79+ resources,
80+ } ;
81+ } ;
82+
2483export const provideMachineStatusContext = ( refetchInterval : ( ) => number ) => {
2584 const clients = useRobotClients ( ) ;
2685 const debug = useQueryLogger ( ) ;
@@ -49,7 +108,7 @@ export const provideMachineStatusContext = (refetchInterval: () => number) => {
49108 try {
50109 const response = await client . getMachineStatus ( ) ;
51110 logger ( 'RES' , 'robot' , 'getMachineStatus' , response ) ;
52- return response ;
111+ return sortResourceStatuses ( response ) ;
53112 } catch ( error ) {
54113 logger ( 'ERR' , 'robot' , 'getMachineStatus' , error ) ;
55114 throw error ;
@@ -96,6 +155,7 @@ export const useMachineStatus = (partID: () => PartID) => {
96155 const error = $derived ( query ?. error ) ;
97156 const fetching = $derived ( query ?. isFetching ) ;
98157 const loading = $derived ( query ?. isLoading ) ;
158+ const pending = $derived ( query ?. isPending ?? true ) ;
99159
100160 return {
101161 get current ( ) {
@@ -110,5 +170,11 @@ export const useMachineStatus = (partID: () => PartID) => {
110170 get loading ( ) {
111171 return loading ;
112172 } ,
173+ get pending ( ) {
174+ return pending ;
175+ } ,
176+ refetch ( ) {
177+ return query ?. refetch ( ) ?? Promise . resolve ( ) ;
178+ } ,
113179 } ;
114180} ;
0 commit comments