Skip to content
Open
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
53 changes: 53 additions & 0 deletions src/activity/preview/ActivityPreview.css
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,59 @@
border: 1px solid #ebebeb;
}

.me_disagg_table {
table-layout: fixed;
}

.me_disagg_title {
text-align: left;
padding: 8px 10px;
}

.me_disagg_header {
text-align: left;
padding: 8px 10px;
vertical-align: top;
line-height: 1.35;
}

.me_disagg_cell {
padding: 8px 10px !important;
vertical-align: top;
line-height: 1.35;
word-break: break-word;
overflow-wrap: anywhere;
}

.me_disagg_category_col {
width: 13%;
}

.me_disagg_subcategory_col {
width: 13%;
}

.me_disagg_value_col {
width: 25%;
}

.me_disagg_actual_col {
width: 12%;
}

.me_disagg_date_col {
width: 12%;
white-space: nowrap;
}

.me_disagg_global_value {
min-height: 34px;
}

.me_disagg_global_value_revised {
margin-top: 4px;
}

.two_box_table {
border-top: 1px solid #ebebeb;
border-bottom: 1px solid #ebebeb;
Expand Down
91 changes: 69 additions & 22 deletions src/activity/preview/sections/APME.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class APME extends Component {
return (<div key={Math.random()}>
{buildSimpleField(`${ActivityConstants.INDICATORS}~${ActivityConstants.INDICATOR}`, true, null, false, indicator,
null, { noTitle: true, fieldValueClass: styles.sector_title })}
{buildSimpleField(`${ActivityConstants.INDICATORS}~${ActivityConstants.LOG_FRAME}`, true, null, false, indicator,
null, { fieldClass: styles.noborder })}
{buildSimpleField(`${ActivityConstants.INDICATORS}~${ActivityConstants.RISK}`, true, null, false, indicator,
null, { fieldClass: styles.noborder })}
{/*{buildSimpleField(`${ActivityConstants.INDICATORS}~${ActivityConstants.LOG_FRAME}`, true, null, false, indicator,*/}
{/* null, { fieldClass: styles.noborder })}*/}
{/*{buildSimpleField(`${ActivityConstants.INDICATORS}~${ActivityConstants.RISK}`, true, null, false, indicator,*/}
{/* null, { fieldClass: styles.noborder })}*/}
<div className={styles.box_field_name} style={{ marginTop: 8, marginBottom: 4 }}>
{this.props.translate('Value Tracking')}
</div>
Expand All @@ -46,13 +46,51 @@ class APME extends Component {
}

_generateValueOrValuesTable(sectionName, value) {
// For the 'actual' section we may have multiple entries — render as a single structured table.
if (sectionName === ActivityConstants.CURRENT && Array.isArray(value) && value.length > 0) {
return this._generateActualsTable(value);
}
return (<div>
{Array.isArray(value)
? value.map(v => this._generateValueTable(sectionName, v))
: this._generateValueTable(sectionName, value)}
</div>);
}

_generateActualsTable(values) {
const { translate } = this.props;
const hasComment = values.some(v => v[ActivityConstants.INDICATOR_COMMENT]);
return (
<table key={Math.random()} className={[styles.box_table, styles.section_group_class].join(' ')}
style={{ marginTop: 6, width: '100%' }}>
<thead>
<tr>
<th style={{ textAlign: 'left', padding: '4px 6px' }}>{translate('Actual Date')}</th>
<th style={{ textAlign: 'left', padding: '4px 6px' }}>{translate('Actual Value')}</th>
{hasComment && <th style={{ textAlign: 'left', padding: '4px 6px' }}>{translate('Comment')}</th>}
</tr>
</thead>
<tbody>
{values.map((v, idx) => (
<tr key={idx}>
<td style={{ padding: '3px 6px' }}>
{v[ActivityConstants.INDICATOR_DATE] || '\u2014'}
</td>
<td style={{ padding: '3px 6px' }}>
{v[ActivityConstants.INDICATOR_VALUE] != null ? v[ActivityConstants.INDICATOR_VALUE] : '\u2014'}
</td>
{hasComment && (
<td style={{ padding: '3px 6px' }}>
{v[ActivityConstants.INDICATOR_COMMENT] || '\u2014'}
</td>
)}
</tr>
))}
</tbody>
</table>
);
}

_generateValueTable(sectionName, value) {
if (!value) {
return null;
Expand Down Expand Up @@ -128,15 +166,24 @@ class APME extends Component {

_renderGlobalValue(gv) {
if (!gv) return null;
const { translate } = this.props;
// Display revised value if available, otherwise original (matching activity form behavior)
const value = gv[ActivityConstants.REVISED_VALUE] != null
? gv[ActivityConstants.REVISED_VALUE]
: (gv[ActivityConstants.ORIGINAL_VALUE] != null ? gv[ActivityConstants.ORIGINAL_VALUE] : '—');

const valueDate = gv[ActivityConstants.REVISED_VALUE] != null
? gv[ActivityConstants.REVISED_VALUE_DATE]
: gv[ActivityConstants.ORIGINAL_VALUE_DATE];

const display = [
value,
valueDate ? `(${valueDate})` : null,
].filter(Boolean).join(' ');

return (
<span>
{gv[ActivityConstants.ORIGINAL_VALUE] != null ? gv[ActivityConstants.ORIGINAL_VALUE] : '—'}
{gv[ActivityConstants.ORIGINAL_VALUE_DATE] ? ` (${gv[ActivityConstants.ORIGINAL_VALUE_DATE]})` : ''}
{gv[ActivityConstants.REVISED_VALUE] != null
? ` / ${translate('Revised')}: ${gv[ActivityConstants.REVISED_VALUE]}` : ''}
{gv[ActivityConstants.REVISED_VALUE_DATE] ? ` (${gv[ActivityConstants.REVISED_VALUE_DATE]})` : ''}
</span>
<div className={styles.me_disagg_global_value}>
<div>{display}</div>
</div>
);
}

Expand Down Expand Up @@ -180,37 +227,37 @@ class APME extends Component {
});

return (
<table key={Math.random()} className={[styles.box_table, styles.section_group_class].join(' ')}
<table key={Math.random()} className={[styles.box_table, styles.section_group_class, styles.me_disagg_table].join(' ')}
style={{ marginTop: 6, borderTop: '1px solid #ccc', width: '100%' }}>
<thead>
<tr>
<th colSpan={4} style={{ textAlign: 'left', padding: '4px 0' }}>
<th colSpan={4} className={styles.me_disagg_title}>
{translate('Disaggregation Values')}
</th>
</tr>
<tr>
<th>{translate('Category')}</th>
<th>{translate('Sub-Category')}</th>
<th>{translate('Actual Value')}</th>
<th>{translate('Actual Date')}</th>
<th className={[styles.me_disagg_header, styles.me_disagg_category_col].join(' ')}>{translate('Category')}</th>
<th className={[styles.me_disagg_header, styles.me_disagg_subcategory_col].join(' ')}>{translate('Sub-Category')}</th>
<th className={[styles.me_disagg_header, styles.me_disagg_actual_col].join(' ')}>{translate('Actual Value')}</th>
<th className={[styles.me_disagg_header, styles.me_disagg_date_col].join(' ')}>{translate('Actual Date')}</th>
</tr>
</thead>
<tbody>
{rows.map((row, idx) => (
<tr key={idx}>
{row.isFirstGroupRow && (
<td rowSpan={row.groupRowCount}>{row.groupKey}</td>
<td rowSpan={row.groupRowCount} className={[styles.me_disagg_cell, styles.me_disagg_category_col].join(' ')}>{row.groupKey}</td>
)}
{row.isFirstDvRow && (
<td rowSpan={row.dvRowCount}>
<td rowSpan={row.dvRowCount} className={[styles.me_disagg_cell, styles.me_disagg_subcategory_col].join(' ')}>
{row.dv[ActivityConstants.CHILD_CATEGORY_NAME] || '\u2014'}
</td>
)}
<td>
<td className={[styles.me_disagg_cell, styles.me_disagg_actual_col].join(' ')}>
{row.av && row.av[ActivityConstants.ORIGINAL_VALUE] != null
? row.av[ActivityConstants.ORIGINAL_VALUE] : '\u2014'}
</td>
<td>
<td className={[styles.me_disagg_cell, styles.me_disagg_date_col].join(' ')}>
{row.av && row.av[ActivityConstants.ORIGINAL_VALUE_DATE]
? row.av[ActivityConstants.ORIGINAL_VALUE_DATE] : '\u2014'}
</td>
Expand Down
47 changes: 16 additions & 31 deletions src/modules/field/FieldsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,40 +165,25 @@ export default class FieldsManager {
return pList.find(itemList => itemList.field_name === pPart);
}

let result;
let fieldsDef = this._fieldsDef;
if (fieldPath) {
let tmpDefinition;
let partToSearch;
let listDefinitions = fieldsDef;
const parts = fieldPath.split('~');
if (!fieldPath) {
return undefined;
}

for (let i = 0; i < parts.length; i++) {
partToSearch = parts[i];
tmpDefinition = _searchDefInList(listDefinitions, partToSearch);
if (tmpDefinition !== undefined) {
if (tmpDefinition.children !== undefined) {
if (parts[i + 1] !== undefined) {
partToSearch = parts[i + 1];
listDefinitions = tmpDefinition.children;
const parts = fieldPath.split('~');
let listDefinitions = this._fieldsDef;
let result;

tmpDefinition = _searchDefInList(listDefinitions, partToSearch);
if (tmpDefinition !== undefined) {
result = tmpDefinition;
i += 2;
}
} else {
result = tmpDefinition;
break;
}
} else { // It doesn't have children
result = tmpDefinition;
break;
}
}
for (let i = 0; i < parts.length; i++) {
const tmpDefinition = _searchDefInList(listDefinitions, parts[i]);
if (tmpDefinition === undefined) {
return undefined;
}
result = tmpDefinition;
if (tmpDefinition.children !== undefined && i + 1 < parts.length) {
listDefinitions = tmpDefinition.children;
} else {
break;
}
} else {
fieldsDef = { children: fieldsDef }; // Deprecated??
}
return result;
}
Expand Down