Skip to content

Commit

Permalink
Merge pull request #5069 from akvo/5068-bug-enumerator-web-form-in-mo…
Browse files Browse the repository at this point in the history
…bile-view

[#5068] Fix see all submissions modal in mobile view
  • Loading branch information
zuhdil authored Mar 15, 2023
2 parents 8e7b9e7 + 4a5e943 commit b144f44
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 68 deletions.
113 changes: 64 additions & 49 deletions akvo/rsr/spa/app/components/AllSubmissionsModal.jsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,90 @@
/* global document */
import React from 'react'
import { Modal } from 'antd'
import { Modal, Row, Col, Tag, Badge } from 'antd'
import moment from 'moment'
import SVGInline from 'react-svg-inline'
import { groupBy, isEmpty } from 'lodash'
import classNames from 'classnames'
import { nicenum } from '../utils/misc'
import statusPending from '../images/status-pending.svg'
import statusApproved from '../images/status-approved.svg'
import statusRevision from '../images/status-revision.svg'

export const AllSubmissionsModal = ({ visible, onCancel, period }) => {
let width = 460
if (period.disaggregations) {
width += period.disaggregations.length * 100
const StatusIcon = ({ status }) => {
if (status === 'A') {
return <SVGInline svg={statusApproved} />
}
if (width > document.body.clientWidth - 100) {
width = document.body.clientWidth - 100
if (['D', 'P'].includes(status)) {
return <SVGInline svg={statusPending} />
}
if (status === 'R') {
return <SVGInline svg={statusRevision} />
}
return null
}

export const AllSubmissionsModal = ({
visible,
onCancel,
updates,
width = 520,
activeKeys = [],
dsgOnly = false,
}) => {
const _updates = updates?.filter((u) => (
(dsgOnly && u?.disaggregations?.length) ||
(!dsgOnly)
))
return (
<Modal {...{ visible, onCancel, width }} title="Period latest submissions" footer={null} className="all-submissions-modal">
<table>
{period.updates.map(update => {
const dsgGroups = {}
update.disaggregations.forEach(item => {
if (!dsgGroups[item.category]) dsgGroups[item.category] = []
dsgGroups[item.category].push(item)
if (period.disaggregationTargets.length > 0) {
const target = period.disaggregationTargets.find(it => it.typeId === item.typeId)
if (target != null) dsgGroups[item.category][dsgGroups[item.category].length - 1].targetValue = target.value
}
})
const dsgKeys = Object.keys(dsgGroups)
<div>
{_updates?.map(update => {
const _disaggregations = update?.disaggregations?.filter((dg) => activeKeys?.includes(dg?.type))
const dsgGroups = groupBy(_disaggregations, 'category')
const userName = (
isEmpty(update?.userDetails?.firstName) &&
isEmpty(update?.userDetails?.lastName)
)
? update?.userDetails?.email
: `${update.userDetails.firstName} ${update.userDetails.lastName}`
return (
<tr>
<td>
<Row type="flex" justify="space-between" align="middle" key={update.id}>
<Col xs={24}>
<div className="svg-text">
<SVGInline svg={update.status === 'A' ? statusApproved : update.status === 'P' ? statusPending : statusRevision} />
<StatusIcon status={update?.status} />
<div className="text">
{update.userDetails.firstName} {update.userDetails.lastName}
{userName}
<span className="date">{moment(update.createdAt).format('DD MMM YYYY')}</span>
</div>
</div>
</td>
<td className="spacer">&nbsp;</td>
{dsgKeys.map(dsgKey => [
<td>
<div className="dsg-group">
<div className="h-holder">
<h5>{dsgKey}</h5>
</div>
<ul>
{dsgGroups[dsgKey].map((dsg) => [
<li>
<div className="label">{dsg.type}</div>
</Col>
<Col xs={24} className="dsg-tags">
{
Object.keys(dsgGroups).map((dsgKey, dx) => (
<div key={dx}>
<h6>{dsgKey}</h6>
{dsgGroups[dsgKey]?.map((dsg, ix) => (
<Tag key={ix}>
<div>
<b>{nicenum(dsg.value)}</b>
{dsg.targetValue && <b> ({Math.round(((dsg.value / dsg.targetValue) * 100 * 10) / 10)}%)</b>}
{dsg?.type}
</div>
</li>
])}
</ul>
</div>
</td>
])}
<td>
<div className="value">{nicenum(update.value)}</div>
</td>
</tr>
<div>
<Badge count={dsg?.value} className={classNames('badge', { [update?.status]: true })} showZero />
</div>
</Tag>
))}
</div>
))
}
</Col>
<Col xs={24}>
<h6>Value</h6>
<div className={classNames('value', { [update?.status]: true })}>{nicenum(update.value)}</div>
</Col>
</Row>
)
}
)}
</table>
</div>
</Modal>
)
}
37 changes: 34 additions & 3 deletions akvo/rsr/spa/app/components/UpdatesHistory.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import React from 'react'
import React, { useState } from 'react'
import {
Row,
Col,
Collapse,
Table,
Tooltip,
Button,
Icon,
} from 'antd'
import classNames from 'classnames'
import isEqual from 'lodash/isEqual'

import ExpandIcon from './ExpandIcon'
import { toCapitalize } from '../utils/string'
import { AllSubmissionsModal } from './AllSubmissionsModal'

const { Panel } = Collapse
const { Column } = Table
Expand All @@ -30,9 +34,14 @@ const setColumns = (value, key) => ({
const UpdatesHistory = ({
columns,
tables,
updates,
disaggregations,
disaggregationTargets,
activeKeys = DEFAULT_ACTIVE_KEYS,
mneView = false,
}) => {
const [visible, setVisible] = useState(false)

const getActiveKeys = (value) => activeKeys?.length
? [...activeKeys, ...DEFAULT_ACTIVE_KEYS]?.includes(value)
: value
Expand Down Expand Up @@ -68,11 +77,33 @@ const UpdatesHistory = ({
const tableProps = mneView ? { pagination: false, scroll: { x: 500 } } : { pagination: false }
return (
<Row>
<Col>
<Col className="table-history-sm">
<Tooltip title="Updates history">
<Button type="link" onClick={() => setVisible(true)}>
<Icon type="unordered-list" />
</Button>
</Tooltip>
<AllSubmissionsModal
{...{
visible,
updates,
activeKeys,
disaggregations,
disaggregationTargets,
}}
onCancel={() => setVisible(false)}
dsgOnly={!(isEqual(activeKeys, DEFAULT_ACTIVE_KEYS))}
/>
</Col>
<Col className="table-history-md">
<Collapse
bordered={false}
expandIconPosition="right"
expandIcon={({ isActive }) => <ExpandIcon isActive={isActive} open="close" close="unordered-list" />}
expandIcon={({ isActive }) => (
<Tooltip title="Updates history">
<ExpandIcon isActive={isActive} open="close" close="unordered-list" />
</Tooltip>
)}
className="collapse-history"
>
<Panel>
Expand Down
2 changes: 1 addition & 1 deletion akvo/rsr/spa/app/images/status-pending.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion akvo/rsr/spa/app/images/status-revision.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const DisaggregationsInput = ({
/>
) : (
<div>
<div style={{ paddingLeft: '1em' }}>{dsg.value}</div>
<h6>{dsg.value}</h6>
<FinalField
name={`disaggregations[${disaggregations.findIndex(it => it.typeId === dsg.id && group.id === it.groupId)}].numerator`}
control="input-number"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,40 @@
white-space: nowrap;
}
}
.table-history-sm {
display: none;
text-align: right;
.ant-btn-link {
color: rgba(0, 0, 0, 0.85);
}
}
.table-history-md {
display: block;
}
}

/*
* Device = Low Resolution Tablets, Mobiles (Landscape)
* Screen = B/w 481px to 767px
*/
@media (min-width: 481px) and (max-width: 767px) {
#rsr-form-container .table-history-sm {
display: block;
}
#rsr-form-container .table-history-md {
display: none;
}
}

/**
* Device = Most of the Smartphones Mobiles (Portrait)
* Screen = B/w 320px to 479px
*/
@media (min-width: 280px) and (max-width: 480px) {
#rsr-form-container .table-history-sm {
display: block;
}
#rsr-form-container .table-history-md {
display: none;
}
}
4 changes: 2 additions & 2 deletions akvo/rsr/spa/app/modules/results/enumerator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ const AddUpdate = ({ period, indicator, addUpdateToPeriod, patchUpdateInPeriod,
precision={2}
verticalGuides={1}
{...period}
/>
/>
)
}}
</FormSpy>
Expand Down Expand Up @@ -732,7 +732,7 @@ const PrevUpdate = ({ update, period, indicator }) => {
<Button type="link" onClick={() => setShowSubmissionsModal(true)}>See all submissions</Button>
</div>
}
<AllSubmissionsModal period={period} visible={showSubmissionsModal} onCancel={() => setShowSubmissionsModal(false)} />
<AllSubmissionsModal {...period} visible={showSubmissionsModal} onCancel={() => setShowSubmissionsModal(false)} />
</div>
)
}
Expand Down
Loading

0 comments on commit b144f44

Please sign in to comment.