Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion cypress/elements/map_context_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@ import { getMaps } from './map_canvas.js'
export const DRILL_UP = 'context-menu-drill-up'
export const DRILL_DOWN = 'context-menu-drill-down'
export const VIEW_PROFILE = 'context-menu-view-profile'
export const ZOOM_TO_FEATURE = 'context-menu-zoom-to-feature'
export const SHOW_LONG_LAT = 'context-menu-show-long-lat'

const ALL_OPTIONS = [DRILL_UP, DRILL_DOWN, VIEW_PROFILE, SHOW_LONG_LAT]
const ALL_OPTIONS = [
DRILL_UP,
DRILL_DOWN,
VIEW_PROFILE,
ZOOM_TO_FEATURE,
SHOW_LONG_LAT,
]

export const expectContextMenuOptions = (availableOptions) => {
getMaps()
Expand Down
62 changes: 35 additions & 27 deletions cypress/integration/dataTable.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('data table', () => {
checkTableCell({ row: 6, column: 1, expectedContent: 'Upper Bambara' })

// Sort by name
cy.get('button[title="Sort by Name"]').click()
cy.getByDataTest('data-table-column-sort-button-Name').click()

// confirm that the rows are sorted by Name descending
checkTableCell({ row: 0, column: 1, expectedContent: 'Upper Bambara' })
Expand All @@ -116,18 +116,20 @@ describe('data table', () => {
.should('have.length', 5)

// Sort by value
cy.get('button[title="Sort by Value"]').click()
cy.getByDataTest('data-table-column-sort-button-Value').click()

// check that the rows are sorted by Value ascending
checkTableCell({ row: 0, column: 3, expectedContent: '35' })
checkTableCell({ row: 4, column: 3, expectedContent: '76' })

// click on a row
// right-click a row and select "View profile"
cy.getByDataTest('bottom-panel')
.findByDataTest('dhis2-uicore-tablebody')
.findByDataTest('dhis2-uicore-datatablerow')
.first()
.click()
.rightclick()

cy.getByDataTest('data-table-context-menu-view-profile').click()

// check that the org unit profile drawer is opened
cy.getByDataTest('org-unit-profile').should('be.visible')
Expand Down Expand Up @@ -230,18 +232,23 @@ describe('data table', () => {
.should('have.length', 2)

// Sort by Age in years
cy.get('button[title="Sort by Age in years"]').click()
cy.getByDataTest('data-table-column-sort-button-Age in years').click()

// confirm that the rows are sorted by Age in years descending
checkTableCell({ row: 0, column: 7, expectedContent: '32' })
checkTableCell({ row: 1, column: 7, expectedContent: '6' })
// Confirm that the rows are sorted by Age in years ascending
// (the first click on a new column always sorts ascending)
checkTableCell({ row: 0, column: 7, expectedContent: '6' })
checkTableCell({ row: 1, column: 7, expectedContent: '32' })

// click on a row
// right-click a row: Event layers have no profile to view
cy.getByDataTest('bottom-panel')
.findByDataTest('dhis2-uicore-tablebody')
.findByDataTest('dhis2-uicore-datatablerow')
.first()
.click()
.rightclick()

cy.getByDataTest('data-table-context-menu-view-profile').should(
'not.exist'
)

// check that the org unit profile drawer is NOT opened
cy.getByDataTest('org-unit-profile').should('not.exist')
Expand Down Expand Up @@ -290,41 +297,42 @@ describe('data table', () => {
// Confirm that the sort order is initially ascending by Name
checkTableCell({ row: 0, column: 1, expectedContent: 'Bendu CHC' })

cy.get('button[title="Sort by Value"]').click()
// First click on a new column always sorts ascending
cy.getByDataTest('data-table-column-sort-button-Value').click()

// Check that first row has Gbamgbama CHC with value 117.98
checkTableCell({ row: 0, column: 1, expectedContent: 'Gbamgbama CHC' })
checkTableCell({ row: 0, column: 3, expectedContent: '117.98' })
// Check that first row has Tihun CHC with value 28.63
checkTableCell({ row: 0, column: 1, expectedContent: 'Tihun CHC' })
checkTableCell({ row: 0, column: 3, expectedContent: '28.63' })

// Check that row 5 has Tihun CHC with value 28.63
checkTableCell({ row: 5, column: 1, expectedContent: 'Tihun CHC' })
checkTableCell({ row: 5, column: 3, expectedContent: '28.63' })
// Check that row 5 has Gbamgbama CHC with value 117.98
checkTableCell({ row: 5, column: 1, expectedContent: 'Gbamgbama CHC' })
checkTableCell({ row: 5, column: 3, expectedContent: '117.98' })

// Check that row 6 has no value (undefined)
checkTableCell({ row: 6, column: 3, expectedContent: '' })

// Sort ascending by Value
cy.get('button[title="Sort by Value"]').click()
// Sort descending by Value
cy.getByDataTest('data-table-column-sort-button-Value').click()

checkTableCell({ row: 0, column: 1, expectedContent: 'Tihun CHC' })
checkTableCell({ row: 0, column: 3, expectedContent: '28.63' })
checkTableCell({ row: 0, column: 1, expectedContent: 'Gbamgbama CHC' })
checkTableCell({ row: 0, column: 3, expectedContent: '117.98' })

checkTableCell({ row: 5, column: 1, expectedContent: 'Gbamgbama CHC' })
checkTableCell({ row: 5, column: 3, expectedContent: '117.98' })
checkTableCell({ row: 5, column: 1, expectedContent: 'Tihun CHC' })
checkTableCell({ row: 5, column: 3, expectedContent: '28.63' })

checkTableCell({ row: 6, column: 3, expectedContent: '' })

// Sort by index and scroll to the top
cy.get('button[title="Sort by Index"]').click()
// Sort by index (a new column, so ascending) and scroll to the top
cy.getByDataTest('data-table-column-sort-button-Index').click()
cy.get('[data-testid="virtuoso-scroller"]').scrollTo('top')

checkTableCell({ row: 0, column: 0, expectedContent: '28' })
checkTableCell({ row: 0, column: 0, expectedContent: '0' })

// Check that row 0 range value is empty
checkTableCell({ row: 0, column: 5, expectedContent: '' })

// Sort by range, which is a string
cy.get('button[title="Sort by Range"]').click()
cy.getByDataTest('data-table-column-sort-button-Range').click()

// Check that row 0 range value has value '0-40'
checkTableCell({ row: 0, column: 5, expectedContent: '0 – 40' })
Expand Down
6 changes: 4 additions & 2 deletions cypress/integration/layers/geojsonlayer.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ describe('GeoJSON URL Layer', () => {
.find('tr')
.should('have.length', 1)

// open the feature panel by clicking on the row
// open the feature panel via the row context menu
cy.getByDataTest('bottom-panel')
.find('tbody')
.find('tr')
.find('td')
.first()
.click()
.rightclick()

cy.getByDataTest('data-table-context-menu-view-profile').click()

// check that Feature profile is displayed
cy.getByDataTest('details-panel')
Expand Down
3 changes: 3 additions & 0 deletions cypress/integration/layers/thematiclayer.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
DRILL_UP,
DRILL_DOWN,
VIEW_PROFILE,
ZOOM_TO_FEATURE,
SHOW_LONG_LAT,
expectContextMenuOptions,
} from '../../elements/map_context_menu.js'
Expand Down Expand Up @@ -535,6 +536,7 @@ context('Thematic Layers', () => {
{ name: DRILL_UP, disabled: true },
{ name: DRILL_DOWN },
{ name: VIEW_PROFILE },
{ name: ZOOM_TO_FEATURE },
{ name: SHOW_LONG_LAT },
])
})
Expand Down Expand Up @@ -723,6 +725,7 @@ context('Thematic Layers', () => {
{ name: DRILL_UP, disabled: true },
{ name: DRILL_DOWN },
{ name: VIEW_PROFILE },
{ name: ZOOM_TO_FEATURE },
])
})

Expand Down
36 changes: 24 additions & 12 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,18 @@ msgstr "Operator"
msgid "Date"
msgstr "Date"

msgid "{{filtered}} of {{total}} rows"
msgstr "{{filtered}} of {{total}} rows"

msgid "{{total}} rows"
msgstr "{{total}} rows"

msgid "Clear filters"
msgstr "Clear filters"

msgid "Close"
msgstr "Close"

msgid "No results found"
msgstr "No results found"

Expand All @@ -167,6 +179,18 @@ msgstr "Something went wrong"
msgid "Search"
msgstr "Search"

msgid "Drill up one level"
msgstr "Drill up one level"

msgid "Drill down one level"
msgstr "Drill down one level"

msgid "View profile"
msgstr "View profile"

msgid "Zoom to feature"
msgstr "Zoom to feature"

msgid "Data table is not supported when events are grouped on the server."
msgstr "Data table is not supported when events are grouped on the server."

Expand Down Expand Up @@ -261,9 +285,6 @@ msgstr "Map download is not supported by your browser. Try Google Chrome or Fire
msgid "Cancel"
msgstr "Cancel"

msgid "Close"
msgstr "Close"

msgid "No organisation units are selected"
msgstr "No organisation units are selected"

Expand Down Expand Up @@ -774,15 +795,6 @@ msgstr "Selected org units: No coordinates found"
msgid "Error"
msgstr "Error"

msgid "Drill up one level"
msgstr "Drill up one level"

msgid "Drill down one level"
msgstr "Drill down one level"

msgid "View profile"
msgstr "View profile"

msgid "Show longitude/latitude"
msgstr "Show longitude/latitude"

Expand Down
5 changes: 5 additions & 0 deletions src/actions/dataFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ export const clearDataFilter = (layerId, fieldId) => ({
layerId,
fieldId,
})

export const clearDataFilters = (layerId) => ({
type: types.DATA_FILTERS_CLEAR_ALL,
layerId,
})
49 changes: 49 additions & 0 deletions src/components/core/icons.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,54 @@
import PropTypes from 'prop-types'
import React from 'react'

export const SortIcon = ({ direction }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
style={{ display: 'block' }}
>
<g fill="none" fillRule="evenodd">
<polygon
fill={
direction === 'desc'
? 'var(--colors-blue700)'
: 'var(--colors-grey500)'
}
points="4 9 12 9 8 14"
/>
<polygon
fill={
direction === 'asc'
? 'var(--colors-blue700)'
: 'var(--colors-grey500)'
}
points="4 7 12 7 8 2"
/>
</g>
</svg>
)

SortIcon.propTypes = {
direction: PropTypes.string,
}

// Magnifying glass with a + sign inside the lens — "zoom to feature"
export const IconZoomIn16 = () => (
<svg
height="16"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 1a5 5 0 013.871 8.164l4.483 4.482-.708.708L9.164 9.87A5 5 0 116 1zm0 1a4 4 0 100 8 4 4 0 000-8zM3.5 5.5L5.5 5.5 5.5 3.5 6.5 3.5 6.5 5.5 8.5 5.5 8.5 6.5 6.5 6.5 6.5 8.5 5.5 8.5 5.5 6.5 3.5 6.5Z"
fill="currentColor"
/>
</svg>
)

export const IconDrag = () => (
<svg
height="8"
Expand Down
Loading
Loading