Skip to content

Commit

Permalink
Allow single observation deletion when editing multiple (#1285)
Browse files Browse the repository at this point in the history
  • Loading branch information
kueda authored Mar 18, 2024
1 parent 4e32f10 commit c0bd48c
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 41 deletions.
24 changes: 18 additions & 6 deletions src/components/ObsEdit/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,25 @@ const Header = ( {
setDeleteSheetVisible( true );
setKebabMenuVisible( false );
}}
title={
observations.length > 1
? t( "Delete-observations" )
: t( "Delete-observation" )
}
title={t( "Delete-observation" )}
/>
{ observations.length > 1 && (
<Menu.Item
testID="Header.delete-all-observation"
onPress={( ) => {
setDiscardObservationSheetVisible( true );
setKebabMenuVisible( false );
}}
title={t( "Delete-all-observations" )}
/>
) }
</KebabMenu>
), [kebabMenuVisible, observations, t, setDeleteSheetVisible] );
), [
kebabMenuVisible,
observations,
setDeleteSheetVisible,
t
] );

return (
<View className="flex-row justify-between items-center">
Expand All @@ -176,6 +187,7 @@ const Header = ( {
navToObsList={navToObsList}
observations={observations}
currentObservation={currentObservation}
updateObservations={updateObservations}
/>
)}
{discardObservationSheetVisible && (
Expand Down
49 changes: 24 additions & 25 deletions src/components/ObsEdit/Sheets/DeleteObservationSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,25 @@ import {
import { RealmContext } from "providers/contexts";
import type { Node } from "react";
import React, { useCallback } from "react";
import { log } from "sharedHelpers/logger";
import safeRealmWrite from "sharedHelpers/safeRealmWrite";
import { useTranslation } from "sharedHooks";

const { useRealm } = RealmContext;

const logger = log.extend( "DeleteObservationSheet" );

type Props = {
currentObservation: Object,
handleClose: Function,
navToObsList: Function,
currentObservation: Object,
observations: Array<Object>
observations: Array<Object>,
updateObservations: Function
}

const DeleteObservationSheet = ( {
currentObservation,
handleClose,
navToObsList,
currentObservation,
observations
observations,
updateObservations
}: Props ): Node => {
const { t } = useTranslation( );
const realm = useRealm( );
Expand All @@ -35,35 +34,35 @@ const DeleteObservationSheet = ( {

const addObservationToDeletionQueue = useCallback( ( ) => {
const localObsToDelete = realm.objectForPrimaryKey( "Observation", uuid );
if ( !localObsToDelete ) {
logger.info(
"Observation to delete is not saved in realm; returning to MyObservations"
);
navToObsList( );
} else {
logger.info( "Observation to add to deletion queue: ", localObsToDelete.uuid );
if ( localObsToDelete ) {
safeRealmWrite( realm, ( ) => {
localObsToDelete._deleted_at = new Date( );
}, "adding _deleted_at date in DeleteObservationSheet" );
logger.info(
"Observation added to deletion queue; returning to MyObservations"
);
navToObsList( );
}
}, [uuid, realm, navToObsList] );
if ( multipleObservations ) {
updateObservations( observations.filter( o => o.uuid !== uuid ) );
handleClose( );
return;
}
navToObsList( );
}, [
handleClose,
multipleObservations,
navToObsList,
observations,
realm,
updateObservations,
uuid
] );

return (
<WarningSheet
handleClose={handleClose}
headerText={multipleObservations
? t( "DELETE-X-OBSERVATIONS", { count: observations.length } )
: t( "DELETE-OBSERVATION" )}
headerText={t( "DELETE-OBSERVATION" )}
handleSecondButtonPress={handleClose}
secondButtonText={t( "CANCEL" )}
confirm={addObservationToDeletionQueue}
buttonText={multipleObservations
? t( "DELETE-ALL" )
: t( "DELETE" )}
buttonText={t( "DELETE" )}
/>
);
};
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/l10n/en.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ Delete-comment = Delete comment
DELETE-OBSERVATION = DELETE OBSERVATION?
Delete-all-observations = Delete all observations
Delete-observation = Delete observation
Delete-observations = Delete observations
Expand Down
1 change: 1 addition & 0 deletions src/i18n/l10n/en.ftl.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
"DELETE-COMMENT-QUESTION": "DELETE COMMENT?",
"Delete-comment": "Delete comment",
"DELETE-OBSERVATION": "DELETE OBSERVATION?",
"Delete-all-observations": "Delete all observations",
"Delete-observation": "Delete observation",
"Delete-observations": "Delete observations",
"DELETE-X-OBSERVATIONS": "DELETE { $count ->\n [one] 1 OBSERVATION?\n *[other] { $count } OBSERVATIONS?\n}",
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/strings.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ Delete-comment = Delete comment
DELETE-OBSERVATION = DELETE OBSERVATION?
Delete-all-observations = Delete all observations
Delete-observation = Delete observation
Delete-observations = Delete observations
Expand Down
44 changes: 34 additions & 10 deletions tests/unit/components/ObsEdit/DeleteObservationSheet.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import inatjs from "inaturalistjs";
import React from "react";
import safeRealmWrite from "sharedHelpers/safeRealmWrite";
import factory from "tests/factory";
import faker from "tests/helpers/faker";
import { renderComponent } from "tests/helpers/render";

const observations = [factory( "LocalObservation", {
Expand All @@ -14,6 +13,8 @@ const observations = [factory( "LocalObservation", {

const currentObservation = observations[0];

const mockUpdateObservations = jest.fn( );

afterEach( ( ) => {
jest.clearAllMocks( );
} );
Expand All @@ -22,9 +23,11 @@ const mockNavigate = jest.fn( );

const renderDeleteSheet = ( ) => renderComponent(
<DeleteObservationSheet
handleClose={jest.fn( )}
navToObsList={mockNavigate}
currentObservation={currentObservation}
observations={observations}
updateObservations={mockUpdateObservations}
/>
);

Expand Down Expand Up @@ -67,23 +70,44 @@ describe( "delete observation", ( ) => {
} );
} );

describe( "handles multiple observation deletion", ( ) => {
it( "navigates back to MyObservations when observations are not in realm", ( ) => {
const unsavedObservations = [{
uuid: faker.string.uuid( )
}, {
uuid: faker.string.uuid( )
}];
it( "navigates back when there's only one observation", ( ) => {
expect( observations.length ).toEqual( 1 );
renderDeleteSheet( );
const deleteButton = screen.queryByText( "DELETE" );
fireEvent.press( deleteButton );
expect( mockNavigate ).toBeCalled( );
} );

describe( "with multiple observations", ( ) => {
const unsavedObservations = [
factory( "LocalObservation" ),
factory( "LocalObservation" )
];

function renderDeleteSheetWithMultiple( ) {
renderComponent(
<DeleteObservationSheet
handleClose={jest.fn( )}
navToObsList={mockNavigate}
currentObservation={unsavedObservations[0]}
observations={unsavedObservations}
updateObservations={mockUpdateObservations}
/>
);
const deleteButton = screen.queryByText( /DELETE ALL/ );
}

it( "does not navigate back when there's more than one observation", ( ) => {
renderDeleteSheetWithMultiple( );
const deleteButton = screen.queryByText( "DELETE" );
fireEvent.press( deleteButton );
expect( mockNavigate ).not.toBeCalled( );
} );

it( "removes observation from state when there's more than one observation", ( ) => {
renderDeleteSheetWithMultiple( );
const deleteButton = screen.queryByText( "DELETE" );
fireEvent.press( deleteButton );
expect( mockNavigate ).toBeCalled( );
expect( mockUpdateObservations ).toBeCalledWith( [unsavedObservations[1]] );
} );
} );
} );

0 comments on commit c0bd48c

Please sign in to comment.