diff --git a/src/client/components/DataSources/DataSources.tsx b/src/client/components/DataSources/DataSources.tsx index b3346a3a4e..084d69f4ce 100644 --- a/src/client/components/DataSources/DataSources.tsx +++ b/src/client/components/DataSources/DataSources.tsx @@ -6,6 +6,7 @@ import { Objects } from 'utils/objects' import { useCycleRouteParams } from 'client/hooks/routeParams' import { useIsPrintRoute } from 'client/hooks/routes' +import Button, { ButtonSize } from 'client/components/Buttons/Button' import { DataCell, DataGrid } from 'client/components/DataGrid' import DataSourceRow from 'client/components/DataSources/DataSourceRow' import HistoryCompare from 'client/components/DataSources/HistoryCompare' @@ -32,6 +33,7 @@ export const DataSources: React.FC = (props: PropsDataSources) dataSourcesLinked, historyCompares, meta, + onAdd, onChange, onDelete, options = defaults.options, @@ -46,7 +48,6 @@ export const DataSources: React.FC = (props: PropsDataSources) const gridTemplateColumns = useGridTemplateColumns({ options }) const textEmpty = useMemo(() => DOMs.isHTMLEmpty(text), [text]) - const hasPlaceholder = useMemo(() => Boolean(dataSources?.find((d) => d.placeholder)), [dataSources]) const hasDataSources = !Objects.isEmpty(dataSources) || !Objects.isEmpty(dataSourcesLinked) const renderGrid = Boolean(hasDataSources || canEdit) @@ -104,25 +105,27 @@ export const DataSources: React.FC = (props: PropsDataSources) ))} {!displayHistory && - dataSources.map((dataSourceValue, i) => { - if (!canEdit && dataSourceValue.placeholder) return null - - return ( - - ) - })} + dataSources.map((dataSourceValue, i) => ( + + ))} + {canEdit && !displayHistory && ( +
+
+ )} + {meta?.text?.readOnly && canEdit && !textEmpty && (
{t('nationalDataPoint.dataSource2025ExplanatoryText')}
diff --git a/src/client/components/DataSources/hooks/useDataSourceActions.ts b/src/client/components/DataSources/hooks/useDataSourceActions.ts index 50947e7a9b..4f39067ee1 100644 --- a/src/client/components/DataSources/hooks/useDataSourceActions.ts +++ b/src/client/components/DataSources/hooks/useDataSourceActions.ts @@ -31,7 +31,7 @@ export const useDataSourceActions = (props: Props): Array => { return useMemo>(() => { const actions: Array = [] - if (readOnly || dataSource.placeholder) return actions + if (readOnly) return actions if (canEdit) { actions.push({ type: DataRowActionType.Delete, onClick: () => onDelete(dataSource) }) diff --git a/src/client/components/DataSources/types.ts b/src/client/components/DataSources/types.ts index b6096c24d8..7bd016444d 100644 --- a/src/client/components/DataSources/types.ts +++ b/src/client/components/DataSources/types.ts @@ -28,6 +28,7 @@ export type PropsDataSources = { dataSourcesLinked?: Array historyCompares?: Array meta?: DataSourceDescription + onAdd: () => void onChange: DataSourceOnChange onDelete: DataSourceOnDelete options?: { diff --git a/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/DataSourcesV2.tsx b/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/DataSourcesV2.tsx index 4fce93a0a5..0ba1b9c393 100644 --- a/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/DataSourcesV2.tsx +++ b/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/DataSourcesV2.tsx @@ -7,8 +7,8 @@ import { useOptionsMethodsUsed } from 'client/pages/OriginalDataPoint/components import { useODPDisplayHistory } from 'client/pages/OriginalDataPoint/components/hooks/useODPDisplayHistory' import { useIsEditODPEnabled } from 'client/pages/OriginalDataPoint/hooks/useIsEditODPEnabled' -import { useDataSourcesData } from './hooks/useDataSourcesData' import { useDataSourcesHistoryLastApproved } from './hooks/useDataSourcesHistoryLastApproved' +import { useOnAdd } from './hooks/useOnAdd' import { useOnChange } from './hooks/useOnChange' import { useOnDelete } from './hooks/useOnDelete' @@ -20,20 +20,21 @@ const DataSourcesV2: React.FC = (props) => { const { originalDataPoint } = props const canEdit = useIsEditODPEnabled() - const dataSourcesData = useDataSourcesData({ originalDataPoint }) const options = useOptionsMethodsUsed() + const onAdd = useOnAdd({ originalDataPoint }) const onChange = useOnChange({ originalDataPoint }) const onDelete = useOnDelete({ originalDataPoint }) - const { dataSources } = dataSourcesData + const { dataSources = [] } = originalDataPoint const historyCompares = useDataSourcesHistoryLastApproved({ dataSources }) const displayHistory = useODPDisplayHistory() return ( { - const { originalDataPoint } = props - const { dataSources = [] } = originalDataPoint - - return useMemo(() => { - const placeholder: DataSource = { comments: '', placeholder: true, reference: '', type: [], uuid: UUIDs.getUuid() } - - return { dataSources: [...dataSources, placeholder] } - }, [dataSources]) -} diff --git a/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useDataSourcesHistoryLastApproved.ts b/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useDataSourcesHistoryLastApproved.ts index d50152a29a..2a231524f7 100644 --- a/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useDataSourcesHistoryLastApproved.ts +++ b/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useDataSourcesHistoryLastApproved.ts @@ -22,8 +22,7 @@ export const useDataSourcesHistoryLastApproved = (props: Props): Returned => { if (!historyLastApprovedIsActive) return undefined const dataSourcesHistory = lastApprovedODP?.dataSources ?? [] - const dataSourcesWithoutPlaceholder = dataSources.filter((ds) => !ds.placeholder) - return DataSources.getHistoryCompares({ dataSources: dataSourcesWithoutPlaceholder, dataSourcesHistory }) + return DataSources.getHistoryCompares({ dataSources, dataSourcesHistory }) }, [dataSources, historyLastApprovedIsActive, lastApprovedODP]) } diff --git a/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useOnAdd.ts b/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useOnAdd.ts new file mode 100644 index 0000000000..e0a90c059f --- /dev/null +++ b/src/client/pages/OriginalDataPoint/components/DataSources/DataSourcesV2/hooks/useOnAdd.ts @@ -0,0 +1,25 @@ +import { useCallback } from 'react' + +import { DataSource } from 'meta/assessment/descriptionValue/dataSource' +import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { UUIDs } from 'meta/uuid/uuids' + +import { useUpdateDataSources } from 'client/pages/OriginalDataPoint/components/DataSources/hooks/useUpdateDataSources' + +type Props = { + originalDataPoint: OriginalDataPoint +} + +type Returned = () => void + +export const useOnAdd = (props: Props): Returned => { + const { originalDataPoint } = props + + const updateDataSources = useUpdateDataSources({ originalDataPoint }) + + return useCallback(() => { + const dataSource: DataSource = { comments: '', reference: '', type: [], uuid: UUIDs.getUuid() } + const dataSourcesUpdate = [...(originalDataPoint.dataSources ?? []), dataSource] + updateDataSources(dataSourcesUpdate) + }, [originalDataPoint.dataSources, updateDataSources]) +} diff --git a/src/client/pages/OriginalDataPoint/components/ExtentOfForest/ExtentOfForest.tsx b/src/client/pages/OriginalDataPoint/components/ExtentOfForest/ExtentOfForest.tsx index 488c97f4e5..e299191703 100644 --- a/src/client/pages/OriginalDataPoint/components/ExtentOfForest/ExtentOfForest.tsx +++ b/src/client/pages/OriginalDataPoint/components/ExtentOfForest/ExtentOfForest.tsx @@ -28,7 +28,7 @@ const ExtentOfForest: React.FC = (props) => { const { t } = useTranslation() const { print } = useIsPrintRoute() - const nationalClasses = originalDataPoint.nationalClasses.filter((nationalClass) => !nationalClass.placeHolder) + const { nationalClasses } = originalDataPoint const nationalClassValidations = nationalClasses.map((_, index) => ODPs.validateNationalClass(originalDataPoint, index) diff --git a/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristics.tsx b/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristics.tsx index 65a2af9420..95001cb72f 100644 --- a/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristics.tsx +++ b/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristics.tsx @@ -66,7 +66,7 @@ const ForestCharacteristics: React.FC = (props) => { const { historyHasNaturallyRegeneratingForest, historyHasPlantationForest } = useHistoryHasNaturallyRegeneratingAndPlantationForest() - const nationalClasses = originalDataPoint.nationalClasses.filter((nationalClass) => !nationalClass.placeHolder) + const { nationalClasses } = originalDataPoint const plantationTotal = ODPs.calcTotalSubFieldArea({ originalDataPoint, field: 'forestPercent', diff --git a/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsNaturallyRegenerating.tsx b/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsNaturallyRegenerating.tsx index aecd95eecc..c99dddc22e 100644 --- a/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsNaturallyRegenerating.tsx +++ b/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsNaturallyRegenerating.tsx @@ -1,10 +1,9 @@ import React from 'react' import { useTranslation } from 'react-i18next' -import { Numbers } from 'utils/numbers' - import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { Numbers } from 'utils/numbers' import DiffText from 'client/components/DiffText' import { useODPDisplayHistory } from 'client/pages/OriginalDataPoint/components/hooks/useODPDisplayHistory' @@ -22,7 +21,7 @@ const ForestCharacteristicsNaturallyRegenerating: React.FC = (props) => { const { canEditData, originalDataPoint } = props const { t } = useTranslation() - const nationalClasses = originalDataPoint?.nationalClasses.filter((nationalClass) => !nationalClass.placeHolder) + const nationalClasses = originalDataPoint?.nationalClasses const totalForestNaturalPercentArea = originalDataPoint && diff --git a/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsPlantation.tsx b/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsPlantation.tsx index aaeb9c6571..b055362c1c 100644 --- a/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsPlantation.tsx +++ b/src/client/pages/OriginalDataPoint/components/ForestCharacteristics/ForestCharacteristicsPlantation.tsx @@ -1,10 +1,9 @@ import React from 'react' import { useTranslation } from 'react-i18next' -import { Numbers } from 'utils/numbers' - import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { Numbers } from 'utils/numbers' import DiffText from 'client/components/DiffText' import { useODPDisplayHistory } from 'client/pages/OriginalDataPoint/components/hooks/useODPDisplayHistory' @@ -21,7 +20,7 @@ const ForestCharacteristicsPlantation: React.FC = (props) => { const { canEditData, originalDataPoint } = props const { t } = useTranslation() - const nationalClasses = originalDataPoint?.nationalClasses.filter((nationalClass) => !nationalClass.placeHolder) + const nationalClasses = originalDataPoint?.nationalClasses const totalForestPlantationPercentArea = originalDataPoint && diff --git a/src/client/pages/OriginalDataPoint/components/NationalClasses/NationalClasses.tsx b/src/client/pages/OriginalDataPoint/components/NationalClasses/NationalClasses.tsx index ac791c218d..41828a57ce 100644 --- a/src/client/pages/OriginalDataPoint/components/NationalClasses/NationalClasses.tsx +++ b/src/client/pages/OriginalDataPoint/components/NationalClasses/NationalClasses.tsx @@ -2,6 +2,7 @@ import React, { useRef } from 'react' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import CreateNationalClass from './components/CreateNationalClass' import { NationalClassesTable } from './components/NationalClassesTable' import { Prefill } from './components/Prefill' import { Title } from './components/Title' @@ -21,6 +22,7 @@ const NationalClasses: React.FC = (props) => { <Prefill canEditData={canEditData} originalDataPoint={originalDataPoint} /> <NationalClassesTable gridRef={gridRef} originalDataPoint={originalDataPoint} /> + <CreateNationalClass canEditData={canEditData} /> </div> ) } diff --git a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/CreateNationalClass.tsx b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/CreateNationalClass.tsx new file mode 100644 index 0000000000..9665bdf30d --- /dev/null +++ b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/CreateNationalClass.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' + +import { useIsOriginalDataPointUpdating } from 'client/store/data/originalDataPoint/hooks/originalDataPoint' +import Button, { ButtonSize } from 'client/components/Buttons/Button' + +import { useOnClick } from './hooks/useOnClick' + +type Props = { + canEditData: boolean +} + +const CreateNationalClass: React.FC<Props> = (props) => { + const { canEditData } = props + + const { t } = useTranslation() + const originalDataPointUpdating = useIsOriginalDataPointUpdating() + const onClick = useOnClick() + + if (!canEditData) { + return null + } + + return ( + <Button + disabled={originalDataPointUpdating} + iconName="small-add" + label={t('common.add')} + onClick={onClick} + size={ButtonSize.xs} + /> + ) +} + +export default CreateNationalClass diff --git a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/hooks/useOnClick.ts b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/hooks/useOnClick.ts new file mode 100644 index 0000000000..807cad035c --- /dev/null +++ b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/hooks/useOnClick.ts @@ -0,0 +1,18 @@ +import { useCallback } from 'react' + +import { ODPNationalClassFactory } from 'meta/assessment/originalDataPoint' + +import { useOriginalDataPoint } from 'client/store/data/originalDataPoint/hooks/originalDataPoint' +import { useUpdateNationalClasses } from 'client/pages/OriginalDataPoint/components/NationalClasses/components/hooks/useUpdateNationalClasses' + +type Returned = () => void + +export const useOnClick = (): Returned => { + const originalDataPoint = useOriginalDataPoint() + const updateNationalClasses = useUpdateNationalClasses() + + return useCallback<Returned>(() => { + const nationalClasses = [...originalDataPoint.nationalClasses, ODPNationalClassFactory.newNationalClass()] + updateNationalClasses({ ...originalDataPoint, nationalClasses }) + }, [originalDataPoint, updateNationalClasses]) +} diff --git a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/index.ts b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/index.ts new file mode 100644 index 0000000000..985b729816 --- /dev/null +++ b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/CreateNationalClass/index.ts @@ -0,0 +1 @@ +export { default } from './CreateNationalClass' diff --git a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/NationalClass.tsx b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/NationalClass.tsx index 21101725f4..667ab71fca 100644 --- a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/NationalClass.tsx +++ b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/NationalClass.tsx @@ -4,17 +4,13 @@ import { useTranslation } from 'react-i18next' import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' -import { useIsPrintRoute } from 'client/hooks/routes' import { DataCell, DataRow } from 'client/components/DataGrid' import InputText from 'client/components/Inputs/InputText' import TextArea from 'client/components/Inputs/TextArea' import { useODPDisplayHistory } from 'client/pages/OriginalDataPoint/components/hooks/useODPDisplayHistory' import ODPDiffText from 'client/pages/OriginalDataPoint/components/ODPDiffText/ODPDiffText' // import { useNationalClassNameComments } from 'client/pages/OriginalDataPoint/hooks' -import { - useIsEditODPDescriptionEnabled, - useIsEditODPEnabled, -} from 'client/pages/OriginalDataPoint/hooks/useIsEditODPEnabled' +import { useIsEditODPDescriptionEnabled } from 'client/pages/OriginalDataPoint/hooks/useIsEditODPEnabled' import { useOnChangeNationalClass } from './hooks/onChangeNationalClass' import { useRowActions } from './hooks/useRowActions' @@ -29,18 +25,16 @@ const NationalClass: React.FC<Props> = (props) => { const { nationalClasses } = originalDataPoint const nationalClass = nationalClasses[index] - const { definition, name, placeHolder } = nationalClass + const { definition, name } = nationalClass const { t } = useTranslation() - const { print } = useIsPrintRoute() - const canEditOdp = useIsEditODPEnabled() const canEditDescription = useIsEditODPDescriptionEnabled() const actions = useRowActions({ index, originalDataPoint }) const { onChangeDefinition, onChangeName, onPasteDefinition, onPasteName } = useOnChangeNationalClass({ index }) const displayHistory = useODPDisplayHistory() - const lastRow = canEditOdp && !print ? placeHolder : index === nationalClasses.length - (print ? 1 : 2) + const lastRow = index === nationalClasses.length - 1 // TODO next pr // const target = [originalDataPoint.id, 'class', `${uuid}`, 'definition'] as string[] // const classNameRowComments = useNationalClassNameComments(target) @@ -48,11 +42,6 @@ const NationalClass: React.FC<Props> = (props) => { const nationalClassValidation = ODPs.validateNationalClass(originalDataPoint, index) const error = !nationalClassValidation.validClassName - // Hide placeholder row if user doesn't have table data permission (prevents adding new items) - if (!canEditOdp && placeHolder) { - return null - } - return ( <DataRow actions={actions}> <DataCell error={error} lastRow={lastRow}> @@ -67,7 +56,7 @@ const NationalClass: React.FC<Props> = (props) => { disabled={!canEditDescription} onChange={onChangeName} onPaste={onPasteName} - placeholder={placeHolder && index === 0 ? t('nationalDataPoint.enterOrCopyPasteNationalClasses') : ''} + placeholder={index === 0 ? t('nationalDataPoint.enterOrCopyPasteNationalClasses') : ''} value={name ?? ''} /> )} diff --git a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/hooks/useRowActions.ts b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/hooks/useRowActions.ts index b6919d6ba8..463202910d 100644 --- a/src/client/pages/OriginalDataPoint/components/NationalClasses/components/hooks/useRowActions.ts +++ b/src/client/pages/OriginalDataPoint/components/NationalClasses/components/hooks/useRowActions.ts @@ -22,11 +22,10 @@ export const useRowActions = (props: Props): Returned => { const { t } = useTranslation() const deleteNationalClass = useDeleteNationalClass({ index, originalDataPoint }) - const { name, placeHolder, uuid } = originalDataPoint.nationalClasses[index] + const { name, uuid } = originalDataPoint.nationalClasses[index] const odpId = originalDataPoint.id - const canEditData = useIsEditODPEnabled() - const canEdit = canEditData && !placeHolder - const showReviewIndicator = useShowReviewIndicator() && !placeHolder + const canEdit = useIsEditODPEnabled() + const showReviewIndicator = useShowReviewIndicator() return useMemo<Returned>(() => { const actions: Returned = [] diff --git a/src/client/pages/Section/Contacts/CreateContact/CreateContact.tsx b/src/client/pages/Section/Contacts/CreateContact/CreateContact.tsx index cd1fb40ab0..fd92c3f495 100644 --- a/src/client/pages/Section/Contacts/CreateContact/CreateContact.tsx +++ b/src/client/pages/Section/Contacts/CreateContact/CreateContact.tsx @@ -11,7 +11,7 @@ const CreateContact: React.FC = () => { return ( <div> - <Button disabled={loading} iconName="small-add" label={t('common.add')} onClick={onClick} size={ButtonSize.m} /> + <Button disabled={loading} iconName="small-add" label={t('common.add')} onClick={onClick} size={ButtonSize.xs} /> </div> ) } diff --git a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/NationalDataSources.tsx b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/NationalDataSources.tsx index b5489eb162..621e6e35f2 100644 --- a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/NationalDataSources.tsx +++ b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/NationalDataSources.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import { DataSourceDescription } from 'meta/assessment/description' import { CommentableDescriptionName } from 'meta/assessment/descriptionValue' +import { Objects } from 'utils/objects' import { useHistoryLastApprovedDescriptionFetched } from 'client/store/data/history/hooks/lastApprovedDescriptions' import { useCanEditDescription, useIsDescriptionEditable } from 'client/store/user/hooks/auth' @@ -18,6 +19,7 @@ import { useDataSourcesHistoryActivities } from './hooks/useDataSourcesHistoryAc import { useDataSourcesHistoryLastApproved } from './hooks/useDataSourcesHistoryLastApproved' import { useDataSourceValidator } from './hooks/useDataSourceValidator' import { useGetDataSourcesLinked } from './hooks/useGetDataSourcesLinked' +import { useOnAdd } from './hooks/useOnAdd' import { useOnChange } from './hooks/useOnChange' import { useOnDelete } from './hooks/useOnDelete' @@ -38,6 +40,7 @@ const NationalDataSources: React.FC<Props> = (props) => { const validator = useDataSourceValidator() const canReview = useCanEditDescription({ sectionName }) const canEdit = useIsDescriptionEditable({ sectionName, name }) + const onAdd = useOnAdd({ sectionName }) const onChange = useOnChange({ sectionName }) const onDelete = useOnDelete({ sectionName }) @@ -64,7 +67,7 @@ const NationalDataSources: React.FC<Props> = (props) => { return ( <DataGrid className="description" withActions={canEdit || canReview}> <Title - canCopy={{ disabled: dataSources.length !== 1 }} + canCopy={{ disabled: !Objects.isEmpty(dataSources) }} name={name} sectionName={sectionName} title={t('description.dataSourcesPlus')} @@ -75,6 +78,7 @@ const NationalDataSources: React.FC<Props> = (props) => { dataSourcesLinked={dataSourcesLinked} historyCompares={historyCompares} meta={meta} + onAdd={onAdd} onChange={onChange} onDelete={onDelete} options={options} diff --git a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourceValidator.ts b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourceValidator.ts index 4584d6c7b8..e042f59ffc 100644 --- a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourceValidator.ts +++ b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourceValidator.ts @@ -11,9 +11,7 @@ export const useDataSourceValidator = (): DataSourceValidator => { return useCallback<DataSourceValidator>( (dataSource) => { - const { placeholder, reference, type, variables, year } = dataSource - - if (placeholder) return {} + const { reference, type, variables, year } = dataSource const getErrorMessage = (value: DataSource[keyof DataSource]): string => { if (Objects.isEmpty(value)) return t('generalValidation.notEmpty') diff --git a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourcesData.ts b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourcesData.ts index 22916c5e58..ad028492fd 100644 --- a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourcesData.ts +++ b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useDataSourcesData.ts @@ -3,7 +3,6 @@ import { useMemo } from 'react' import { CommentableDescriptionName } from 'meta/assessment/descriptionValue' import { DataSource } from 'meta/assessment/descriptionValue/dataSource' import { SectionName } from 'meta/assessment/section' -import { UUIDs } from 'meta/uuid/uuids' import { useCommentableDescriptionValue } from 'client/store/data/descriptions/hooks/descriptions' @@ -16,16 +15,6 @@ type Returned = { text: string } -const newPlaceholder = (): DataSource => ({ - comments: '', - placeholder: true, - reference: '', - type: '', - uuid: UUIDs.getUuid(), - variables: [], - year: [], -}) - const name = CommentableDescriptionName.dataSources export const useDataSourcesData = (props: Props): Returned => { @@ -34,9 +23,6 @@ export const useDataSourcesData = (props: Props): Returned => { const value = useCommentableDescriptionValue({ sectionName, name }) return useMemo<Returned>(() => { - const _dataSources = value.dataSources ?? [] - const dataSources = [..._dataSources, newPlaceholder()] - - return { dataSources, text: value.text } + return { dataSources: value.dataSources ?? [], text: value.text } }, [value.dataSources, value.text]) } diff --git a/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useOnAdd.ts b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useOnAdd.ts new file mode 100644 index 0000000000..a0d4288084 --- /dev/null +++ b/src/client/pages/Section/Descriptions/NationalDataDescriptions/NationalDataSources/hooks/useOnAdd.ts @@ -0,0 +1,45 @@ +import { useCallback } from 'react' + +import { CountryIso } from 'meta/area/countryIso' +import { CommentableDescriptionName, CommentableDescriptionValue } from 'meta/assessment/descriptionValue' +import { DataSource } from 'meta/assessment/descriptionValue/dataSource' +import { SectionName } from 'meta/assessment/section' +import { UUIDs } from 'meta/uuid/uuids' + +import { DescriptionsActions } from 'client/store/data/descriptions/actions' +import { useCommentableDescriptionValue } from 'client/store/data/descriptions/hooks/descriptions' +import { useAppDispatch } from 'client/store/hooks' +import { useCountryRouteParams } from 'client/hooks/routeParams' + +const name: CommentableDescriptionName = CommentableDescriptionName.dataSources + +type Props = { + sectionName: SectionName +} + +type Returned = () => void + +export const useOnAdd = (props: Props): Returned => { + const { sectionName } = props + + const { assessmentName, countryIso, cycleName } = useCountryRouteParams<CountryIso>() + const dispatch = useAppDispatch() + const value = useCommentableDescriptionValue({ name, sectionName }) + + return useCallback<Returned>(() => { + const dataSource: DataSource = { + comments: '', + reference: '', + type: '', + uuid: UUIDs.getUuid(), + variables: [], + year: [], + } + + const dataSources = [...(value.dataSources ?? []), dataSource] + const valueUpdate: CommentableDescriptionValue = { ...value, dataSources } + + const updateProps = { assessmentName, cycleName, countryIso, sectionName, name, value: valueUpdate } + dispatch(DescriptionsActions.updateDescription(updateProps)) + }, [assessmentName, countryIso, cycleName, dispatch, sectionName, value]) +} diff --git a/src/client/store/data/originalDataPoint/actions/copyNationalClasses.ts b/src/client/store/data/originalDataPoint/actions/copyNationalClasses.ts index 078ef019ea..6e85f8505d 100644 --- a/src/client/store/data/originalDataPoint/actions/copyNationalClasses.ts +++ b/src/client/store/data/originalDataPoint/actions/copyNationalClasses.ts @@ -3,8 +3,8 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { SectionNames } from 'meta/assessment/section' type Props = CountryParams & { year: number; targetYear: number } @@ -13,15 +13,12 @@ export const copyNationalClasses = createAsyncThunk<OriginalDataPoint, Props>( async (props: Props) => { const { assessmentName, countryIso, cycleName, targetYear, year } = props - const params = { countryIso, assessmentName, cycleName, sectionName: 'extentOfForest', year } + const params = { countryIso, assessmentName, cycleName, sectionName: SectionNames.extentOfForest, year } const config = { params } const data = { targetYear } - const { data: originalDataPoint } = await axios.put( - ApiEndPoint.CycleData.NationalDataPoint.copyNationalClasses(), - data, - config - ) - return ODPs.addNationalClassPlaceHolder(originalDataPoint) + const { data: ndp } = await axios.put(ApiEndPoint.CycleData.NationalDataPoint.copyNationalClasses(), data, config) + + return ndp } ) diff --git a/src/client/store/data/originalDataPoint/actions/createOriginalDataPoint.ts b/src/client/store/data/originalDataPoint/actions/createOriginalDataPoint.ts index 3c8c24e655..243e8d4ec0 100644 --- a/src/client/store/data/originalDataPoint/actions/createOriginalDataPoint.ts +++ b/src/client/store/data/originalDataPoint/actions/createOriginalDataPoint.ts @@ -3,8 +3,8 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { SectionNames } from 'meta/assessment/section' type Params = CountryParams & { originalDataPoint: OriginalDataPoint } @@ -13,20 +13,11 @@ export const createOriginalDataPoint = createAsyncThunk<OriginalDataPoint, Param async (props) => { const { assessmentName, countryIso, cycleName, originalDataPoint } = props - const { data } = await axios.post( - ApiEndPoint.CycleData.NationalDataPoint.one(), - { - originalDataPoint: ODPs.removeNationalClassPlaceHolder(originalDataPoint), - }, - { - params: { - countryIso, - assessmentName, - cycleName, - sectionName: 'extentOfForest', - }, - } - ) - return ODPs.addNationalClassPlaceHolder(data) + const data = { originalDataPoint } + const params = { countryIso, assessmentName, cycleName, sectionName: SectionNames.extentOfForest } + const config = { params } + + const { data: ndp } = await axios.post(ApiEndPoint.CycleData.NationalDataPoint.one(), data, config) + return ndp } ) diff --git a/src/client/store/data/originalDataPoint/actions/getOriginalDataPoint.ts b/src/client/store/data/originalDataPoint/actions/getOriginalDataPoint.ts index 50b6bffc33..3fe0e6f72e 100644 --- a/src/client/store/data/originalDataPoint/actions/getOriginalDataPoint.ts +++ b/src/client/store/data/originalDataPoint/actions/getOriginalDataPoint.ts @@ -3,7 +3,6 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' export const getOriginalDataPoint = createAsyncThunk<OriginalDataPoint, CountryParams & { year: string }>( @@ -17,6 +16,6 @@ export const getOriginalDataPoint = createAsyncThunk<OriginalDataPoint, CountryP year, }, }) - return ODPs.addNationalClassPlaceHolder(data) + return data } ) diff --git a/src/client/store/data/originalDataPoint/actions/handlePaste.test.ts b/src/client/store/data/originalDataPoint/actions/handlePaste.test.ts index f757114658..914b6db0b7 100644 --- a/src/client/store/data/originalDataPoint/actions/handlePaste.test.ts +++ b/src/client/store/data/originalDataPoint/actions/handlePaste.test.ts @@ -8,7 +8,7 @@ const pick = (o: Record<string, string>, props: Array<string>): Record<string, u const countryIso = 'ATL' as CountryIso -const emptyOdp = { id: 1, countryIso, nationalClasses: [{ placeHolder: true }], values: {} } as OriginalDataPoint +const emptyOdp = { id: 1, countryIso, nationalClasses: [{ name: '', definition: '' }], values: {} } as OriginalDataPoint const odpWithExistingClasses = { id: 1, @@ -16,7 +16,6 @@ const odpWithExistingClasses = { nationalClasses: [ { name: 'Hardwood plantations', definition: 'Forest occurring below ...' }, { name: 'Coconut plantations', definition: 'Areas under coconut ...' }, - { name: '', placeHolder: true }, ], values: {}, } as OriginalDataPoint @@ -85,7 +84,6 @@ describe('OriginalDataPoint paste test:', () => { { name: 'Open forest', otherPlantedForestPercent: '10' }, { name: 'Hardwood plantations' }, { name: 'Coconut plantations', otherPlantedForestPercent: '25' }, - { name: '', placeHolder: true }, ], values: {}, } as OriginalDataPoint diff --git a/src/client/store/data/originalDataPoint/actions/handlePaste.ts b/src/client/store/data/originalDataPoint/actions/handlePaste.ts index 9d23db37da..ffe1748433 100644 --- a/src/client/store/data/originalDataPoint/actions/handlePaste.ts +++ b/src/client/store/data/originalDataPoint/actions/handlePaste.ts @@ -1,8 +1,7 @@ -import { Arrays } from 'utils/arrays' -import { Objects } from 'utils/objects' - import { ODPs } from 'meta/assessment/odps' import { ODPNationalClass, OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { Arrays } from 'utils/arrays' +import { Objects } from 'utils/objects' import { Sanitizer } from 'client/utils/sanitizer' @@ -15,8 +14,8 @@ const handlePaste = ( rowIndex: number, colIndex: number ): { updatedOdp: OriginalDataPoint; firstPastedCellData: string } => { - const sanitizerFor = (type: string) => { - let sanitizer = (newValue: string, _oldValue: string, _precision?: number) => newValue + const sanitizerFor = (type: string): ((newValue: string, _oldValue: string, _precision?: number) => string) => { + let sanitizer = (newValue: string, _oldValue: string, _precision?: number): string => newValue if (type === 'decimal') sanitizer = Sanitizer.acceptNextDecimal if (type === 'integer') sanitizer = Sanitizer.acceptNextInteger return sanitizer @@ -32,7 +31,7 @@ const handlePaste = ( const allowedClasses = odp.nationalClasses .map((nc, rowIndex) => ({ ...nc, rowIndex })) - .filter((nc) => !nc.placeHolder && allowedClass(nc)) + .filter((nc) => allowedClass(nc)) const rowCount = allowedClasses.length @@ -45,22 +44,17 @@ const handlePaste = ( const pastedData: Array<Array<string>> = allowGrow ? rawPastedData : rawPastedData.slice(0, rowCount - rowOffset) const handleRow = (pastedRowIndex: number, pastedRow: Array<string>, odp: OriginalDataPoint): OriginalDataPoint => pastedRow.reduce<{ odp: OriginalDataPoint; colIndex: number }>( - (accu, pastedColumnValue) => ({ - odp: updateOdp( - accu.odp, - allowedIndexes[pastedRowIndex] + rowOffset, - accu.colIndex + colIndex, - pastedColumnValue - ), - colIndex: accu.colIndex + 1, + (acc, pastedColumnValue) => ({ + odp: updateOdp(acc.odp, allowedIndexes[pastedRowIndex] + rowOffset, acc.colIndex + colIndex, pastedColumnValue), + colIndex: acc.colIndex + 1, }), { odp, colIndex: 0 } ).odp const updatedOdp: OriginalDataPoint = pastedData.reduce<{ odp: OriginalDataPoint; pastedRowIndex: number }>( - (accu, pastedRow) => ({ - odp: handleRow(accu.pastedRowIndex, pastedRow, accu.odp), - pastedRowIndex: accu.pastedRowIndex + 1, + (acc, pastedRow) => ({ + odp: handleRow(acc.pastedRowIndex, pastedRow, acc.odp), + pastedRowIndex: acc.pastedRowIndex + 1, }), { odp, pastedRowIndex: 0 } ).odp diff --git a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDataSources.ts b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDataSources.ts index afce52a176..1c09d9039e 100644 --- a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDataSources.ts +++ b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDataSources.ts @@ -4,8 +4,8 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' import { CountryIso } from 'meta/area/countryIso' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { SectionNames } from 'meta/assessment/section' import { Functions } from 'utils/functions' type Props = CountryParams & { @@ -17,20 +17,11 @@ const putOriginalDataPointDataSources = Functions.debounce( async (props: Props) => { const { assessmentName, countryIso, cycleName, originalDataPoint } = props - await axios.put( - ApiEndPoint.CycleData.NationalDataPoint.dataSources(), - { - originalDataPoint: ODPs.removeNationalClassPlaceHolder(originalDataPoint), - }, - { - params: { - countryIso, - assessmentName, - cycleName, - sectionName: 'extentOfForest', - }, - } - ) + const data = { originalDataPoint } + const params = { countryIso, assessmentName, cycleName, sectionName: SectionNames.extentOfForest } + const config = { params } + + await axios.put(ApiEndPoint.CycleData.NationalDataPoint.dataSources(), data, config) }, 1000, 'updateOriginalDataPointDataSources' diff --git a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDescription.ts b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDescription.ts index ffb2476314..bbc497a601 100644 --- a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDescription.ts +++ b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointDescription.ts @@ -4,8 +4,8 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' import { CountryIso } from 'meta/area/countryIso' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint, OriginalDataPointCommentKey } from 'meta/assessment/originalDataPoint' +import { SectionNames } from 'meta/assessment/section' import { Functions } from 'utils/functions' type Props = CountryParams & { @@ -18,12 +18,10 @@ const putOriginalDataPointDescription = Functions.debounce( async (props: Props) => { const { assessmentName, countryIso, cycleName, field, originalDataPoint } = props - const params = { countryIso, assessmentName, cycleName, sectionName: 'extentOfForest' } + const data = { field, originalDataPoint } + const params = { countryIso, assessmentName, cycleName, sectionName: SectionNames.extentOfForest } const config = { params } - const data = { - field, - originalDataPoint: ODPs.removeNationalClassPlaceHolder(originalDataPoint), - } + await axios.put(ApiEndPoint.CycleData.NationalDataPoint.description(), data, config) }, 1000, diff --git a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointNationalClasses.ts b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointNationalClasses.ts index dfc8580714..2d2c4ffdec 100644 --- a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointNationalClasses.ts +++ b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointNationalClasses.ts @@ -4,8 +4,8 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' import { CountryIso } from 'meta/area/countryIso' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { SectionNames } from 'meta/assessment/section' import { Functions } from 'utils/functions' type Props = CountryParams & { @@ -17,20 +17,11 @@ const putOriginalDataPointNationalClasses = Functions.debounce( async (props: Props) => { const { assessmentName, countryIso, cycleName, originalDataPoint } = props - await axios.put( - ApiEndPoint.CycleData.NationalDataPoint.nationalClasses(), - { - originalDataPoint: ODPs.removeNationalClassPlaceHolder(originalDataPoint), - }, - { - params: { - countryIso, - assessmentName, - cycleName, - sectionName: 'extentOfForest', - }, - } - ) + const data = { originalDataPoint } + const params = { countryIso, assessmentName, cycleName, sectionName: SectionNames.extentOfForest } + const config = { params } + + await axios.put(ApiEndPoint.CycleData.NationalDataPoint.nationalClasses(), data, config) }, 1000, 'updateOriginalDataPointNationalClasses' diff --git a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointOriginalData.ts b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointOriginalData.ts index 70c583d604..41d26a5388 100644 --- a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointOriginalData.ts +++ b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointOriginalData.ts @@ -4,7 +4,6 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CycleDataParams } from 'meta/api/request/cycleData/cycleData' import { CountryIso } from 'meta/area/countryIso' -import { ODPs } from 'meta/assessment/odps' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { Functions } from 'utils/functions' @@ -17,8 +16,8 @@ const putOriginalDataPointOriginalData = Functions.debounce( async (props: Props) => { const { assessmentName, countryIso, cycleName, originalDataPoint, sectionName } = props + const data = { originalDataPoint } const params = { countryIso, assessmentName, cycleName, sectionName } - const data = { originalDataPoint: ODPs.removeNationalClassPlaceHolder(originalDataPoint) } const config = { params } await axios.put(ApiEndPoint.CycleData.NationalDataPoint.originalData(), data, config) diff --git a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointYear.ts b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointYear.ts index 0df758267a..0e42e3dd4e 100644 --- a/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointYear.ts +++ b/src/client/store/data/originalDataPoint/actions/updateOriginalDataPointYear.ts @@ -4,6 +4,7 @@ import axios from 'axios' import { ApiEndPoint } from 'meta/api/endpoint' import { CountryParams } from 'meta/api/request/country' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { SectionNames } from 'meta/assessment/section' import { Functions } from 'utils/functions' type Props = CountryParams & { @@ -17,7 +18,7 @@ const putOriginalDataPointYear = Functions.debounce( async (props: Props) => { const { assessmentName, countryIso, cycleName, id, targetYear, year } = props - const params = { countryIso, assessmentName, cycleName, sectionName: 'extentOfForest' } + const params = { countryIso, assessmentName, cycleName, sectionName: SectionNames.extentOfForest } const config = { params } const data = { id, year, targetYear } await axios.put(ApiEndPoint.CycleData.NationalDataPoint.year(), data, config) diff --git a/src/meta/assessment/descriptionValue/dataSource.ts b/src/meta/assessment/descriptionValue/dataSource.ts index 484d9018bd..28329ce551 100644 --- a/src/meta/assessment/descriptionValue/dataSource.ts +++ b/src/meta/assessment/descriptionValue/dataSource.ts @@ -4,7 +4,6 @@ import { UUID } from 'meta/uuid/uuid' // data export type DataSource = { comments: string - placeholder?: boolean reference: string type: string | Array<string> uuid: UUID diff --git a/src/meta/assessment/descriptionValue/dataSources/updateFieldValue.ts b/src/meta/assessment/descriptionValue/dataSources/updateFieldValue.ts index cb714eabd8..182a8b6af0 100644 --- a/src/meta/assessment/descriptionValue/dataSources/updateFieldValue.ts +++ b/src/meta/assessment/descriptionValue/dataSources/updateFieldValue.ts @@ -11,7 +11,6 @@ export const updateFieldValue = (props: Props): Array<DataSource> => { const { dataSource, dataSources, fieldName, fieldValue } = props const dataSourceUpdate: DataSource = { ...dataSource, [fieldName]: fieldValue } - delete dataSourceUpdate.placeholder const dataSourcesUpdate = [...dataSources] const index = dataSourcesUpdate.findIndex((_dataSource) => _dataSource.uuid === dataSourceUpdate.uuid) diff --git a/src/meta/assessment/odps/addNationalClassPlaceHolder.ts b/src/meta/assessment/odps/addNationalClassPlaceHolder.ts deleted file mode 100644 index eb8f14247d..0000000000 --- a/src/meta/assessment/odps/addNationalClassPlaceHolder.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ODPNationalClassFactory, OriginalDataPoint } from 'meta/assessment/originalDataPoint' - -export const addNationalClassPlaceHolder = (odp: OriginalDataPoint): OriginalDataPoint => ({ - ...odp, - nationalClasses: [...odp.nationalClasses, ODPNationalClassFactory.newNationalClassPlaceholder()], -}) diff --git a/src/meta/assessment/odps/index.ts b/src/meta/assessment/odps/index.ts index bcc713b5bb..c63a26c9d5 100644 --- a/src/meta/assessment/odps/index.ts +++ b/src/meta/assessment/odps/index.ts @@ -1,4 +1,3 @@ -import { addNationalClassPlaceHolder } from 'meta/assessment/odps/addNationalClassPlaceHolder' import { calcTotalArea, calcTotalFieldArea, @@ -17,12 +16,10 @@ import { calculateNationalClassPlantationForestPercentArea, hasNaturallyRegenerating, } from 'meta/assessment/odps/nationalClassUtils' -import { removeNationalClassPlaceHolder } from 'meta/assessment/odps/removeNationalClassPlaceHolder' import { updateNationalClass } from 'meta/assessment/odps/updateNationalClass' import { validateNationalClass, validateYear } from 'meta/assessment/odps/validateODP' export const ODPs = { - addNationalClassPlaceHolder, calcTotalArea, calcTotalFieldArea, calcTotalLandArea, @@ -36,7 +33,6 @@ export const ODPs = { canCopyPreviousValues, deleteNationalClass, hasNaturallyRegenerating, - removeNationalClassPlaceHolder, shouldUseTotalPrimaryForestPercentage, updateNationalClass, // Validate diff --git a/src/meta/assessment/odps/removeNationalClassPlaceHolder.ts b/src/meta/assessment/odps/removeNationalClassPlaceHolder.ts deleted file mode 100644 index 2e7ed08388..0000000000 --- a/src/meta/assessment/odps/removeNationalClassPlaceHolder.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' - -export const removeNationalClassPlaceHolder = (odp: OriginalDataPoint): OriginalDataPoint => ({ - ...odp, - nationalClasses: [...odp.nationalClasses.filter((nationalClass) => !nationalClass.placeHolder)], -}) diff --git a/src/meta/assessment/odps/test/mock/odp1.ts b/src/meta/assessment/odps/test/mock/odp1.ts index 81b3bcd030..ebd0e1e00d 100644 --- a/src/meta/assessment/odps/test/mock/odp1.ts +++ b/src/meta/assessment/odps/test/mock/odp1.ts @@ -53,11 +53,5 @@ export const odp1 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: '6c611c99-9eab-4369-a56b-16c671e491da', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp10.ts b/src/meta/assessment/odps/test/mock/odp10.ts index 05c827b26e..9397b317ec 100644 --- a/src/meta/assessment/odps/test/mock/odp10.ts +++ b/src/meta/assessment/odps/test/mock/odp10.ts @@ -53,11 +53,5 @@ export const odp10 = { forestPercent: null, otherWoodedLandPercent: null, }, - { - name: '', - definition: '', - uuid: 'f3074aa1-c5b4-4984-86e9-87eb97648619', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp11.ts b/src/meta/assessment/odps/test/mock/odp11.ts index bf2cf07b47..f4d6eb7c42 100644 --- a/src/meta/assessment/odps/test/mock/odp11.ts +++ b/src/meta/assessment/odps/test/mock/odp11.ts @@ -53,11 +53,5 @@ export const odp11 = { forestPercent: null, otherWoodedLandPercent: null, }, - { - name: '', - definition: '', - uuid: '012d5db6-3990-43f0-bc12-c99fe8467bbb', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp2.ts b/src/meta/assessment/odps/test/mock/odp2.ts index dbc278bb26..f780c44dc1 100644 --- a/src/meta/assessment/odps/test/mock/odp2.ts +++ b/src/meta/assessment/odps/test/mock/odp2.ts @@ -53,11 +53,5 @@ export const odp2 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: '6c611c99-9eab-4369-a56b-16c671e491da', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp3.ts b/src/meta/assessment/odps/test/mock/odp3.ts index c5592306e2..84679df33a 100644 --- a/src/meta/assessment/odps/test/mock/odp3.ts +++ b/src/meta/assessment/odps/test/mock/odp3.ts @@ -53,11 +53,5 @@ export const odp3 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: '6c611c99-9eab-4369-a56b-16c671e491da', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp4.ts b/src/meta/assessment/odps/test/mock/odp4.ts index db0323f0f5..c6dc7be2e0 100644 --- a/src/meta/assessment/odps/test/mock/odp4.ts +++ b/src/meta/assessment/odps/test/mock/odp4.ts @@ -53,11 +53,5 @@ export const odp4 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: 'd747092c-bf76-42c0-afd9-dced0e5d8a75', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp5.ts b/src/meta/assessment/odps/test/mock/odp5.ts index bebc6125df..2f89391ba6 100644 --- a/src/meta/assessment/odps/test/mock/odp5.ts +++ b/src/meta/assessment/odps/test/mock/odp5.ts @@ -53,11 +53,5 @@ export const odp5 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: '589e3b51-fbef-4998-970f-a2b3133493e2', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp6.ts b/src/meta/assessment/odps/test/mock/odp6.ts index 1f19fbc120..ce5ac0aef4 100644 --- a/src/meta/assessment/odps/test/mock/odp6.ts +++ b/src/meta/assessment/odps/test/mock/odp6.ts @@ -53,11 +53,5 @@ export const odp6 = { forestPercent: null, otherWoodedLandPercent: '50.00', }, - { - name: '', - definition: '', - uuid: 'b27d8f15-6a69-4b6b-805c-c2dfce85ddae', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp7.ts b/src/meta/assessment/odps/test/mock/odp7.ts index 8738c95a43..caaba40e2c 100644 --- a/src/meta/assessment/odps/test/mock/odp7.ts +++ b/src/meta/assessment/odps/test/mock/odp7.ts @@ -53,11 +53,5 @@ export const odp7 = { forestPercent: null, otherWoodedLandPercent: '50.00', }, - { - name: '', - definition: '', - uuid: 'b27d8f15-6a69-4b6b-805c-c2dfce85ddae', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp8.ts b/src/meta/assessment/odps/test/mock/odp8.ts index dfac7e36e3..5799e025f6 100644 --- a/src/meta/assessment/odps/test/mock/odp8.ts +++ b/src/meta/assessment/odps/test/mock/odp8.ts @@ -53,11 +53,5 @@ export const odp8 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: 'e4470f48-11f8-460f-b400-ba4b939d8a6e', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/test/mock/odp9.ts b/src/meta/assessment/odps/test/mock/odp9.ts index fc46f699f0..0248423734 100644 --- a/src/meta/assessment/odps/test/mock/odp9.ts +++ b/src/meta/assessment/odps/test/mock/odp9.ts @@ -53,11 +53,5 @@ export const odp9 = { forestPercent: '0.00', otherWoodedLandPercent: '100.00', }, - { - name: '', - definition: '', - uuid: 'e4470f48-11f8-460f-b400-ba4b939d8a6e', - placeHolder: true, - }, ], } as OriginalDataPoint diff --git a/src/meta/assessment/odps/updateNationalClass.ts b/src/meta/assessment/odps/updateNationalClass.ts index 5815cab243..247a5c2c2f 100644 --- a/src/meta/assessment/odps/updateNationalClass.ts +++ b/src/meta/assessment/odps/updateNationalClass.ts @@ -1,8 +1,7 @@ +import { ODPNationalClass, ODPNationalClassFactory, OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { Numbers } from 'utils/numbers' import { Objects } from 'utils/objects' -import { ODPNationalClass, ODPNationalClassFactory, OriginalDataPoint } from 'meta/assessment/originalDataPoint' - import { calculateValues as calculateODPValues } from './calc' // Helper utility to calculate correct value for Classifications and definitions. @@ -24,7 +23,7 @@ type CalculateValuesProps = { field: keyof ODPNationalClass } -const calculateValues = (props: CalculateValuesProps) => { +const calculateValues = (props: CalculateValuesProps): ODPNationalClass => { const { field, index, odp, value } = props const prevValue = odp.nationalClasses[index][field] as string @@ -107,16 +106,14 @@ export const updateNationalClass = (props: { const { field, index, odp: odpProps, value } = props const odp: OriginalDataPoint = Objects.cloneDeep(odpProps) - const calculateProps = { odp, index, field, value } - const nationalClass: ODPNationalClass = calculateValues(calculateProps) - const wasPlaceHolder = !Objects.isNil(nationalClass.placeHolder) - delete nationalClass.placeHolder - - odp.nationalClasses[index] = nationalClass - if (wasPlaceHolder) { - odp.nationalClasses.push(ODPNationalClassFactory.newNationalClassPlaceholder()) + // handle pasting multiple rows + if (Objects.isNil(odp.nationalClasses[index])) { + odp.nationalClasses[index] = ODPNationalClassFactory.newNationalClass() } + const calculateProps = { odp, index, field, value } + odp.nationalClasses[index] = calculateValues(calculateProps) + return calculateODPValues(odp) } diff --git a/src/meta/assessment/odps/validateODP.ts b/src/meta/assessment/odps/validateODP.ts index c67c177fa2..60bc753c9b 100644 --- a/src/meta/assessment/odps/validateODP.ts +++ b/src/meta/assessment/odps/validateODP.ts @@ -1,26 +1,25 @@ +import { ODPNationalClass, OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { Numbers } from 'utils/numbers' import { Objects } from 'utils/objects' -import { ODPNationalClass, OriginalDataPoint } from 'meta/assessment/originalDataPoint' - -const ltE100 = (x: number) => Numbers.lessThanOrEqualTo(x, 100) +const ltE100 = (x: number): boolean => Numbers.lessThanOrEqualTo(x, 100) -const e100 = (x: number) => Numbers.eq(x, 100) +const e100 = (x: number): boolean => Numbers.eq(x, 100) -export const validateYear = (originalDataPoint: OriginalDataPoint) => { +export const validateYear = (originalDataPoint: OriginalDataPoint): boolean => { return Numbers.greaterThan(originalDataPoint.year ?? 0, 0) } // National Class Validations: // == Name must not be empty or longer than 1024 -const _validateClassName = (nationalClass: ODPNationalClass) => +const _validateClassName = (nationalClass: ODPNationalClass): boolean => !Objects.isEmpty(nationalClass?.name) && nationalClass?.name?.length < 1024 // == Area must not be null -const _validateArea = (nationalClass: ODPNationalClass) => Number.isNaN(+nationalClass.area) +const _validateArea = (nationalClass: ODPNationalClass): boolean => Number.isNaN(+nationalClass.area) // == ExtentOfForest percentage (forestPercent, otherWoodedLandPercent) sum should be less than or equal to 100 -const _validExtentOfForestPercentage = (nationalClass: ODPNationalClass) => { +const _validExtentOfForestPercentage = (nationalClass: ODPNationalClass): boolean => { const percentSum = Numbers.sum([nationalClass.forestPercent ?? 0, nationalClass.otherWoodedLandPercent ?? 0]) return ltE100(percentSum) } @@ -29,7 +28,7 @@ const _validExtentOfForestPercentage = (nationalClass: ODPNationalClass) => { // (forestNaturalPercent, forestPlantationPercent, otherPlantedForestPercent) // sum should be equal to 100 -const _validForestCharacteristicsPercentage = (nationalClass: ODPNationalClass) => { +const _validForestCharacteristicsPercentage = (nationalClass: ODPNationalClass): boolean => { if (+nationalClass.forestPercent <= 0) return true const percentSum = Numbers.sum([ nationalClass.forestNaturalPercent ?? 0, @@ -42,7 +41,7 @@ const _validForestCharacteristicsPercentage = (nationalClass: ODPNationalClass) // == Forest plantation introduced percentage (forestPlantationIntroducedPercent) // should be less than or equal to 100 -const _validForestPlantationIntroducedPercent = (nationalClass: ODPNationalClass) => { +const _validForestPlantationIntroducedPercent = (nationalClass: ODPNationalClass): boolean => { if (Objects.isEmpty(nationalClass.forestPlantationIntroducedPercent)) return true if (+nationalClass.forestPlantationIntroducedPercent <= 0) return true return ltE100(+nationalClass.forestPlantationIntroducedPercent) @@ -50,7 +49,7 @@ const _validForestPlantationIntroducedPercent = (nationalClass: ODPNationalClass // == Natural forest of which primary forest percentage (forestNaturalForestOfWhichPrimaryForestPercent) // should be less than or equal to 100 -const _validPrimaryForest = (nationalClass: ODPNationalClass) => { +const _validPrimaryForest = (nationalClass: ODPNationalClass): boolean => { if (Objects.isEmpty(nationalClass.forestNaturalForestOfWhichPrimaryForestPercent)) return true if (+nationalClass.forestNaturalForestOfWhichPrimaryForestPercent <= 0) return true return ltE100(+nationalClass.forestNaturalForestOfWhichPrimaryForestPercent) @@ -70,8 +69,7 @@ export const validateNationalClass = (originalDataPoint: OriginalDataPoint, inde const nationalClass = originalDataPoint?.nationalClasses?.[index] // If the national class doesn't exist, it is not invalid if (!nationalClass) return { error: false } as NationalClassValidation - const isPlaceHolder = nationalClass.placeHolder - const validClassName = isPlaceHolder || _validateClassName(nationalClass) + const validClassName = _validateClassName(nationalClass) const validArea = validClassName || _validateArea(nationalClass) const validExtentOfForestPercentage = _validExtentOfForestPercentage(nationalClass) const validForestCharacteristicsPercentage = _validForestCharacteristicsPercentage(nationalClass) diff --git a/src/meta/assessment/originalDataPoint/odpNationalClass.ts b/src/meta/assessment/originalDataPoint/odpNationalClass.ts index 83c1ab061b..6a502529e3 100644 --- a/src/meta/assessment/originalDataPoint/odpNationalClass.ts +++ b/src/meta/assessment/originalDataPoint/odpNationalClass.ts @@ -8,7 +8,6 @@ const newNationalClass = (props?: { name?: string; definition?: string }): ODPNa export const ODPNationalClassFactory = { newNationalClass, - newNationalClassPlaceholder: (): ODPNationalClass => ({ ...newNationalClass(), placeHolder: true }), } export interface ODPNationalClass { @@ -19,7 +18,6 @@ export interface ODPNationalClass { forestNaturalPercent?: string otherPlantedForestPercent?: string otherWoodedLandPercent?: string - placeHolder?: boolean forestPlantationIntroducedPercent?: string forestPlantationPercent?: string forestNaturalForestOfWhichPrimaryForestPercent?: string