-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PSP-8103 Warn user that property is part of any disposition file #3968
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,13 +5,15 @@ import { useHistory } from 'react-router-dom'; | |
|
||
import { useMapStateMachine } from '@/components/common/mapFSM/MapStateMachineContext'; | ||
import { useDispositionProvider } from '@/hooks/repositories/useDispositionProvider'; | ||
import { usePimsPropertyRepository } from '@/hooks/repositories/usePimsPropertyRepository'; | ||
import { usePropertyAssociations } from '@/hooks/repositories/usePropertyAssociations'; | ||
import useApiUserOverride from '@/hooks/useApiUserOverride'; | ||
import { useInitialMapSelectorProperties } from '@/hooks/useInitialMapSelectorProperties'; | ||
import { useModalContext } from '@/hooks/useModalContext'; | ||
import { IApiError } from '@/interfaces/IApiError'; | ||
import { ApiGen_Concepts_DispositionFile } from '@/models/api/generated/ApiGen_Concepts_DispositionFile'; | ||
import { UserOverrideCode } from '@/models/api/UserOverrideCode'; | ||
import { featuresetToMapProperty } from '@/utils'; | ||
import { exists, featuresetToMapProperty, isValidId, isValidString } from '@/utils'; | ||
|
||
import { PropertyForm } from '../../shared/models'; | ||
import { DispositionFormModel } from '../models/DispositionFormModel'; | ||
|
@@ -30,11 +32,48 @@ const AddDispositionContainer: React.FC<IAddDispositionContainerProps> = ({ onCl | |
const selectedFeatureDataset = mapMachine.selectedFeatureDataset; | ||
|
||
const { setModalContent, setDisplayModal } = useModalContext(); | ||
const { execute: getPropertyAssociations } = usePropertyAssociations(); | ||
const { | ||
getPropertyByPidWrapper: { execute: getPropertyByPid }, | ||
getPropertyByPinWrapper: { execute: getPropertyByPin }, | ||
} = usePimsPropertyRepository(); | ||
const [needsUserConfirmation, setNeedsUserConfirmation] = useState<boolean>(true); | ||
|
||
const { | ||
addDispositionFileApi: { execute: addDispositionFileApi, loading }, | ||
} = useDispositionProvider(); | ||
|
||
// Warn user that property is part of an existing disposition file | ||
const confirmBeforeAdd = useCallback( | ||
async (propertyForm: PropertyForm): Promise<boolean> => { | ||
let apiId; | ||
try { | ||
if (isValidId(propertyForm.apiId)) { | ||
apiId = propertyForm.apiId; | ||
} else if (isValidString(propertyForm.pid)) { | ||
const result = await getPropertyByPid(propertyForm.pid); | ||
apiId = result?.id; | ||
} else if (isValidString(propertyForm.pin)) { | ||
const result = await getPropertyByPin(Number(propertyForm.pin)); | ||
apiId = result?.id; | ||
} | ||
} catch (e) { | ||
apiId = 0; | ||
} | ||
|
||
if (isValidId(apiId)) { | ||
const response = await getPropertyAssociations(apiId); | ||
const fileAssociations = response?.dispositionAssociations ?? []; | ||
const otherFiles = fileAssociations.filter(a => exists(a.id)); | ||
return otherFiles.length > 0; | ||
} else { | ||
// the property is not in PIMS db -> no need to confirm | ||
return false; | ||
} | ||
}, | ||
[getPropertyAssociations, getPropertyByPid, getPropertyByPin], | ||
); | ||
|
||
const initialForm = useMemo(() => { | ||
const dispositionForm = new DispositionFormModel(); | ||
// support creating a new disposition file from the map popup | ||
|
@@ -55,12 +94,58 @@ const AddDispositionContainer: React.FC<IAddDispositionContainerProps> = ({ onCl | |
initialForm.fileProperties[0].address = initialProperty.address; | ||
} | ||
|
||
// Require user confirmation before adding a property to file | ||
// This is the flow for Map Marker -> right-click -> create Disposition File | ||
useEffect(() => { | ||
if (!!initialForm && !!formikRef.current) { | ||
formikRef.current.resetForm(); | ||
formikRef.current?.setFieldValue('fileProperties', initialForm.fileProperties); | ||
} | ||
}, [initialForm]); | ||
const runAsync = async () => { | ||
if (exists(initialForm) && exists(formikRef.current) && needsUserConfirmation) { | ||
if (initialForm.fileProperties.length > 0) { | ||
const formProperty = initialForm.fileProperties[0]; | ||
if (await confirmBeforeAdd(formProperty)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love the name of this function. Confirm what before Add? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Open to suggestions on better naming. I believe you created a similar "canDelete" in the same area of code but "canAdd" did not make sense to me. |
||
setModalContent({ | ||
variant: 'warning', | ||
title: 'User Override Required', | ||
message: ( | ||
<> | ||
<p>This property has already been added to one or more disposition files.</p> | ||
<p>Do you want to acknowledge and proceed?</p> | ||
</> | ||
), | ||
okButtonText: 'Yes', | ||
cancelButtonText: 'No', | ||
handleOk: () => { | ||
// allow the property to be added to the file being created | ||
formikRef.current.resetForm(); | ||
formikRef.current.setFieldValue('fileProperties', initialForm.fileProperties); | ||
setDisplayModal(false); | ||
// show the user confirmation modal only once when creating a file | ||
setNeedsUserConfirmation(false); | ||
}, | ||
handleCancel: () => { | ||
// clear out the properties array as the user did not agree to the popup | ||
initialForm.fileProperties.splice(0, initialForm.fileProperties.length); | ||
formikRef.current.resetForm(); | ||
formikRef.current.setFieldValue('fileProperties', initialForm.fileProperties); | ||
setDisplayModal(false); | ||
// show the user confirmation modal only once when creating a file | ||
setNeedsUserConfirmation(false); | ||
}, | ||
}); | ||
setDisplayModal(true); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
runAsync(); | ||
}, [ | ||
confirmBeforeAdd, | ||
initialForm, | ||
needsUserConfirmation, | ||
setDisplayModal, | ||
setModalContent, | ||
bcaLoading, | ||
]); | ||
|
||
const handleCancel = useCallback(() => onClose && onClose(), [onClose]); | ||
|
||
|
@@ -109,6 +194,7 @@ const AddDispositionContainer: React.FC<IAddDispositionContainerProps> = ({ onCl | |
dispositionInitialValues={initialForm} | ||
loading={loading || bcaLoading} | ||
displayFormInvalid={!isFormValid} | ||
confirmBeforeAdd={confirmBeforeAdd} | ||
onSave={handleSave} | ||
onCancel={handleCancel} | ||
onSubmit={( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems like this function has more to do with properties then acquisition files, would recommend moving this to a shared space to reduce code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would need to handle the associations for each type, perhaps via a param? not strictly necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with the code duplication - have to to think about that. Given that we are so close to sprint end I would lean towards merging as-is (if not broken) and then refactoring next sprint