Skip to content

Commit

Permalink
[#5080] Create audit trail modal
Browse files Browse the repository at this point in the history
  • Loading branch information
ifirmawan committed Aug 24, 2022
1 parent f343c4a commit a972475
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 112 deletions.
5 changes: 3 additions & 2 deletions akvo/rsr/spa/app/components/AddUpdate.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import moment from 'moment'
import classNames from 'classnames'
import SimpleMarkdown from 'simple-markdown'
import orderBy from 'lodash/orderBy'
import kebabCase from 'lodash/kebabCase'
import api, { config } from '../utils/api'
import { nicenum, dateTransform, kebabClassName } from '../utils/misc'
import { nicenum, dateTransform } from '../utils/misc'
import FinalField from '../utils/final-field'
import RTE from '../utils/rte'
import DsgOverview from '../modules/results/dsg-overview'
Expand Down Expand Up @@ -204,7 +205,7 @@ export const AddUpdate = ({
? draftUpdate : recentUpdate
? ({ ...recentUpdate, status: recentUpdate.status === 'A' ? 'A' : 'SR' }) : (pendingUpdate && pendingUpdate.status === 'P')
? pendingUpdate : null
const updateClass = kebabClassName(updateLabel?.statusDisplay)
const updateClass = kebabCase(updateLabel?.statusDisplay)
return [
<Panel
{...props}
Expand Down
15 changes: 15 additions & 0 deletions akvo/rsr/spa/app/components/Icon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import { Icon as AntIcon } from 'antd'
import SVGInline from 'react-svg-inline'
import get from 'lodash/get'
import { icons } from '../utils/images'


const Icon = ({ type, ...props }) => {
const customIcon = get(icons, type)
return customIcon
? <SVGInline svg={customIcon} {...props} />
: <AntIcon type={type} {...props} />
}

export default Icon
2 changes: 1 addition & 1 deletion akvo/rsr/spa/app/components/ProgressBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const ProgressBar = ({ period, values, valueRef, onlyApproved = false }) => {
}
}
return (
<Tooltip title={String(value.value).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}>
<Tooltip title={String(value.value).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} key={index}>
<div {...barProps}>
{
(
Expand Down
1 change: 1 addition & 0 deletions akvo/rsr/spa/app/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export { MobileSlider } from './MobileSlider'
export { PrevUpdate } from './PrevUpdate'
export { DeclinePopup } from './DeclinePopup'
export { IndicatorItem } from './IndicatorItem'
export { default as Icon } from './Icon'
3 changes: 3 additions & 0 deletions akvo/rsr/spa/app/images/clock-history.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions akvo/rsr/spa/app/images/edit-pencil.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
224 changes: 131 additions & 93 deletions akvo/rsr/spa/app/modules/results-admin/TobeReported.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,28 @@ import {
Row,
Col,
Modal,
Icon,
message
} from 'antd'
import { useTranslation } from 'react-i18next'
import SimpleMarkdown from 'simple-markdown'
import SVGInline from 'react-svg-inline'
import classNames from 'classnames'
import moment from 'moment'
import { isEmpty } from 'lodash'
import { isEmpty, kebabCase } from 'lodash'
import { connect } from 'react-redux'

import './TobeReported.scss'
import editButton from '../../images/edit-button.svg'
import api from '../../utils/api'
import ReportedEdit from './components/ReportedEdit'
import { isPeriodNeedsReportingForAdmin } from '../results/filters'
import Highlighted from '../../components/Highlighted'
import StatusIndicator from '../../components/StatusIndicator'
import ResultType from '../../components/ResultType'
import * as actions from '../results/actions'
import { kebabClassName } from '../../utils/misc'
import { ACTIVE_PERIOD } from '../../utils/constants'
import { Icon } from '../../components'
import AuditTrailModal from './components/AuditTrailModal'

const { Text } = Typography
const { Text, Title } = Typography

const TobeReported = ({
resultRdr,
Expand All @@ -54,6 +52,7 @@ const TobeReported = ({
const [activeKey, setActiveKey] = useState(null)
const [deletion, setDeletion] = useState([])
const [errors, setErrors] = useState([])
const [openHistory, setOpenHistory] = useState({ item: null, visible: false })
const formRef = useRef()

const mdParse = SimpleMarkdown.defaultBlockParse
Expand Down Expand Up @@ -150,61 +149,100 @@ const TobeReported = ({
formRef.current.form.setConfig('keepDirtyOnReinitialize', true)
}

const handleOnShowHistory = item => {
setOpenHistory({
item,
visible: !openHistory.visible
})
}

return (
<List
grid={{ column: 1 }}
itemLayout="vertical"
className="tobe-reported"
dataSource={updates}
renderItem={(item, ix) => {
const iKey = item?.id || `${item?.indicator?.id}0${ix}`
const allSubmissions = resultRdr
?.filter((r) => r.id === item.result?.id)
?.flatMap((r) => r.indicators)
?.filter((i) => i.id === item.indicator?.id)
?.flatMap((i) => i.periods)
?.filter((p) => (
p.id === item.period?.id &&
p.updates.length &&
!p.locked
))
?.flatMap((p) => p.updates)
const updateClass = (!item.status && allSubmissions.length) ? ACTIVE_PERIOD : kebabClassName(item?.statusDisplay)
return (
<List.Item className="tobe-reported-item">
<Card className={classNames(updateClass, { active: (activeKey === iKey) })}>
<Row type="flex" justify="space-between" align="middle">
<Col lg={22} md={22} sm={24} xs={24}>
{isEmpty(period) && (
<div className="period-caption">
{moment(item?.period?.periodStart, 'DD/MM/YYYY').format('DD MMM YYYY')} - {moment(item?.period?.periodEnd, 'DD/MM/YYYY').format('DD MMM YYYY')}
</div>
)}
<StatusIndicator status={item?.status} updateClass={updateClass} />
<ResultType {...item?.indicator?.result} />
<br />
<Text strong>Title : </Text>
<Highlighted text={item?.indicator?.title} highlight={keyword} />
<br />
{((!isEmpty(item?.indicator?.description.trim())) && item?.indicator?.description?.trim().length > 5) && (
<details>
<summary>{t('Description')}</summary>
<p className="desc hide-for-mobile">{mdOutput(mdParse(item?.indicator?.description))}</p>
</details>
)}
</Col>
<Col lg={2} md={2} sm={24} xs={24} className="action">
{
(activeKey === iKey)
? (
<div className="action-close">
<Button onClick={handleCancel}>
<Icon type="close" />
<span className="action-text">Close</span>
<>
<Modal
centered
closable
visible={openHistory.visible}
width={710}
onCancel={() => {
setOpenHistory({
...openHistory,
visible: false
})
}}
title={(
<div
style={{
display: 'flex',
gap: 8,
alignItems: 'center'
}}
>
<Icon type="clock.history" width="16px" />
<Title level={4} strong>Audit trail</Title>
</div>
)}
>
<AuditTrailModal {...openHistory.item} />
</Modal>
<List
grid={{ column: 1 }}
itemLayout="vertical"
className="tobe-reported"
dataSource={updates}
renderItem={(item, ix) => {
const iKey = item?.id || `${item?.indicator?.id}0${ix}`
const allSubmissions = resultRdr
?.filter((r) => r.id === item.result?.id)
?.flatMap((r) => r.indicators)
?.filter((i) => i.id === item.indicator?.id)
?.flatMap((i) => i.periods)
?.filter((p) => (
p.id === item.period?.id &&
p.updates.length &&
!p.locked
))
?.flatMap((p) => p.updates)
const updateClass = (!item.status && allSubmissions.length) ? ACTIVE_PERIOD : kebabCase(item?.statusDisplay)
return (
<List.Item className="tobe-reported-item">
<Card className={classNames(updateClass, { active: (activeKey === iKey) })}>
<Row type="flex" justify="space-between" align="top">
<Col lg={22} md={22} sm={24} xs={24}>
{isEmpty(period) && (
<div className="period-caption">
{moment(item?.period?.periodStart, 'DD/MM/YYYY').format('DD MMM YYYY')} - {moment(item?.period?.periodEnd, 'DD/MM/YYYY').format('DD MMM YYYY')}
</div>
)}
<StatusIndicator status={item?.status} updateClass={updateClass} />
<ResultType {...item?.indicator?.result} />
<br />
<Text strong>Title : </Text>
<Highlighted text={item?.indicator?.title} highlight={keyword} />
<br />
{((!isEmpty(item?.indicator?.description.trim())) && item?.indicator?.description?.trim().length > 5) && (
<details>
<summary>{t('Description')}</summary>
<span className="desc">{mdOutput(mdParse(item?.indicator?.description))}</span>
</details>
)}
</Col>
<Col lg={2} md={2} sm={24} xs={24} className="action">
{(activeKey === iKey) && (
<div className="action-close">
<Button onClick={handleCancel}>
<Icon type="close" />
<span className="action-text">Close</span>
</Button>
</div>
)}
{(activeKey !== iKey) && (
<>
{(allSubmissions.length > 0) && (
<Button type="link" onClick={() => handleOnShowHistory(item)}>
<Icon type="clock.history" />
<span className="action-text">Audit Trail</span>
</Button>
</div>
)
: (
)}
<Button
type="link"
onClick={() => {
Expand All @@ -214,43 +252,43 @@ const TobeReported = ({
handleOnEdit(item)
setActiveKey(iKey)
}}
block
>
<SVGInline svg={editButton} className="edit-button" />
<Icon type="edit.pencil" />
<span className="action-text">Edit Value</span>
</Button>
)
}
</Col>
</Row>
</Card>
{(editing && activeKey) && (
<Collapse activeKey={activeKey} bordered={false} accordion>
<Collapse.Panel key={iKey} showArrow={false}>
<ReportedEdit
{...{
activeKey,
formRef,
project,
editing,
editPeriod,
deleteFile,
deletion,
errors,
setErrors,
setActiveKey,
handleOnUpdate,
mneView: true,
deletePendingUpdate: deleteOnUpdate
}}
/>
</Collapse.Panel>
</Collapse>
)}
</List.Item>
)
}}
/>
</>
)}
</Col>
</Row>
</Card>
{(editing && activeKey) && (
<Collapse activeKey={activeKey} bordered={false} accordion>
<Collapse.Panel key={iKey} showArrow={false}>
<ReportedEdit
{...{
activeKey,
formRef,
project,
editing,
editPeriod,
deleteFile,
deletion,
errors,
setErrors,
setActiveKey,
handleOnUpdate,
mneView: true,
deletePendingUpdate: deleteOnUpdate
}}
/>
</Collapse.Panel>
</Collapse>
)}
</List.Item>
)
}}
/>
</>
)
}

Expand Down
15 changes: 14 additions & 1 deletion akvo/rsr/spa/app/modules/results-admin/TobeReported.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ $no-status-color: #a7a5a5;
$revision-color: #f5222d;
$active-color: #1890ff;
$approved-color: #52c41a;
$gray-500: #667085;

.tobe-reported {
.ant-collapse-borderless {
Expand Down Expand Up @@ -87,7 +88,12 @@ $approved-color: #52c41a;
display: none;
}
.mne-view .action {
text-align: center;
display: flex;
flex-direction: row;
justify-content: end;
.ant-btn.ant-btn-link {
color: $gray-500;
}
}
.tobe-reported .ant-collapse-borderless .ant-collapse-item .ant-collapse-content .ant-collapse-content-box .action-bar-xs {
display: none;
Expand All @@ -97,8 +103,15 @@ $approved-color: #52c41a;
padding-top: 16px;
}
.mne-view .action-text {
margin-left: 8px;
display: block;
}
.mne-view .action {
flex-direction: column;
.ant-btn.ant-btn.ant-btn-link {
width: 100%;
}
}
.tobe-reported .tobe-reported-item .action .ant-btn {
display: flex;
justify-content: center;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'

const AuditTrailModal = ({ id }) => {
return (
<>
Audit Trail here {id}
</>
)
}

export default AuditTrailModal
Loading

0 comments on commit a972475

Please sign in to comment.