Skip to content

Commit

Permalink
fix: include title page in edit preview but scroll to below it [DHIS2…
Browse files Browse the repository at this point in the history
…-9417] (#1038)

In contrast to the Print Layout (from View mode), the Edit print preview did not have a title page, which means there was no page break prior to the first item page. This means the first item page had more vertical space in Edit print preview than in Print Layout. The result could lead to more items getting on the first page in Edit preview, than the actual print.

The solution is to include the title page in Edit preview as well, so that Edit preview and Print Layout are identical. Then, to allow the user to focus on the important stuff (item print layout), the Edit preview is auto scrolled to the top of the first item page.
  • Loading branch information
jenniferarnesen authored Sep 8, 2020
1 parent 8c938e2 commit 2c49410
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 10 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@dhis2/ui": "^5.5.4",
"@material-ui/core": "^3.9.2",
"@material-ui/icons": "^4.9.1",
"classnames": "^2.2.6",
"d2": "^31.8.1",
"d2-utilizr": "^0.2.16",
"i18next": "^19.7.0",
Expand Down
10 changes: 6 additions & 4 deletions src/components/Dashboard/PrintLayoutDashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { spacers } from '@dhis2/ui'
import cx from 'classnames'

import PrintInfo from './PrintInfo'
import PrintActionsBar from './PrintActionsBar'
Expand Down Expand Up @@ -103,9 +104,7 @@ export class PrintLayoutDashboard extends Component {

addPageBreaks(this.props)

if (!this.props.fromEdit) {
this.props.addDashboardItem({ type: PRINT_TITLE_PAGE })
}
this.props.addDashboardItem({ type: PRINT_TITLE_PAGE })
}
}

Expand Down Expand Up @@ -137,7 +136,10 @@ export class PrintLayoutDashboard extends Component {
{!this.props.fromEdit && (
<PrintActionsBar id={this.props.dashboard.id} />
)}
<div className={classes.wrapper} style={this.getWrapperStyle()}>
<div
className={cx(classes.wrapper, 'scroll-area')}
style={this.getWrapperStyle()}
>
{!this.props.fromEdit && <PrintInfo isLayout={true} />}
<div
className={classes.pageOuter}
Expand Down
38 changes: 37 additions & 1 deletion src/components/ItemGrid/PrintLayoutItemGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import i18n from '@dhis2/d2-i18n'
import sortBy from 'lodash/sortBy'
import ReactGridLayout from 'react-grid-layout'
import { Layer, CenteredContent, CircularLoader } from '@dhis2/ui'
import cx from 'classnames'

import { Item } from '../Item/Item'
import NoContentMessage from '../../widgets/NoContentMessage'
Expand All @@ -14,6 +16,7 @@ import {
sGetPrintDashboardRoot,
sGetPrintDashboardItems,
} from '../../reducers/printDashboard'
import { sGetIsEditing } from '../../reducers/editDashboard'

import {
GRID_ROW_HEIGHT,
Expand All @@ -25,6 +28,7 @@ import {
import {
a4LandscapeWidthPx,
getDomGridItemsSortedByYPos,
getTransformYPx,
} from '../../modules/printUtils'

import { PRINT_LAYOUT } from '../Dashboard/dashboardModes'
Expand All @@ -42,8 +46,26 @@ export class PrintLayoutItemGrid extends Component {
onLayoutChange = newLayout => {
this.props.updateDashboardLayout(newLayout)
}

isFirstPageBreak = item => {
if (item.type !== PAGEBREAK) {
return false
}

const pageBreaks = this.props.dashboardItems.filter(
i => i.type === PAGEBREAK
)

const sortedPageBreaks = sortBy(pageBreaks, ['y'])
return item.y === sortedPageBreaks[0].y
}

getItemComponent = item => {
const itemClassNames = [item.type, 'print', 'layout'].join(' ')
// the first-page-break class is used in Edit print preview
const itemClassNames = cx('print', 'layout', `${item.type}`, {
'first-page-break':
this.props.isEditing && this.isFirstPageBreak(item),
})

return (
<div key={item.i} className={itemClassNames}>
Expand All @@ -65,6 +87,7 @@ export class PrintLayoutItemGrid extends Component {

for (let i = sortedElements.length - 1; i >= 0; --i) {
const item = sortedElements[i]

if (item.type === PAGEBREAK) {
if (!foundNonPageBreak) {
item.el.classList.add('removed')
Expand Down Expand Up @@ -98,6 +121,17 @@ export class PrintLayoutItemGrid extends Component {
if (gridElement) {
gridElement.style.height = `${maxHeight}px`
}

if (this.props.isEditing) {
//scroll to below the title page - which is middle of the first pagebreak
const firstBreak = document.querySelector('.first-page-break')
if (firstBreak && firstBreak.style && firstBreak.style.transform) {
const yPos = getTransformYPx(firstBreak.style)
const scrollArea = document.querySelector('.scroll-area')

scrollArea && scrollArea.scroll(0, yPos + 50)
}
}
}

componentDidMount() {
Expand Down Expand Up @@ -155,6 +189,7 @@ export class PrintLayoutItemGrid extends Component {

PrintLayoutItemGrid.propTypes = {
dashboardItems: PropTypes.array,
isEditing: PropTypes.bool,
isLoading: PropTypes.bool,
updateDashboardLayout: PropTypes.func,
}
Expand All @@ -169,6 +204,7 @@ const mapStateToProps = state => {
return {
isLoading: sGetSelectedIsLoading(state) || !selectedDashboard,
dashboardItems: sGetPrintDashboardItems(state).filter(hasShape),
isEditing: sGetIsEditing(state),
}
}

Expand Down
53 changes: 52 additions & 1 deletion src/modules/__tests__/printUtils.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getDomGridItemsSortedByYPos } from '../printUtils'
import { getDomGridItemsSortedByYPos, getTransformYPx } from '../printUtils'

describe('printUtils', () => {
describe('getDomGridItemsSortedByYPos', () => {
Expand Down Expand Up @@ -303,4 +303,55 @@ describe('printUtils', () => {
)
})
})

describe('getTransformYPx', () => {
it('returns null if style is not defined', () => {
const style = undefined
expect(getTransformYPx(style)).toEqual(null)
})

it('returns null if no transform property', () => {
const style = {}
expect(getTransformYPx(style)).toEqual(null)
})

it('returns null if transform is malformed', () => {
const style = {
transform: 'ab',
}
expect(getTransformYPx(style)).toEqual(null)
})

it('returns y position if px in 100s', () => {
const style = {
transform: 'translate(10px, 300px)',
}

expect(getTransformYPx(style)).toEqual(300)
})

it('returns y position if px in 10s', () => {
const style = {
transform: 'translate(10px, 30px)',
}

expect(getTransformYPx(style)).toEqual(30)
})

it('returns y position if px in 1000s', () => {
const style = {
transform: 'translate(10px, 3000px)',
}

expect(getTransformYPx(style)).toEqual(3000)
})

it('returns null if not px units', () => {
const style = {
transform: 'translate(10%, 50%)',
}

expect(getTransformYPx(style)).toEqual(null)
})
})
})
21 changes: 17 additions & 4 deletions src/modules/printUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ export const a4LandscapeWidthPx = 1102

export const MAX_ITEM_GRID_HEIGHT = 33

export const getTransformYPx = elStyle => {
if (!elStyle || !elStyle.transform) {
return null
}

// find valid transforms - those with y pixels
// the code is expecting the transform prop to
// look like: translate(10px, 300px)
const transformY = elStyle.transform.split(' ')[1]?.match(/(\d+)px/)
if (transformY) {
return parseInt(transformY[1])
} else {
return null
}
}

export const getDomGridItemsSortedByYPos = elements => {
const types = Object.keys(itemTypeMap)
const elementsWithBoundingRect = orArray(elements).map(el => {
Expand All @@ -17,10 +33,7 @@ export const getDomGridItemsSortedByYPos = elements => {
)

const rect = el.getBoundingClientRect()

const y = el.style.transform
? parseInt(el.style.transform?.split(' ')[1]?.slice(0, -3))
: parseInt(rect.y)
const y = getTransformYPx(el.style) || parseInt(rect.y)

return {
type,
Expand Down

0 comments on commit 2c49410

Please sign in to comment.