1818 * SPDX-License-Identifier: Apache-2.0
1919 */
2020
21- import React , { useEffect , useState , useRef } from "react" ;
21+ import React , {
22+ useEffect ,
23+ useState ,
24+ useRef ,
25+ useCallback ,
26+ Suspense ,
27+ useMemo ,
28+ } from "react" ;
2229import type { Subscription } from "relay-runtime" ;
2330import { FormattedMessage , useIntl } from "react-intl" ;
2431import {
@@ -27,17 +34,24 @@ import {
2734 fetchQuery ,
2835 useRelayEnvironment ,
2936 usePaginationFragment ,
37+ usePreloadedQuery ,
38+ PreloadedQuery ,
39+ UseMutationConfig ,
3040} from "react-relay/hooks" ;
3141
3242import type { SoftwareUpdateTab_PaginationQuery } from "@/api/__generated__/SoftwareUpdateTab_PaginationQuery.graphql" ;
3343import type { SoftwareUpdateTab_otaOperations$key } from "@/api/__generated__/SoftwareUpdateTab_otaOperations.graphql" ;
34- import type { SoftwareUpdateTab_createManualOtaOperation_Mutation } from "@/api/__generated__/SoftwareUpdateTab_createManualOtaOperation_Mutation.graphql" ;
44+ // import type { SoftwareUpdateTab_createManualOtaOperation_Mutation } from "@/api/__generated__/SoftwareUpdateTab_createManualOtaOperation_Mutation.graphql";
3545
3646import Alert from "@/components/Alert" ;
3747import OperationTable from "@/components/OperationTable" ;
3848import Spinner from "@/components/Spinner" ;
3949import { Tab } from "@/components/Tabs" ;
4050import BaseImageForm from "@/forms/BaseImageForm" ;
51+ import { Device_getBaseImageCollections_Query } from "@/api/__generated__/Device_getBaseImageCollections_Query.graphql" ;
52+ import { GET_BASE_IMAGE_COLL_QUERY } from "@/pages/Device" ;
53+ import { SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation , SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation$data } from "@/api/__generated__/SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation.graphql" ;
54+ import { SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation , SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation$data } from "@/api/__generated__/SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation.graphql" ;
4155
4256const DEVICE_OTA_OPERATIONS_FRAGMENT = graphql `
4357 fragment SoftwareUpdateTab_otaOperations on Device
@@ -73,11 +87,11 @@ const GET_DEVICE_OTA_OPERATIONS_QUERY = graphql`
7387 }
7488` ;
7589
76- const DEVICE_CREATE_MANUAL_OTA_OPERATION_MUTATION = graphql `
77- mutation SoftwareUpdateTab_createManualOtaOperation_Mutation (
78- $input: CreateManualOtaOperationInput !
90+ const DEVICE_CREATE_MANUAL_OTA_OPERATION_NO_EXISTING_IMAGE_MUTATION = graphql `
91+ mutation SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation (
92+ $input: CreateManualOtaOperationNoExistingBaseImageInput !
7993 ) {
80- createManualOtaOperation (input: $input) {
94+ createManualOtaOperationNoExistingBaseImage (input: $input) {
8195 result {
8296 id
8397 baseImageUrl
@@ -90,12 +104,47 @@ const DEVICE_CREATE_MANUAL_OTA_OPERATION_MUTATION = graphql`
90104 }
91105` ;
92106
107+ const DEVICE_CREATE_MANUAL_OTA_OPERATION_EXISTING_IMAGE_MUTATION = graphql `
108+ mutation SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation(
109+ $input: CreateManualOtaOperationExistingBaseImageInput!
110+ ) {
111+ createManualOtaOperationExistingBaseImage(input: $input) {
112+ result {
113+ id
114+ baseImageUrl
115+ createdAt
116+ status
117+ statusCode
118+ updatedAt
119+ }
120+ }
121+ }
122+ ` ;
123+
124+ export type GetBaseImageCollsQueryType = PreloadedQuery <
125+ Device_getBaseImageCollections_Query ,
126+ Record < string , unknown >
127+ > ;
128+
129+ type OTAOperationFunctionIncompleteVariables = {
130+ input : {
131+ deviceId : string ;
132+ baseImageFile ?: File ;
133+ baseImageUrl ?: string ;
134+ }
135+ } ;
136+
137+ type OTAOperationFunctionVariables = UseMutationConfig < SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation > [ "variables" ] & UseMutationConfig < SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation > [ "variables" ]
138+ type NoExistingImageMutationName = "createManualOtaOperationNoExistingBaseImage" | "createManualOtaOperationExistingBaseImage"
139+
93140type DeviceSoftwareUpdateTabProps = {
94141 deviceRef : SoftwareUpdateTab_otaOperations$key ;
142+ getBaseImageCollsQuery : GetBaseImageCollsQueryType ;
95143} ;
96144
97145const DeviceSoftwareUpdateTab = ( {
98146 deviceRef,
147+ getBaseImageCollsQuery,
99148} : DeviceSoftwareUpdateTabProps ) => {
100149 const [ isRefreshing , setIsRefreshing ] = useState ( false ) ;
101150 const [ errorFeedback , setErrorFeedback ] = useState < React . ReactNode > ( null ) ;
@@ -109,10 +158,34 @@ const DeviceSoftwareUpdateTab = ({
109158
110159 const deviceId = data . id ;
111160
112- const [ createOtaOperation , isCreatingOtaOperation ] =
113- useMutation < SoftwareUpdateTab_createManualOtaOperation_Mutation > (
114- DEVICE_CREATE_MANUAL_OTA_OPERATION_MUTATION ,
161+ const [ createOtaOperationNoExistingImage , isCreatingOtaOperationNoExistingImage ] =
162+ useMutation < SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation > (
163+ DEVICE_CREATE_MANUAL_OTA_OPERATION_NO_EXISTING_IMAGE_MUTATION ,
115164 ) ;
165+ const [ createOtaOperationExistingImage , isCreatingOtaOperationExistingImage ] =
166+ useMutation < SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation > (
167+ DEVICE_CREATE_MANUAL_OTA_OPERATION_EXISTING_IMAGE_MUTATION ,
168+ ) ;
169+ const pickOTAOperationFunction = useCallback ( ( ...input : Array < File | string > ) => {
170+ const variables : OTAOperationFunctionIncompleteVariables = {
171+ input : {
172+ deviceId,
173+ } ,
174+ }
175+ if ( input . length === 1 ) {
176+ const [ baseImage ] = input ;
177+ if ( baseImage instanceof File ) {
178+ variables . input . baseImageFile = baseImage
179+ return { func : createOtaOperationNoExistingImage , vars : variables as UseMutationConfig < SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation > [ "variables" ] }
180+ }
181+ else if ( typeof baseImage === "string" ) {
182+ variables . input . baseImageUrl = baseImage
183+ return { func : createOtaOperationExistingImage , vars : variables as UseMutationConfig < SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation > [ "variables" ] }
184+ }
185+ }
186+ } , [ createOtaOperationNoExistingImage , createOtaOperationExistingImage ] )
187+
188+ const isCreatingOtaOperation = useMemo ( ( ) => isCreatingOtaOperationNoExistingImage || isCreatingOtaOperationExistingImage , [ isCreatingOtaOperationNoExistingImage , isCreatingOtaOperationExistingImage ] )
116189
117190 const otaOperations = (
118191 data . otaOperations ?. edges ?. map ( ( { node } ) => node ) || [ ]
@@ -186,14 +259,11 @@ const DeviceSoftwareUpdateTab = ({
186259 return null ;
187260 }
188261
189- const launchManualOTAUpdate = ( file : File ) => {
262+ const launchManualOTAUpdate = ( ...input : Array < File | string > ) => {
263+ const { func : createOtaOperation , vars : variables } = pickOTAOperationFunction ( ...input )
264+ console . log ( "vars after picking:" , variables ) ;
190265 createOtaOperation ( {
191- variables : {
192- input : {
193- deviceId,
194- baseImageFile : file ,
195- } ,
196- } ,
266+ variables : variables as OTAOperationFunctionVariables ,
197267 onCompleted ( data , errors ) {
198268 if ( errors ) {
199269 const errorFeedback = errors
@@ -213,7 +283,15 @@ const DeviceSoftwareUpdateTab = ({
213283 ) ;
214284 } ,
215285 updater ( store , data ) {
216- const otaOperationId = data ?. createManualOtaOperation ?. result ?. id ;
286+ if ( data ) {
287+ let mutData : SoftwareUpdateTab_createManualOtaOperationNoExistingBaseImage_Mutation$data [ "createManualOtaOperationNoExistingBaseImage" ] | SoftwareUpdateTab_createManualOtaOperationExistingBaseImage_Mutation$data [ "createManualOtaOperationExistingBaseImage" ] | undefined ;
288+ if ( "createManualOtaOperationNoExistingBaseImage" in data ) {
289+ mutData = data . createManualOtaOperationNoExistingBaseImage
290+ }
291+ else if ( data && "createManualOtaOperationExistingBaseImage" in data ) {
292+ mutData = data . createManualOtaOperationExistingBaseImage
293+ }
294+ const otaOperationId = mutData ?. result ?. id ;
217295 if ( otaOperationId ) {
218296 const otaOperation = store . get ( otaOperationId ) ;
219297 const storedDevice = store . get ( deviceId ) ;
@@ -225,10 +303,16 @@ const DeviceSoftwareUpdateTab = ({
225303 ) ;
226304 }
227305 }
306+ }
228307 } ,
229308 } ) ;
230309 } ;
231310
311+ const baseImageCollections = usePreloadedQuery (
312+ GET_BASE_IMAGE_COLL_QUERY ,
313+ getBaseImageCollsQuery ,
314+ ) ;
315+
232316 return (
233317 < Tab
234318 eventKey = "device-software-update-tab"
@@ -252,11 +336,14 @@ const DeviceSoftwareUpdateTab = ({
252336 >
253337 { errorFeedback }
254338 </ Alert >
255- < BaseImageForm
256- className = "mt-3"
257- onSubmit = { launchManualOTAUpdate }
258- isLoading = { isCreatingOtaOperation }
259- />
339+ < Suspense fallback = { < Spinner /> } >
340+ < BaseImageForm
341+ className = "mt-3"
342+ onManualOTAImageSubmit = { launchManualOTAUpdate }
343+ isLoading = { isCreatingOtaOperation }
344+ baseImageCollectionsData = { baseImageCollections }
345+ />
346+ </ Suspense >
260347 { currentOperation && (
261348 < div className = "mt-3" >
262349 < FormattedMessage
@@ -290,4 +377,18 @@ const DeviceSoftwareUpdateTab = ({
290377 ) ;
291378} ;
292379
380+ export const DisabledDeviceSoftwareTab = ( { } ) => {
381+ const intl = useIntl ( ) ;
382+ return (
383+ < Tab
384+ className = "disabled"
385+ eventKey = "device-software-update-tab"
386+ title = { intl . formatMessage ( {
387+ id : "components.DeviceTabs.SoftwareUpdateTab" ,
388+ defaultMessage : "Software Updates" ,
389+ } ) }
390+ />
391+ ) ;
392+ } ;
393+
293394export default DeviceSoftwareUpdateTab ;
0 commit comments