Skip to content

Commit

Permalink
4033 - NationalData-DataSources Cycle 2029: data/metadata clone (#4034)
Browse files Browse the repository at this point in the history
* 4033 - Do not import dataSources.text prop / Fix clone cycle props

* 4033 - improve Objects.isEmpty + unit test

* 4033 - fix DataSources grid

* 4033 - Do not import dataSources.text value
  • Loading branch information
minotogna authored Oct 16, 2024
1 parent e641fc8 commit 45d2f2a
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import './DataSources.scss'
import React from 'react'
import { useTranslation } from 'react-i18next'

import { Objects } from 'utils/objects'

import { CommentableDescriptionName } from 'meta/assessment'
import { NationalDataDescription } from 'meta/assessment/description'

Expand Down Expand Up @@ -39,7 +41,7 @@ export const DataSources: React.FC<Props> = (props: Props) => {
const editable = useIsDescriptionEditable({ sectionName, name })
const { empty } = useDescriptionErrorState({ name, sectionName })

const renderGrid = Boolean(dataSources?.length || dataSourcesLinked?.length || editable)
const renderGrid = Boolean(!Objects.isEmpty(dataSources) || !Objects.isEmpty(dataSourcesLinked) || editable)
const keyPrefix = `${assessmentName}.${cycleName}.description.dataSource`

return (
Expand Down
23 changes: 15 additions & 8 deletions src/meta/assessment/cols.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TFunction } from 'i18next'
import { Objects } from 'utils/objects'

import { Cycle } from 'meta/assessment/cycle'
import { Labels } from 'meta/assessment/labels'
Expand All @@ -12,16 +13,22 @@ const cloneProps = (props: { cycleSource: Cycle; cycleTarget: Cycle; col: Col })
const { uuid: cycleSourceUuid } = cycleSource
const { uuid: cycleTargetUuid } = cycleTarget

const _props: Col['props'] = { ...col.props }
const _props: Col['props'] = Objects.cloneDeep(col.props)
_props.cycles.push(cycleTargetUuid)

if (_props.calculateFn?.[cycleSourceUuid]) _props.calculateFn[cycleTargetUuid] = _props.calculateFn[cycleSourceUuid]
if (_props.classNames?.[cycleSourceUuid]) _props.classNames[cycleTargetUuid] = _props.classNames[cycleSourceUuid]
if (_props.labels?.[cycleSourceUuid]) _props.labels[cycleTargetUuid] = _props.labels[cycleSourceUuid]
if (_props.linkedNodes?.[cycleSourceUuid]) _props.linkedNodes[cycleTargetUuid] = _props.linkedNodes[cycleSourceUuid]
if (_props.style?.[cycleSourceUuid]) _props.style[cycleTargetUuid] = _props.style[cycleSourceUuid]
if (_props.validateFns?.[cycleSourceUuid]) _props.validateFns[cycleTargetUuid] = _props.validateFns[cycleSourceUuid]
if (_props.variableNo?.[cycleSourceUuid]) _props.variableNo[cycleTargetUuid] = _props.variableNo[cycleSourceUuid]
if (_props.calculateFn?.[cycleSourceUuid])
_props.calculateFn[cycleTargetUuid] = Objects.cloneDeep(_props.calculateFn[cycleSourceUuid])
if (_props.classNames?.[cycleSourceUuid])
_props.classNames[cycleTargetUuid] = Objects.cloneDeep(_props.classNames[cycleSourceUuid])
if (_props.labels?.[cycleSourceUuid])
_props.labels[cycleTargetUuid] = Objects.cloneDeep(_props.labels[cycleSourceUuid])
if (_props.linkedNodes?.[cycleSourceUuid])
_props.linkedNodes[cycleTargetUuid] = Objects.cloneDeep(_props.linkedNodes[cycleSourceUuid])
if (_props.style?.[cycleSourceUuid]) _props.style[cycleTargetUuid] = Objects.cloneDeep(_props.style[cycleSourceUuid])
if (_props.validateFns?.[cycleSourceUuid])
_props.validateFns[cycleTargetUuid] = Objects.cloneDeep(_props.validateFns[cycleSourceUuid])
if (_props.variableNo?.[cycleSourceUuid])
_props.variableNo[cycleTargetUuid] = Objects.cloneDeep(_props.variableNo[cycleSourceUuid])

return _props
}
Expand Down
22 changes: 14 additions & 8 deletions src/meta/assessment/rows.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Objects } from 'utils/objects'

import { Cycle } from 'meta/assessment/cycle'
import { Row } from 'meta/assessment/row'

Expand All @@ -7,18 +9,22 @@ const cloneProps = (props: { cycleSource: Cycle; cycleTarget: Cycle; row: Row })
const { uuid: cycleSourceUuid } = cycleSource
const { uuid: cycleTargetUuid } = cycleTarget

const _props: Row['props'] = { ...row.props }
const _props: Row['props'] = Objects.cloneDeep(row.props)
_props.cycles.push(cycleTargetUuid)

if (_props.calculateFn?.[cycleSourceUuid]) _props.calculateFn[cycleTargetUuid] = _props.calculateFn[cycleSourceUuid]
if (_props.calculateIf?.[cycleSourceUuid]) _props.calculateIf[cycleTargetUuid] = _props.calculateIf[cycleSourceUuid]
if (_props.chart?.[cycleSourceUuid]) _props.chart[cycleTargetUuid] = _props.chart[cycleSourceUuid]
if (_props.calculateFn?.[cycleSourceUuid])
_props.calculateFn[cycleTargetUuid] = Objects.cloneDeep(_props.calculateFn[cycleSourceUuid])
if (_props.calculateIf?.[cycleSourceUuid])
_props.calculateIf[cycleTargetUuid] = Objects.cloneDeep(_props.calculateIf[cycleSourceUuid])
if (_props.chart?.[cycleSourceUuid]) _props.chart[cycleTargetUuid] = Objects.cloneDeep(_props.chart[cycleSourceUuid])
if (_props.excludeFromDataExport?.[cycleSourceUuid])
_props.excludeFromDataExport[cycleTargetUuid] = _props.excludeFromDataExport[cycleSourceUuid]
_props.excludeFromDataExport[cycleTargetUuid] = Objects.cloneDeep(_props.excludeFromDataExport[cycleSourceUuid])
if (_props.linkToSection?.[cycleSourceUuid])
_props.linkToSection[cycleTargetUuid] = _props.linkToSection[cycleSourceUuid]
if (_props.validateFns?.[cycleSourceUuid]) _props.validateFns[cycleTargetUuid] = _props.validateFns[cycleSourceUuid]
if (_props.withReview?.[cycleSourceUuid]) _props.withReview[cycleTargetUuid] = _props.withReview[cycleSourceUuid]
_props.linkToSection[cycleTargetUuid] = Objects.cloneDeep(_props.linkToSection[cycleSourceUuid])
if (_props.validateFns?.[cycleSourceUuid])
_props.validateFns[cycleTargetUuid] = Objects.cloneDeep(_props.validateFns[cycleSourceUuid])
if (_props.withReview?.[cycleSourceUuid])
_props.withReview[cycleTargetUuid] = Objects.cloneDeep(_props.withReview[cycleSourceUuid])

return _props
}
Expand Down
10 changes: 7 additions & 3 deletions src/meta/assessment/sections.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Objects } from 'utils/objects'

import { Cycle } from 'meta/assessment/cycle'
import { Section } from 'meta/assessment/section'

Expand All @@ -7,11 +9,13 @@ const cloneProps = (props: { cycleSource: Cycle; cycleTarget: Cycle; section: Se
const { uuid: cycleSourceUuid } = cycleSource
const { uuid: cycleTargetUuid } = cycleTarget

const _props: Section['props'] = { ...section.props }
const _props: Section['props'] = Objects.cloneDeep(section.props)
_props.cycles.push(cycleTargetUuid)

if (_props.anchors?.[cycleSourceUuid]) _props.anchors[cycleTargetUuid] = _props.anchors[cycleSourceUuid]
if (_props.labels?.[cycleSourceUuid]) _props.labels[cycleTargetUuid] = _props.labels[cycleSourceUuid]
if (_props.anchors?.[cycleSourceUuid])
_props.anchors[cycleTargetUuid] = Objects.cloneDeep(_props.anchors[cycleSourceUuid])
if (_props.labels?.[cycleSourceUuid])
_props.labels[cycleTargetUuid] = Objects.cloneDeep(_props.labels[cycleSourceUuid])

return _props
}
Expand Down
16 changes: 11 additions & 5 deletions src/meta/assessment/subSections.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Objects } from 'utils/objects'

import { Cycle } from 'meta/assessment/cycle'
import { Section, SubSection } from 'meta/assessment/section'
import { Sections } from 'meta/assessment/sections'
Expand All @@ -12,12 +14,16 @@ const cloneProps = (props: { cycleSource: Cycle; cycleTarget: Cycle; subSection:
const section = subSection as Section

const _props: SubSection['props'] = Sections.cloneProps({ cycleSource, cycleTarget, section }) as SubSection['props']
_props.cycles.push(cycleTargetUuid)

if (_props.descriptions?.[cycleSourceUuid])
_props.descriptions[cycleTargetUuid] = _props.descriptions[cycleSourceUuid]
if (_props.hidden?.[cycleSourceUuid]) _props.hidden[cycleTargetUuid] = _props.hidden[cycleSourceUuid]
if (_props.hints?.[cycleSourceUuid]) _props.hints[cycleTargetUuid] = _props.hints[cycleSourceUuid]
const descriptionsSource = Objects.cloneDeep(_props.descriptions?.[cycleSourceUuid])
if (!Objects.isEmpty(descriptionsSource)) {
// delete nationalData->dataSources->text needed only in FRA 2025
Objects.unset(descriptionsSource, ['nationalData', 'dataSources', 'text'])
_props.descriptions[cycleTargetUuid] = descriptionsSource
}
if (_props.hidden?.[cycleSourceUuid])
_props.hidden[cycleTargetUuid] = Objects.cloneDeep(_props.hidden[cycleSourceUuid])
if (_props.hints?.[cycleSourceUuid]) _props.hints[cycleTargetUuid] = Objects.cloneDeep(_props.hints[cycleSourceUuid])

return _props
}
Expand Down
9 changes: 6 additions & 3 deletions src/meta/assessment/tableSections.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Objects } from 'utils/objects'

import { Cycle } from 'meta/assessment/cycle'
import { TableSection } from 'meta/assessment/tableSection'

Expand All @@ -11,12 +13,13 @@ const cloneProps = (props: {
const { uuid: cycleSourceUuid } = cycleSource
const { uuid: cycleTargetUuid } = cycleTarget

const _props: TableSection['props'] = { ...tableSection.props }
const _props: TableSection['props'] = Objects.cloneDeep(tableSection.props)
_props.cycles.push(cycleTargetUuid)

if (_props.descriptions?.[cycleSourceUuid])
_props.descriptions[cycleTargetUuid] = _props.descriptions[cycleSourceUuid]
if (_props.labels?.[cycleSourceUuid]) _props.labels[cycleTargetUuid] = _props.labels[cycleSourceUuid]
_props.descriptions[cycleTargetUuid] = Objects.cloneDeep(_props.descriptions[cycleSourceUuid])
if (_props.labels?.[cycleSourceUuid])
Objects.cloneDeep((_props.labels[cycleTargetUuid] = _props.labels[cycleSourceUuid]))

return _props
}
Expand Down
15 changes: 9 additions & 6 deletions src/meta/assessment/tables.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Objects } from 'utils/objects'

import { Cycle } from 'meta/assessment/cycle'
import { Table } from 'meta/assessment/table'

Expand All @@ -7,18 +9,19 @@ const cloneProps = (props: { cycleSource: Cycle; cycleTarget: Cycle; table: Tabl
const { uuid: cycleSourceUuid } = cycleSource
const { uuid: cycleTargetUuid } = cycleTarget

const _props: Table['props'] = { ...table.props }
const _props: Table['props'] = Objects.cloneDeep(table.props)
_props.cycles.push(cycleTargetUuid)

if (_props.cellsExportAlways?.[cycleSourceUuid])
_props.cellsExportAlways[cycleTargetUuid] = _props.cellsExportAlways[cycleSourceUuid]
if (_props.columnNames?.[cycleSourceUuid]) _props.columnNames[cycleTargetUuid] = _props.columnNames[cycleSourceUuid]
_props.cellsExportAlways[cycleTargetUuid] = Objects.cloneDeep(_props.cellsExportAlways[cycleSourceUuid])
if (_props.columnNames?.[cycleSourceUuid])
_props.columnNames[cycleTargetUuid] = Objects.cloneDeep(_props.columnNames[cycleSourceUuid])
if (_props.columnsExport?.[cycleSourceUuid])
_props.columnsExport[cycleTargetUuid] = _props.columnsExport[cycleSourceUuid]
_props.columnsExport[cycleTargetUuid] = Objects.cloneDeep(_props.columnsExport[cycleSourceUuid])
if (_props.columnsExportAlways?.[cycleSourceUuid])
_props.columnsExportAlways[cycleTargetUuid] = _props.columnsExportAlways[cycleSourceUuid]
_props.columnsExportAlways[cycleTargetUuid] = Objects.cloneDeep(_props.columnsExportAlways[cycleSourceUuid])
if (_props.disableErrorMessage?.[cycleSourceUuid])
_props.disableErrorMessage[cycleTargetUuid] = _props.disableErrorMessage[cycleSourceUuid]
_props.disableErrorMessage[cycleTargetUuid] = Objects.cloneDeep(_props.disableErrorMessage[cycleSourceUuid])

return _props
}
Expand Down
10 changes: 9 additions & 1 deletion src/server/controller/assessment/cloneCycle/_cloneData.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { CommentableDescriptionName } from 'meta/assessment'

import { CloneProps } from 'server/controller/assessment/cloneCycle/types'
import { BaseProtocol, Schemas } from 'server/db'

Expand Down Expand Up @@ -39,7 +41,13 @@ export const cloneData = async (props: CloneProps, client: BaseProtocol): Promis
from ${schemaCycleSource}.original_data_point;
insert into ${schemaCycleTarget}.descriptions (country_iso, section_name, name, value)
select country_iso, section_name, name, value
select country_iso,
section_name,
name,
case
when name = '${CommentableDescriptionName.dataSources}' then jsonb_delete(value, 'text')
else value
end -- // delete nationalData->dataSources->text needed only in FRA 2025
from ${schemaCycleSource}.descriptions;
insert into ${schemaCycleTarget}.repository (uuid, country_iso, file_uuid, link, props)
Expand Down
3 changes: 1 addition & 2 deletions src/utils/objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import * as isEqual from 'lodash.isequal'
// @ts-ignore
import * as isFunction from 'lodash.isfunction'
// @ts-ignore
import * as isNil from 'lodash.isnil'
// @ts-ignore
import * as pick from 'lodash.pick'
// @ts-ignore
import * as unset from 'lodash.unset'
import { getInPath } from 'utils/objects/getInPath'

import { camelize } from './camelize'
import { isEmpty } from './isEmpty'
import { isNil } from './isNil'
import { propertyOf } from './propertyOf'
import { setInPath } from './setInPath'

Expand Down
30 changes: 30 additions & 0 deletions src/utils/objects/isEmpty.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { isEmpty } from 'utils/objects/isEmpty'

const tests: Array<{ empty: boolean; value: any }> = [
{ empty: true, value: undefined },
{ empty: true, value: null },
{ empty: true, value: '' },
{ empty: true, value: ' ' },
{ empty: false, value: ' fdsafd a' },
{ empty: false, value: 'fdsafd ' },
{ empty: false, value: 'fdsafd' },
{ empty: false, value: { a: '' } },
{ empty: false, value: { a: '', b: '' } },
{ empty: false, value: { a: undefined } },
{ empty: true, value: {} },
{ empty: false, value: [1] },
{ empty: false, value: [1, 2, 3] },
{ empty: true, value: [] },
{ empty: false, value: [undefined] },
{ empty: false, value: [null] },
{ empty: false, value: [undefined, null] },
]

describe('isEmpty', () => {
tests.forEach(({ empty, value }) => {
test(`${JSON.stringify(value)}-${empty}`, () => {
const result = isEmpty(value)
expect(result).toEqual(empty)
})
})
})
10 changes: 5 additions & 5 deletions src/utils/objects/isEmpty.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { isNil } from 'utils/objects/isNil'

/**
* Determines if the specified value is null, empty string, NaN, empty object or empty array.
*
* @param {any} value - Value to
* @returns {boolean} True if the specified value is empty, false otherwise.
*/
export const isEmpty = (value: any): boolean =>
value === undefined ||
value === null ||
value === '' ||
isNil(value) ||
Number.isNaN(value) ||
(value instanceof Object && Object.entries(value).length === 0) ||
(Array.isArray(value) && value.length === 0)
(typeof value === 'object' && Object.keys(value).length === 0) ||
(typeof value === 'string' && value.trim().length === 0)
4 changes: 4 additions & 0 deletions src/utils/objects/isNil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-expect-error
import * as isNil from 'lodash.isnil'

export { isNil }

0 comments on commit 45d2f2a

Please sign in to comment.