Skip to content

Commit

Permalink
fix(layout module): move/add functions, constants and tests from DV a…
Browse files Browse the repository at this point in the history
…pp (#25)

* fix: add layout, axis, dimension, item

* fix: use prop object

* fix: add basic validation

* fix: add data checks

* fix: add layout, axis, dimension fns

* fix: add has dynamic dimension fn

* fix: clean up fixed dimensions

* fix: add test resources

* fix: add item tests

* fix: add dimension tests

* fix: add axis tests

* fix: add layoutFilterDimensions test

* fix: add layoutGetAllAxes test

* fix: add layoutGetAllDimensions test

* fix: add layoutGetAllItemIds test

* fix: add layoutGetAllItems test

* fix: add layoutGetDimensionIdItemIdsObject test

* fix: update layoutGetDimensionIdItemIdsObject test

* fix: update layoutGetDimensionIdItemIdsObject test

* fix: add layoutHasDataDimension test

* fix: add layoutHasDimension test

* fix: add layoutHasDynamicDimension test

* fix: add layoutHasPeriodDimension test

* fix: add axisGetAllItems test

* fix: add axisGetDimensionIds

* fix: add axisGetDimensionIds test

* fix: update axis tests

* fix: update default value tests

* fix: export functions

* fix: update AXIS import path

* fix: fix export typo

* fix: add new layout fns

* fix: add getDimension tests

* fix: remove unused exports

* fix: add test

* fix: remove unused import

* fix: lodash imports

* fix: lodash imports

* fix: rename 'validate' to 'isValid' + add docs

* fix: update docs

* fix: update docs
  • Loading branch information
janhenrikoverland authored May 22, 2019
1 parent 674a834 commit 7c8658f
Show file tree
Hide file tree
Showing 65 changed files with 986 additions and 13 deletions.
68 changes: 68 additions & 0 deletions docs/module-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Layout description

### Layout

Layout refers to the dimensional part of a visualization in DHIS2. It has three axes:

```
{
columns: [<dimensions>],
rows: [<dimensions>],
filters: [<dimensions>],
}
```

- `columns`: Refers to top/horizontal dimensions in pivot tables and series dimensions in charts
- `rows`: Refers to left/vertical dimensions in pivot tables and category dimensions in charts
- `filters`: These dimensions simply filter the returned data values

### Axis

An axis is an array of dimensions.

### Dimension

A dimension is an object with a dimension id and an array of items.

```
{
dimension: "dx",
items: [<items>]
}
```

- `dimension`: The id property of the dimension, note that it is not called "id"
- `items`: Refers to the metadata you want to fetch data for, typically indicators/data elements, periods and organisation units

There are three fixed dimensions in DHIS2 (data, period and organisation unit), but you are free to add dynamic dimensions as well, e.g. data element group sets, organisation unit group sets, categories etc.

### Item

An item is an object with an id.

```
{
id: "Uvn6LCg7dVU",
}
```

- `id`: The id of the item

## Example layout

```
{
columns: [{
dimension: "dx", // data dimension
items: [{id: "Uvn6LCg7dVU"}, {id: "Uvn6LCg7dVU"}] // two indicators
}],
rows: [{
dimension: "pe", // period dimension
items: [{id: "THIS_YEAR"}] // a period
}],
filters: [{
dimension: "ou", // organisation unit dimension
items: [{id: "LEVEL-2"}] // all orgunits at level 2
}],
}
```
2 changes: 1 addition & 1 deletion src/components/ItemSelector/modules/reorderList.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sortBy } from 'lodash'
import sortBy from 'lodash/sortBy'

export const reorderList = ({
items,
Expand Down
85 changes: 79 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,91 @@
export {
default as PeriodDimension,
} from './components/PeriodDimension/PeriodDimension'
// Components

export {
default as DataDimension,
} from './components/DataDimension/DataDimension'

export {
default as DynamicDimension,
} from './components/DynamicDimension/DynamicDimension'
default as PeriodDimension,
} from './components/PeriodDimension/PeriodDimension'

export {
default as OrgUnitDimension,
} from './components/OrgUnitDimension/OrgUnitDimension'

export {
default as DynamicDimension,
} from './components/DynamicDimension/DynamicDimension'

export {
default as DimensionsPanel,
} from './components/DimensionsPanel/DimensionsPanel'

export { default as ItemSelector } from './components/ItemSelector/ItemSelector'
export { FIXED_DIMENSIONS } from './modules/fixedDimensions'

// Api

export { apiFetchDimensions } from './api/dimensions'

// Modules

export {
DIMENSION_ID_DATA,
DIMENSION_ID_PERIOD,
DIMENSION_ID_ORGUNIT,
FIXED_DIMENSIONS,
} from './modules/fixedDimensions'

export { LAYOUT } from './modules/layout/layout'
export { layoutFilterDimensions } from './modules/layout/layoutFilterDimensions'
export { layoutGetAllAxes } from './modules/layout/layoutGetAllAxes'
export { layoutGetAllDimensions } from './modules/layout/layoutGetAllDimensions'
export { layoutGetAllItemIds } from './modules/layout/layoutGetAllItemIds'
export { layoutGetAllItems } from './modules/layout/layoutGetAllItems'
export {
layoutGetAxisNameDimensionIdsObject,
} from './modules/layout/layoutGetAxisNameDimensionIdsObject'
export { layoutGetDimension } from './modules/layout/layoutGetDimension'
export {
layoutGetDimensionIdItemIdsObject,
} from './modules/layout/layoutGetDimensionIdItemIdsObject'
export { layoutHasDataDimension } from './modules/layout/layoutHasDataDimension'
export { layoutHasDimension } from './modules/layout/layoutHasDimension'
export {
layoutHasDynamicDimension,
} from './modules/layout/layoutHasDynamicDimension'
export {
layoutHasPeriodDimension,
} from './modules/layout/layoutHasPeriodDimension'

export {
AXIS,
AXIS_NAME_COLUMNS,
AXIS_NAME_ROWS,
AXIS_NAME_FILTERS,
AXIS_NAMES,
} from './modules/layout/axis'
export { axisGetAllItems } from './modules/layout/axisGetAllItems'
export { axisGetDimension } from './modules/layout/axisGetDimension'
export { axisGetDimensionIds } from './modules/layout/axisGetDimensionIds'
export { axisHasDataDimension } from './modules/layout/axisHasDataDimension'
export { axisHasDimension } from './modules/layout/axisHasDimension'
export { axisHasPeriodDimension } from './modules/layout/axisHasPeriodDimension'
export { axisIsEmpty } from './modules/layout/axisIsEmpty'

export {
DIMENSION,
DIMENSION_PROP_ID,
DIMENSION_PROP_ITEMS,
DIMENSION_PROPS,
} from './modules/layout/dimension'
export { dimensionCreate } from './modules/layout/dimensionCreate'
export { dimensionGetId } from './modules/layout/dimensionGetId'
export { dimensionGetItemIds } from './modules/layout/dimensionGetItemIds'
export { dimensionGetItems } from './modules/layout/dimensionGetItems'
export { dimensionIs } from './modules/layout/dimensionIs'
export { dimensionIsEmpty } from './modules/layout/dimensionIsEmpty'
export { dimensionIsValid } from './modules/layout/dimensionIsValid'

export { ITEM, ITEM_PROP_ID, ITEM_PROPS } from './modules/layout/item'
export { itemGetId } from './modules/layout/itemGetId'
export { itemIsValid } from './modules/layout/itemIsValid'
16 changes: 10 additions & 6 deletions src/modules/fixedDimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ import DataIcon from '../assets/DataIcon'
import PeriodIcon from '../assets/PeriodIcon'
import OrgUnitIcon from '../assets/OrgUnitIcon'

export const DIMENSION_ID_DATA = 'dx'
export const DIMENSION_ID_PERIOD = 'pe'
export const DIMENSION_ID_ORGUNIT = 'ou'

export const FIXED_DIMENSIONS = {
dx: {
id: 'dx',
[DIMENSION_ID_DATA]: {
id: DIMENSION_ID_DATA,
name: i18n.t('Data'),
iconName: 'DataIcon',
icon: DataIcon,
},
pe: {
id: 'pe',
[DIMENSION_ID_PERIOD]: {
id: DIMENSION_ID_PERIOD,
name: i18n.t('Period'),
iconName: 'PeriodIcon',
icon: PeriodIcon,
},
ou: {
id: 'ou',
[DIMENSION_ID_ORGUNIT]: {
id: DIMENSION_ID_ORGUNIT,
name: i18n.t('Organisation Unit'),
iconName: 'OrgUnitIcon',
icon: OrgUnitIcon,
Expand Down
16 changes: 16 additions & 0 deletions src/modules/layout/__tests__/axisGetAllItems.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { axisGetAllItems } from '../axisGetAllItems'
import {
TEST_AXIS_COLUMNS,
TEST_ITEMS_IN_AXIS_1,
TEST_ITEMS_IN_AXIS_2,
} from '../testResources'

describe('axisGetAllItems', () => {
it('should return all items in all dimensions in the axis', () => {
expect(axisGetAllItems(TEST_AXIS_COLUMNS)).toEqual(TEST_ITEMS_IN_AXIS_1)

expect(axisGetAllItems(TEST_AXIS_COLUMNS)).not.toEqual(
TEST_ITEMS_IN_AXIS_2
)
})
})
18 changes: 18 additions & 0 deletions src/modules/layout/__tests__/axisGetDimension.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { axisGetDimension } from '../axisGetDimension'
import { TEST_AXIS_COLUMNS, TEST_AXIS_ROWS } from '../testResources'
import { dimensionGetId } from '../dimensionGetId'

describe('axisGetDimension', () => {
it('should return the dimension specified by id', () => {
const columnDimension = TEST_AXIS_COLUMNS[0]
const rowDimension = TEST_AXIS_ROWS[0]

expect(
axisGetDimension(TEST_AXIS_COLUMNS, dimensionGetId(columnDimension))
).toEqual(columnDimension)

expect(
axisGetDimension(TEST_AXIS_COLUMNS, dimensionGetId(rowDimension))
).not.toEqual(columnDimension)
})
})
20 changes: 20 additions & 0 deletions src/modules/layout/__tests__/axisGetDimensionIds.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { AXIS } from '../axis'
import { axisGetDimensionIds } from '../axisGetDimensionIds'
import { DIMENSION_PROP_ID } from '../dimension'
import { TEST_AXIS_COLUMNS, TEST_AXIS_ROWS } from '../testResources'

describe('axisGetDimensionIds', () => {
it('should return the id of the dimensions in the axis', () => {
const columnDimIds = TEST_AXIS_COLUMNS.map(
item => item[DIMENSION_PROP_ID.name]
)

expect(axisGetDimensionIds(TEST_AXIS_COLUMNS)).toEqual(columnDimIds)

expect(axisGetDimensionIds(TEST_AXIS_ROWS)).not.toEqual(columnDimIds)
})

it('should return the default value', () => {
expect(axisGetDimensionIds('Not an axis')).toEqual(AXIS.defaultValue)
})
})
10 changes: 10 additions & 0 deletions src/modules/layout/__tests__/axisHasDataDimension.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TEST_AXIS_COLUMNS, TEST_AXIS_ROWS } from '../testResources'
import { axisHasDataDimension } from '../axisHasDataDimension'

describe('axisHasDataDimension', () => {
it('should return true if the dimension is found in the axis', () => {
expect(axisHasDataDimension(TEST_AXIS_COLUMNS)).toBe(true)

expect(axisHasDataDimension(TEST_AXIS_ROWS)).toBe(false)
})
})
21 changes: 21 additions & 0 deletions src/modules/layout/__tests__/axisHasDimension.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { axisHasDimension } from '../axisHasDimension'
import { TEST_AXIS_COLUMNS, TEST_AXIS_ROWS } from '../testResources'
import { DIMENSION_PROP_ID } from '../dimension'

describe('axisHasDimension', () => {
it('should return true if the dimension is found in the axis, otherwise false', () => {
expect(
axisHasDimension(
TEST_AXIS_COLUMNS,
TEST_AXIS_COLUMNS[0][DIMENSION_PROP_ID.name]
)
).toBe(true)

expect(
axisHasDimension(
TEST_AXIS_COLUMNS,
TEST_AXIS_ROWS[0][DIMENSION_PROP_ID.name]
)
).toBe(false)
})
})
10 changes: 10 additions & 0 deletions src/modules/layout/__tests__/axisHasPeriodDimension.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TEST_AXIS_COLUMNS, TEST_AXIS_ROWS } from '../testResources'
import { axisHasPeriodDimension } from '../axisHasPeriodDimension'

describe('axisHasPeriodDimension', () => {
it('should return true if the dimension is found in the axis', () => {
expect(axisHasPeriodDimension(TEST_AXIS_COLUMNS)).toBe(false)

expect(axisHasPeriodDimension(TEST_AXIS_ROWS)).toBe(true)
})
})
10 changes: 10 additions & 0 deletions src/modules/layout/__tests__/axisIsEmpty.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TEST_AXIS_COLUMNS, TEST_AXIS_EMPTY } from '../testResources'
import { axisIsEmpty } from '../axisIsEmpty'

describe('axisIsEmpty', () => {
it('should return true if the axis has no dimensions, otherwise false', () => {
expect(axisIsEmpty(TEST_AXIS_COLUMNS)).toBe(false)

expect(axisIsEmpty(TEST_AXIS_EMPTY)).toBe(true)
})
})
14 changes: 14 additions & 0 deletions src/modules/layout/__tests__/dimensionCreate.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { DIMENSION_PROP_ID, DIMENSION_PROP_ITEMS } from '../dimension'
import { dimensionCreate } from '../dimensionCreate'
import { TEST_DIMENSION_1 } from '../testResources'

describe('dimensionCreate', () => {
it('should return the created dimension', () => {
const dimensionId = TEST_DIMENSION_1[DIMENSION_PROP_ID.name]
const itemIds = TEST_DIMENSION_1[DIMENSION_PROP_ITEMS.name].map(
item => item.id
)

expect(dimensionCreate(dimensionId, itemIds)).toEqual(TEST_DIMENSION_1)
})
})
11 changes: 11 additions & 0 deletions src/modules/layout/__tests__/dimensionGetId.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { dimensionGetId } from '../dimensionGetId'
import { DIMENSION_PROP_ID } from '../dimension'
import { TEST_DIMENSION_1 } from '../testResources'

describe('dimensionGetId', () => {
it('should return the dimension id', () => {
expect(dimensionGetId(TEST_DIMENSION_1)).toBe(
TEST_DIMENSION_1[DIMENSION_PROP_ID.name]
)
})
})
14 changes: 14 additions & 0 deletions src/modules/layout/__tests__/dimensionGetItemIds.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { dimensionGetItemIds } from '../dimensionGetItemIds'
import { TEST_DIMENSION_1 } from '../testResources'
import { DIMENSION_PROP_ITEMS } from '../dimension'
import { ITEM_PROP_ID } from '../item'

describe('dimensionGetItemIds', () => {
it('should return the item ids in the dimension', () => {
expect(dimensionGetItemIds(TEST_DIMENSION_1)).toEqual(
TEST_DIMENSION_1[DIMENSION_PROP_ITEMS.name].map(
item => item[ITEM_PROP_ID.name]
)
)
})
})
17 changes: 17 additions & 0 deletions src/modules/layout/__tests__/dimensionGetItems.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DIMENSION_PROP_ITEMS } from '../dimension'
import { TEST_DIMENSION_1 } from '../testResources'
import { dimensionGetItems } from '../dimensionGetItems'

describe('dimensionGetItems', () => {
it('should return the items in the dimension', () => {
expect(dimensionGetItems(TEST_DIMENSION_1)).toEqual(
TEST_DIMENSION_1[DIMENSION_PROP_ITEMS.name]
)
})

it('should return the default value', () => {
expect(dimensionGetItems('Not a dimension')).toEqual(
DIMENSION_PROP_ITEMS.defaultValue
)
})
})
21 changes: 21 additions & 0 deletions src/modules/layout/__tests__/dimensionIs.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { TEST_DIMENSION_1, TEST_DIMENSION_2 } from '../testResources'
import { DIMENSION_PROP_ID } from '../dimension'
import { dimensionIs } from '../dimensionIs'

describe('dimensionIs', () => {
it('should return true if it is the specified dimension, otherwise false', () => {
expect(
dimensionIs(
TEST_DIMENSION_1,
TEST_DIMENSION_1[DIMENSION_PROP_ID.name]
)
).toBe(true)

expect(
dimensionIs(
TEST_DIMENSION_2,
TEST_DIMENSION_1[DIMENSION_PROP_ID.name]
)
).toBe(false)
})
})
Loading

0 comments on commit 7c8658f

Please sign in to comment.