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