diff --git a/src/components/MyObservations/SimpleUploadBanner.js b/src/components/MyObservations/SimpleUploadBanner.js index 65c3563e2..ab797585f 100644 --- a/src/components/MyObservations/SimpleUploadBanner.js +++ b/src/components/MyObservations/SimpleUploadBanner.js @@ -92,7 +92,7 @@ const SimpleUploadBanner = ( { return ( - {status.text !== "" && renderUploadStatusText( )} + {( status.text !== "" || !!error ) && renderUploadStatusText( )} ); diff --git a/src/components/MyObservations/SimpleUploadBannerContainer.js b/src/components/MyObservations/SimpleUploadBannerContainer.js index 6db3ca7e0..7fc3ec8c2 100644 --- a/src/components/MyObservations/SimpleUploadBannerContainer.js +++ b/src/components/MyObservations/SimpleUploadBannerContainer.js @@ -38,7 +38,6 @@ const SimpleUploadBannerContainer = ( { const currentDeleteCount = useStore( state => state.currentDeleteCount ); const deleteError = useStore( state => state.deleteError ); const uploadMultiError = useStore( state => state.multiError ); - const uploadErrorsByUuid = useStore( state => state.errorsByUuid ); const initialNumObservationsInQueue = useStore( state => state.initialNumObservationsInQueue ); const totalToolbarProgress = useStore( state => state.totalToolbarProgress ); const uploadStatus = useStore( state => state.uploadStatus ); @@ -47,6 +46,8 @@ const SimpleUploadBannerContainer = ( { const stopAllUploads = useStore( state => state.stopAllUploads ); const numUploadsAttempted = useStore( state => state.numUploadsAttempted ); + const totalUploadErrors = useStore( state => state.getTotalUploadErrors() ); + const numUploadedWithoutErrors = useStore( state => state.getNumUploadedWithoutErrors() ); // Note that initialNumObservationsInQueue is the number of obs being uploaded in // the current upload session, so it might be 1 if a single obs is @@ -69,7 +70,6 @@ const SimpleUploadBannerContainer = ( { const pendingUpload = uploadStatus === UPLOAD_PENDING && numUploadableObservations > 0; const uploadInProgress = uploadStatus === UPLOAD_IN_PROGRESS && numUploadsAttempted > 0; const uploadsComplete = uploadStatus === UPLOAD_COMPLETE && initialNumObservationsInQueue > 0; - const totalUploadErrors = Object.keys( uploadErrorsByUuid ).length; const setDeletionsProgress = ( ) => { // TODO: we should emit deletions progress like we do for uploads for an accurate progress @@ -130,8 +130,8 @@ const SimpleUploadBannerContainer = ( { return status; } - if ( uploadsComplete ) { - status.text = t( "X-observations-uploaded", { count: numUploadsAttempted } ); + if ( uploadsComplete && numUploadedWithoutErrors > 0 ) { + status.text = t( "X-observations-uploaded", { count: numUploadedWithoutErrors } ); return status; } @@ -140,7 +140,7 @@ const SimpleUploadBannerContainer = ( { currentDeleteCount, deletionsComplete, initialNumDeletionsInQueue, - numUploadsAttempted, + numUploadedWithoutErrors, numUploadableObservations, pendingUpload, manualSyncInProgress, diff --git a/src/stores/createUploadObservationsSlice.ts b/src/stores/createUploadObservationsSlice.ts index b38efeb4e..692de3fe7 100644 --- a/src/stores/createUploadObservationsSlice.ts +++ b/src/stores/createUploadObservationsSlice.ts @@ -279,7 +279,9 @@ const createUploadObservationsSlice: StateCreator = ( s ? UPLOAD_COMPLETE : UPLOAD_IN_PROGRESS } ); - } ) + } ), + getTotalUploadErrors: () => Object.keys( get().errorsByUuid ).length, + getNumUploadedWithoutErrors: () => get().numUploadsAttempted - get().getTotalUploadErrors() } ); export default createUploadObservationsSlice; diff --git a/tests/unit/components/MyObservations/SimpleUploadBannerContainer.test.js b/tests/unit/components/MyObservations/SimpleUploadBannerContainer.test.js index 906315fe0..4036d0e5f 100644 --- a/tests/unit/components/MyObservations/SimpleUploadBannerContainer.test.js +++ b/tests/unit/components/MyObservations/SimpleUploadBannerContainer.test.js @@ -146,6 +146,71 @@ describe( "SimpleUploadBannerContainer", () => { expect( statusText ).toBeVisible( ); } ); + it( "displays 1 upload completed and 4 failed", () => { + useStore.setState( { + layout: { + isDefaultMode: false + }, + numUploadsAttempted: 5, + uploadStatus: UPLOAD_COMPLETE, + syncingStatus: SYNC_PENDING, + initialNumObservationsInQueue: 5, + errorsByUuid: { + 1: true, 2: true, 3: true, 4: true + } + } ); + renderComponent( ); + + const successText = screen.getByText( /1 observation uploaded/ ); + const errorText = screen.getByText( /4 uploads failed/ ); + expect( successText ).toBeVisible( ); + expect( errorText ).toBeVisible( ); + } ); + + it( "displays only error when all 5 uploads failed", () => { + useStore.setState( { + layout: { + isDefaultMode: false + }, + uploadStatus: UPLOAD_COMPLETE, + syncingStatus: SYNC_PENDING, + initialNumObservationsInQueue: 5, + numUploadsAttempted: 5, + errorsByUuid: { + 1: true, + 2: true, + 3: true, + 4: true, + 5: true + } + } ); + renderComponent( ); + + const errorText = screen.getByText( /5 uploads failed/ ); + expect( errorText ).toBeVisible(); + const successText = screen.queryByText( /1 observation uploaded/ ); + expect( successText ).toBeFalsy(); + } ); + + it( "displays 4 uploads completed and 1 failed", () => { + useStore.setState( { + layout: { + isDefaultMode: false + }, + uploadStatus: UPLOAD_COMPLETE, + syncingStatus: SYNC_PENDING, + initialNumObservationsInQueue: 5, + numUploadsAttempted: 5, + errorsByUuid: { 1: true } + } ); + renderComponent( ); + + const successText = screen.getByText( /4 observations uploaded/ ); + const errorText = screen.getByText( /1 upload failed/ ); + expect( successText ).toBeVisible(); + expect( errorText ).toBeVisible(); + } ); + // 20240611 amanda - removing this test for now, since I believe the new intended UI // is that the user will only ever see "Syncing..." followed by // "1 observation deleted" UI after deleting a local observation. feel free to reinstate this