Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
30c6a72
Add funding columns to this old GGW codebase
brianbrix Apr 26, 2026
5d998ec
Add workflow to old codebase
brianbrix Apr 27, 2026
6dbd505
Add workflow to old codebase
brianbrix Apr 27, 2026
01722e9
Add workflow to old codebase
brianbrix Apr 27, 2026
d487737
Resolve failing deployment
brianbrix Apr 27, 2026
f6b5be9
Add funding columns to the old GGW codebase DonorFundingJob
brianbrix Apr 27, 2026
d27116f
Add Missing global settings
brianbrix Apr 28, 2026
efc1653
Add Missing global settings
brianbrix Apr 28, 2026
d3f6db2
Failing xml patches
brianbrix Apr 28, 2026
8ac723a
Failing xml patches
brianbrix Apr 28, 2026
6e8d5ec
Failing xml patches
brianbrix Apr 28, 2026
8489239
Failing xml patches
brianbrix Apr 28, 2026
4737503
Failing xml patches
brianbrix Apr 28, 2026
2d506e6
Revert donor job columns
brianbrix Apr 28, 2026
eaf47c3
Revert donor job columns
brianbrix Apr 29, 2026
7824ac6
Resolve map popup issue
brianbrix May 13, 2026
9517e7f
Merge remote-tracking branch 'origin/future/v4.0' into future/GGW
brianbrix May 13, 2026
ccda24b
Resolve map popup issue
brianbrix May 13, 2026
d4c708f
Report engine failing
brianbrix May 14, 2026
0ed93d1
Report engine failing
brianbrix May 14, 2026
fd2781c
Internal error when saving activity
brianbrix May 14, 2026
d7e3293
Internal error when saving activity
brianbrix May 15, 2026
20a1394
Internal error when saving activity
brianbrix May 15, 2026
04fbc87
Project list folded on load
brianbrix May 15, 2026
2011c00
AMP-31125: Issue viewing/editing some activities from tab
brianbrix May 18, 2026
aaf11ce
AMP-31125: Issue viewing/editing some activities from tab
brianbrix May 19, 2026
3c6957d
AMP-31125: Issue some activities missing from GIS
brianbrix May 19, 2026
045d5f0
AMP-31125: Issue some activities missing from GIS
brianbrix May 19, 2026
37c81be
Merge pull request #4475 from devgateway/fix/GGW/GGW-issues
jdeanquin-dg Jul 14, 2026
4ae5b6a
Merge branch 'develop' into future/v4.0
brianbrix Aug 11, 2026
8e840a6
Merge pull request #4510 from devgateway/future/v4.0-merge-conflicts-fix
jdeanquin-dg Aug 11, 2026
5a7b338
Fails to fetch translations
brianbrix Oct 27, 2026
6643c4c
Enable indicator report in feature manager
brianbrix Oct 28, 2026
7579d61
Saiku initialization fails when opening report
brianbrix Oct 28, 2026
2ee6075
Activity failing to load
brianbrix Oct 28, 2026
d95d981
Activity failing to load
brianbrix Oct 28, 2026
9dfec62
Merge branch 'show-indicator-reports' into future/v4.0
brianbrix Oct 29, 2026
bf35370
AMP-31126: Add third disaggregation dimension
brianbrix Oct 29, 2026
dd336de
AMP-31226: Add third disaggregation dimension
brianbrix Oct 29, 2026
045b0cf
Merge remote-tracking branch 'origin/feature/AMP-31226/New-Disaggrega…
brianbrix Oct 29, 2026
a11385f
Refactor image handling in EditActivity.java
brianbrix Oct 29, 2026
ef7c661
Change INSERT statement to use nextval for sequence
brianbrix Oct 29, 2026
584b466
AMP-31226: Add third disaggregation dimension
brianbrix Oct 29, 2026
aa0439f
Merge remote-tracking branch 'origin/feature/AMP-31226/New-Disaggrega…
brianbrix Oct 29, 2026
220ace9
AMP-31226: Resolve copilot comment on activityID
brianbrix Oct 29, 2026
47d1419
AMP-31226: Add UI for third dimension
brianbrix Oct 29, 2026
8688c4f
AMP-31226: Add UI for third dimension
brianbrix Oct 29, 2026
4c79c23
AMP-31226: Retain old UI for disaggregation
brianbrix Oct 29, 2026
ed678a1
AMP-31226: GFM not able to save
brianbrix Oct 30, 2026
1b36349
AMP-31226: Extend indicator reports to include disaggregation again
brianbrix Nov 3, 2026
71a1a90
AMP-31226: Extend indicator reports to include disaggregation again
brianbrix Nov 3, 2026
5babb05
AMP-31226: Add filter for indicator reports
brianbrix Nov 3, 2026
483ea62
AMP-31226: Filter widget failing due to date picker
brianbrix Nov 3, 2026
8653573
AMP-31226: Pin report filter widget and add regressions
brianbrix Nov 3, 2026
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
10 changes: 3 additions & 7 deletions amp/TEMPLATE/ampTemplate/js_2/esrigis/mainmapPopup.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,14 @@ function initMap() {
function loadBaseMap() {
map = L.map('map').setView([latitude, longitude], 7);
// create the tile layer with correct attribution
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
if (isOsm) {
var subdomains = ['a', 'b', 'c'];
if (basemapurl !== undefined && basemapurl.indexOf("mqcdn") != -1) {
subdomains = ['otile1', 'otile2', 'otile3', 'otile4'];
}
var osmAttrib = 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
var osmAttrib = 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
tileLayer = new L.TileLayer(osmUrl, {
minZoom: 0,
maxZoom: 16,
attribution: osmAttrib,
subdomains: subdomains
subdomains: ['a', 'b', 'c']
});
} else {
tileLayer = L.esri.tiledMapLayer({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,13 @@ Backbone.sync = function(method, model, options) {
url = model.url();
}

var isQueryFixture = url === "/TEMPLATE/ampTemplate/saikuui_reports/mockData/query.json";

// AMP-22600: Remove timestamp argument.
if (url.indexOf('.json') !== -1) {
Saiku.logger.log('Using cache=true for ' + url);
cache = true;
type = 'POST';
type = isQueryFixture ? 'GET' : 'POST';
}

// Prepare for failure
Expand Down Expand Up @@ -147,6 +149,9 @@ Backbone.sync = function(method, model, options) {
if (typeof options.data != "undefined") {
data = options.data;
}
if (isQueryFixture) {
data = undefined;
}

// Default JSON-request options.
params = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ var reportType = Saiku.originalReportMetadata.reportMetadata.reportSpec.reportTy
var reportTypeCode = 'D';
if (reportType === 5) {
reportTypeCode = 'P';
} else if (reportType === 7) {
reportTypeCode = 'I';
}
window.currentFilter = new ampFilter({
el: $('#filter-popup'),
Expand Down
34 changes: 25 additions & 9 deletions amp/TEMPLATE/ampTemplate/tabs/js/business/grid/gridManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ define([ 'business/grid/columnsMapping', 'translationManager', 'util/tabUtils','
return '/aim/viewActivityPreview.do~activityId=' + id;
}

function getRowActivityId(grid, rowId) {
var activityId = jQuery(grid).jqGrid('getCell', rowId, app.TabsApp.COLUMN_ACTIVITY_ID);
activityId = activityId ? String(activityId).replace(/(?:[\s\u00A0]|&nbsp;)/gi, '') : '';
return /^[1-9]\d*$/.test(activityId) ? activityId : '';
}

GridManager.prototype = {
constructor : GridManager
};
Expand Down Expand Up @@ -230,12 +236,15 @@ define([ 'business/grid/columnsMapping', 'translationManager', 'util/tabUtils','
//set default color and link for rows
row = this.rows[iRow];
className = row.className;
var id = row.cells[1].textContent;
var iconedit = "<a href='/wicket/onepager/"+ onePagerParameter +"/" + id
+ "'><img src='/TEMPLATE/ampTemplate/tabs/css/images/ico_edit.gif'/></a>";
var iconvalidated = "<a href='/wicket/onepager/"+ onePagerParameter +"/" + id
+ "'><img src='/TEMPLATE/ampTemplate/tabs/css/images/validate.png'/></a>";
var link = "<a href='/wicket/onepager/"+ onePagerParameter +"/" + id + "'>";
var id = getRowActivityId(grid, row.id);
if (!id) {
console.warn('Cannot create activity links for a report row without a valid activity ID', row.id);
}
var iconedit = id ? "<a href='/wicket/onepager/"+ onePagerParameter +"/" + id
+ "'><img src='/TEMPLATE/ampTemplate/tabs/css/images/ico_edit.gif'/></a>" : '';
var iconvalidated = id ? "<a href='/wicket/onepager/"+ onePagerParameter +"/" + id
+ "'><img src='/TEMPLATE/ampTemplate/tabs/css/images/validate.png'/></a>" : '';
var link = id ? "<a href='/wicket/onepager/"+ onePagerParameter +"/" + id + "'>" : '';


row.className = className + ' status_1';
Expand Down Expand Up @@ -358,9 +367,11 @@ define([ 'business/grid/columnsMapping', 'translationManager', 'util/tabUtils','
colIndex = i;
}
});
var newContent = "<a class='preview-cell" + statusClass + "' href='" + getPreviewPageURL(id) + "'>"
+ jQuery(row.cells[colIndex]).html() + "</a>";
jQuery(row.cells[colIndex]).html(newContent);
if (id) {
var newContent = "<a class='preview-cell" + statusClass + "' href='" + getPreviewPageURL(id) + "'>"
+ jQuery(row.cells[colIndex]).html() + "</a>";
jQuery(row.cells[colIndex]).html(newContent);
}
}

TranslationManager.searchAndTranslate();
Expand Down Expand Up @@ -545,6 +556,11 @@ define([ 'business/grid/columnsMapping', 'translationManager', 'util/tabUtils','
row[column.columnName] = element.entityId;
}
});

// A leaf owner identifies the activity, unlike individual cell entity IDs.
if (obj.owner && obj.owner.columnName === '##LEAF##' && obj.owner.id > 0) {
row[app.TabsApp.COLUMN_ACTIVITY_ID] = obj.owner.id;
}

// To flatten the tree structure and maintain hierarchies values on every row we add the values from "auxCurrentHierarchiesValues".
if (hierarchies.models.length > 0) {
Expand Down
5 changes: 3 additions & 2 deletions amp/TEMPLATE/reampv2/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion amp/TEMPLATE/reampv2/packages/reampv2-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"proxy": "http://localhost:8080",
"dependencies": {
"@devgateway/amp-boilerplate": "github:devgateway/amp-boilerplate",
"@devgateway/amp-filter": "github:devgateway/amp-filter",
"@devgateway/amp-filter": "github:devgateway/amp-filter#530cae5cf290fcca2a7476aef7ae136326f23260",
"@devgateway/amp-settings": "github:devgateway/amp-settings",
"@fortawesome/fontawesome-svg-core": "^1.2.30",
"@fortawesome/free-solid-svg-icons": "^5.14.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import styles from './css/IndicatorModal.module.css';
import { DateUtil } from '../../utils/dateFn';
import { translatedIndicatorValidationSchema } from '../../utils/validator';
import { useDispatch, useSelector } from 'react-redux';
import { BaseAndTargetValueType, DefaultComponentProps, ProgramSchemeType, SettingsType } from '../../types';
import { BaseAndTargetValueType, DefaultComponentProps, DisaggregationFormValue, ProgramSchemeType, SettingsType } from '../../types';
import { createIndicator } from '../../reducers/createIndicatorReducer';
import { getIndicators } from '../../reducers/fetchIndicatorsReducer';
import { getOutcomes } from '../../reducers/fetchOutcomesReducer';
Expand All @@ -20,6 +20,8 @@ import { getResponsibleOrgs } from '../../reducers/fetchResponsibleOrgsReducer';
import axios from 'axios';
import Accordion from 'react-bootstrap/Accordion';
import initialTranslations from '../../config/initialTranslations.json';
import { buildThreeDisaggregationValues, hasEnteredDisaggregationValue } from '../../utils/disaggregation';
import DisaggregationCombinationValues from './DisaggregationCombinationValues';


const MySwal = withReactContent(Swal);
Expand Down Expand Up @@ -54,23 +56,7 @@ interface IndicatorFormValues {
outputId?: number;
outcomeId?: number;
indicatorsCategory?: number;
// Add editable disaggregation values
disaggregationValues?: Array<{
parentCategoryId: number;
childCategoryId: number | null;
base: {
originalValue: string | number;
originalValueDate: string;
revisedValue: string | number;
revisedValueDate: string;
};
target: {
originalValue: string | number;
originalValueDate: string;
revisedValue: string | number;
revisedValueDate: string;
};
}>;
disaggregationValues?: DisaggregationFormValue[];
}

const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
Expand Down Expand Up @@ -326,6 +312,8 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
const frequencyOptions = getCategoryOptions('indicator_frequency');

const [disaggregationChildren, setDisaggregationChildren] = useState<{[key: number]: any[]}>({});
const [disaggregationLoading, setDisaggregationLoading] = useState(false);
const [disaggregationError, setDisaggregationError] = useState(false);
const [singleDisaggregationActiveKey, setSingleDisaggregationActiveKey] = useState<string | null>('0');
const [doubleDisaggregationActiveKey, setDoubleDisaggregationActiveKey] = useState<string | null>('0');

Expand All @@ -350,6 +338,10 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
initialValues={initialValues}
validationSchema={translatedIndicatorValidationSchema(translations)}
onSubmit={(values) => {
if (disaggregationLoading || disaggregationError) {
MySwal.fire({ icon: 'error', text: t("amp.indicatormanager:disaggregation-options-error") });
return;
}
const { name, description, code, sectors, programId, ascending, creationDate, base, target, indicatorsCategory } = values;
if (selectedProgramSchemeId && !programId) {
MySwal.fire({
Expand Down Expand Up @@ -422,18 +414,30 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
// Move disaggregation children-fetching logic here
useEffect(() => {
const selected = props.values.disaggregation;
if (selected && (selected.length === 1 || selected.length === 2)) {
let active = true;
setDisaggregationError(false);
if (selected && selected.length > 0) {
setDisaggregationLoading(true);
setDisaggregationChildren({});
Promise.all(selected.map(id => axios.get(`/rest/indicator_disaggregation/options/${id}`)))
.then((responses) => {
if (!active) return;
const childrenMap = {};
selected.forEach((id, idx) => {
childrenMap[id] = responses[idx].data;
});
setDisaggregationChildren(childrenMap);
setDisaggregationLoading(false);
}).catch(() => {
if (!active) return;
setDisaggregationLoading(false);
setDisaggregationError(true);
});
} else {
setDisaggregationChildren({});
setDisaggregationLoading(false);
}
return () => { active = false; };
}, [props.values.disaggregation]);

// Ensure all required disaggregation entries exist in Formik state before rendering Accordion
Expand Down Expand Up @@ -471,8 +475,12 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
});
// Remove any entries with childCategoryId: null
updated = updated.filter((v: any) => v.childCategoryId !== null);
} else if (props.values.disaggregation.length === 3) {
updated = buildThreeDisaggregationValues(
props.values.disaggregation, disaggregationChildren, updated);
}
if (updated.length !== props.values.disaggregationValues.length) {
if (updated.length !== props.values.disaggregationValues.length
|| updated.some((value, index) => value !== props.values.disaggregationValues?.[index])) {
props.setFieldValue('disaggregationValues', updated);
}
}, [props.values.disaggregation, disaggregationChildren]);
Expand Down Expand Up @@ -759,8 +767,18 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
name="disaggregation"
options={disaggregationOptions}
onChange={(selectedValues) => {
// Limit selection to max 2
const limitedValues = selectedValues.slice(0, 2);
const limitedValues = selectedValues.slice(0, 3);
if (props.values.disaggregation.length === 3
&& props.values.disaggregation.some(id => !limitedValues.some(value => value.value === id))
&& (props.values.disaggregationValues || []).some(value =>
value.thirdCategoryId != null && hasEnteredDisaggregationValue(value))) {
MySwal.fire({ icon: 'error', text: t("amp.indicatormanager:unsaved-third-values-error") });
return;
}
if (limitedValues.length < 3) {
props.setFieldValue('disaggregationValues',
(props.values.disaggregationValues || []).filter(value => value.thirdCategoryId == null));
}
props.setFieldValue('disaggregation', limitedValues.map((v: any) => v.value));
}}
onBlur={props.handleBlur}
Expand All @@ -771,6 +789,11 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
/>
</Form.Group>
</Row>
{disaggregationError && <p role="alert">{t("amp.indicatormanager:disaggregation-options-error")}</p>}
{props.values.disaggregation?.length === 3 && (
<DisaggregationCombinationValues values={props.values.disaggregationValues || []}
options={disaggregationChildren} translations={translations} onChange={updateDisaggregationField} />
)}
{/* Accordion for disaggregation values, always in a new row below the select */}
{props.values.disaggregation?.length === 1 && (
<Row className={styles.view_row}>
Expand Down Expand Up @@ -1369,7 +1392,7 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
<Button variant="secondary" onClick={handleClose}>
{t("amp.indicatormanager:close")}
</Button>
<Button type="submit" variant="success" >
<Button type="submit" variant="success" disabled={disaggregationLoading || disaggregationError} >
{t("amp.indicatormanager:save")}
</Button>
</Modal.Footer>
Expand All @@ -1381,4 +1404,3 @@ const AddNewIndicatorModal: React.FC<AddNewIndicatorModalProps> = (props) => {
};

export default AddNewIndicatorModal;

Loading
Loading