@iapps/ng-dhis2-ui 1.1.68 → 1.1.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/iapps-ng-dhis2-ui.mjs +304 -233
- package/fesm2022/iapps-ng-dhis2-ui.mjs.map +1 -1
- package/lib/modules/form/utils/field-type.util.d.ts +1 -1
- package/lib/modules/form/utils/field.util.d.ts +1 -1
- package/lib/modules/line-list/components/data-table-actions/data-table-actions.d.ts +8 -0
- package/lib/modules/line-list/components/data-table-actions/index.d.ts +1 -0
- package/lib/modules/line-list/components/dropdown-menu/dropdown-menu.d.ts +4 -2
- package/lib/modules/line-list/containers/line-list.component.d.ts +3 -1
- package/lib/modules/line-list/index.d.ts +1 -0
- package/lib/modules/line-list/models/action-option-orientation.model.d.ts +1 -0
- package/lib/modules/line-list/models/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { NgxDhis2HttpClientService } from '@iapps/ngx-dhis2-http-client';
|
|
|
8
8
|
import * as React from 'react';
|
|
9
9
|
import React__default, { useState, useCallback, useRef, useEffect, createContext, useContext, useMemo } from 'react';
|
|
10
10
|
import * as ReactDOM from 'react-dom/client';
|
|
11
|
-
import { catchError, of, map, zip, firstValueFrom, filter, Subject, takeUntil } from 'rxjs';
|
|
11
|
+
import { catchError, of, map, zip, firstValueFrom, take, filter, Subject, takeUntil } from 'rxjs';
|
|
12
12
|
import i18n from '@dhis2/d2-i18n';
|
|
13
13
|
import { colors, theme, spacers } from '@dhis2/ui-constants';
|
|
14
14
|
import PropTypes from 'prop-types';
|
|
@@ -3195,13 +3195,237 @@ const DropdownMenu$1 = (props) => {
|
|
|
3195
3195
|
const ref = useRef();
|
|
3196
3196
|
const [visible, setVisible] = useState(false);
|
|
3197
3197
|
const { dropdownOptions, onClick } = props;
|
|
3198
|
-
return (React__default.createElement("div", { ref: ref, style: { display:
|
|
3198
|
+
return (React__default.createElement("div", { ref: ref, style: { display: 'inline-block' } },
|
|
3199
3199
|
React__default.createElement(Button$1, { small: true, secondary: true, icon: React__default.createElement(IconMore24, { color: colors$1.grey600 }), onClick: () => setVisible(true) }),
|
|
3200
3200
|
visible && (React__default.createElement(ContextMenu$1, { dropDownOptions: dropdownOptions, anchorRef: ref, onClose: () => setVisible(false), onMenuClick: (dropDownOption) => {
|
|
3201
3201
|
onClick(dropDownOption);
|
|
3202
3202
|
} }))));
|
|
3203
3203
|
};
|
|
3204
3204
|
|
|
3205
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
3206
|
+
// Use of this source code is governed by a BSD-style
|
|
3207
|
+
// license that can be found in the LICENSE file.
|
|
3208
|
+
const DataTableActions = (props) => {
|
|
3209
|
+
const { actionOptions, actionOptionOrientation, onClick } = props;
|
|
3210
|
+
switch (actionOptionOrientation) {
|
|
3211
|
+
case 'BUTTON':
|
|
3212
|
+
return (React__default.createElement(ButtonStrip$1, null, actionOptions.map((option) => (React__default.createElement(Button$1, { key: option.label, onClick: () => onClick(option), icon: option.icon ? React__default.createElement(option.icon, null) : React__default.createElement(React__default.Fragment, null), small: true, destructive: option.destructive }, !option.iconOnly ? option.label : '')))));
|
|
3213
|
+
case 'DROPDOWN':
|
|
3214
|
+
return (React__default.createElement(DropdownMenu$1, { dropdownOptions: actionOptions, onClick: (option) => {
|
|
3215
|
+
onClick(option);
|
|
3216
|
+
} }));
|
|
3217
|
+
case 'LINK':
|
|
3218
|
+
return (React__default.createElement("div", { style: {
|
|
3219
|
+
display: 'flex',
|
|
3220
|
+
gap: 16,
|
|
3221
|
+
alignItems: 'center',
|
|
3222
|
+
} }, actionOptions.map((option) => (React__default.createElement("a", { style: {
|
|
3223
|
+
cursor: 'pointer',
|
|
3224
|
+
textDecoration: 'underline',
|
|
3225
|
+
fontSize: 14,
|
|
3226
|
+
display: 'flex',
|
|
3227
|
+
alignItems: 'center',
|
|
3228
|
+
gap: 4,
|
|
3229
|
+
color: option.destructive ? colors$1.red700 : colors$1.grey900,
|
|
3230
|
+
}, key: option.label, onClick: (event) => {
|
|
3231
|
+
event.stopPropagation();
|
|
3232
|
+
onClick(option);
|
|
3233
|
+
} },
|
|
3234
|
+
option.icon ? React__default.createElement(option.icon, null) : React__default.createElement(React__default.Fragment, null),
|
|
3235
|
+
!option.iconOnly ? React__default.createElement("span", null, option.label) : React__default.createElement(React__default.Fragment, null))))));
|
|
3236
|
+
default:
|
|
3237
|
+
return React__default.createElement(React__default.Fragment, null);
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
|
|
3241
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
3242
|
+
// Use of this source code is governed by a BSD-style
|
|
3243
|
+
// license that can be found in the LICENSE file.
|
|
3244
|
+
|
|
3245
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
3246
|
+
// Use of this source code is governed by a BSD-style
|
|
3247
|
+
// license that can be found in the LICENSE file.
|
|
3248
|
+
// @flow
|
|
3249
|
+
const orgUnitFieldStyles$1 = {
|
|
3250
|
+
container: {
|
|
3251
|
+
border: '1px solid',
|
|
3252
|
+
borderColor: colors$1.grey400,
|
|
3253
|
+
borderRadius: '3px',
|
|
3254
|
+
height: '100%',
|
|
3255
|
+
width: '100%',
|
|
3256
|
+
zIndex: 0,
|
|
3257
|
+
backgroundColor: 'white',
|
|
3258
|
+
},
|
|
3259
|
+
searchField: {
|
|
3260
|
+
height: '40px',
|
|
3261
|
+
overflow: 'hidden',
|
|
3262
|
+
borderBottomLeftRadius: 0,
|
|
3263
|
+
borderBottomRightRadius: 0,
|
|
3264
|
+
boxShadow: 'none',
|
|
3265
|
+
border: 'none',
|
|
3266
|
+
},
|
|
3267
|
+
debounceFieldContainer: {
|
|
3268
|
+
padding: '8px',
|
|
3269
|
+
background: colors$1.grey100,
|
|
3270
|
+
borderTopLeftRadius: '3px',
|
|
3271
|
+
borderTopRightRadius: '3px',
|
|
3272
|
+
},
|
|
3273
|
+
orgUnitTreeContainer: {
|
|
3274
|
+
borderBottomLeftRadius: '3px',
|
|
3275
|
+
borderBottomRightRadius: '3px',
|
|
3276
|
+
overflow: 'auto',
|
|
3277
|
+
},
|
|
3278
|
+
orgUnitTreeLoader: {
|
|
3279
|
+
padding: '8px',
|
|
3280
|
+
},
|
|
3281
|
+
orgUnitFieldLabel: {
|
|
3282
|
+
marginBottom: '8px',
|
|
3283
|
+
display: 'block',
|
|
3284
|
+
boxSizing: 'border-box',
|
|
3285
|
+
fontSize: '14px',
|
|
3286
|
+
lineHeight: '19px',
|
|
3287
|
+
color: 'rgb(33, 41, 52)',
|
|
3288
|
+
padding: '0',
|
|
3289
|
+
},
|
|
3290
|
+
orgUnitFieldRequiredLabel: {
|
|
3291
|
+
paddingInlineStart: '4px',
|
|
3292
|
+
},
|
|
3293
|
+
};
|
|
3294
|
+
const OrgUnitFormField$1 = (props) => {
|
|
3295
|
+
const { onSelectOrgUnit, label, required, selected, disabled, key } = props;
|
|
3296
|
+
const d2 = window?.d2Web;
|
|
3297
|
+
const classes = useDynamicStyles$2(orgUnitFieldStyles$1);
|
|
3298
|
+
const config = useMemo(() => {
|
|
3299
|
+
return d2.systemInfo?.toInitObject();
|
|
3300
|
+
}, []);
|
|
3301
|
+
const rootOrgUnits = useMemo(() => {
|
|
3302
|
+
return d2.currentUser?.organisationUnits || [];
|
|
3303
|
+
}, []);
|
|
3304
|
+
const getExpandedItems = () => {
|
|
3305
|
+
if (rootOrgUnits && rootOrgUnits.length === 1) {
|
|
3306
|
+
return [`/${rootOrgUnits[0].id}`];
|
|
3307
|
+
}
|
|
3308
|
+
else if (rootOrgUnits?.length > 1) {
|
|
3309
|
+
return rootOrgUnits.map((root) => root.path);
|
|
3310
|
+
}
|
|
3311
|
+
return undefined;
|
|
3312
|
+
};
|
|
3313
|
+
const initiallyExpanded = getExpandedItems();
|
|
3314
|
+
const [searchText, setSearchText] = useState(undefined);
|
|
3315
|
+
const [loading, setLoading] = useState(true);
|
|
3316
|
+
const [searchLoading, setSearchLoading] = useState();
|
|
3317
|
+
const [searchData, setSearchData] = useState();
|
|
3318
|
+
const [selectedOrgUnit, setSelectedOrgUnit] = useState();
|
|
3319
|
+
const [expanded, setExpanded] = useState(initiallyExpanded);
|
|
3320
|
+
const [showOrgUnitTree, setShowOrgUnitTree] = useState(!selected);
|
|
3321
|
+
useEffect(() => {
|
|
3322
|
+
setLoading(true);
|
|
3323
|
+
if (selected) {
|
|
3324
|
+
d2.httpInstance
|
|
3325
|
+
.get(`organisationUnits/${selected}.json?fields=id,displayName,path,code,ancestors[id,displayName]`)
|
|
3326
|
+
.then((response) => {
|
|
3327
|
+
if (response.data) {
|
|
3328
|
+
setSelectedOrgUnit(response.data);
|
|
3329
|
+
handleExpand({ path: response.data['path'] });
|
|
3330
|
+
setLoading(false);
|
|
3331
|
+
}
|
|
3332
|
+
});
|
|
3333
|
+
}
|
|
3334
|
+
else {
|
|
3335
|
+
setShowOrgUnitTree(true);
|
|
3336
|
+
setLoading(false);
|
|
3337
|
+
}
|
|
3338
|
+
}, []);
|
|
3339
|
+
const highlighted = useMemo(() => {
|
|
3340
|
+
if (selectedOrgUnit) {
|
|
3341
|
+
return [selectedOrgUnit['path']];
|
|
3342
|
+
}
|
|
3343
|
+
return undefined;
|
|
3344
|
+
}, [selectedOrgUnit]);
|
|
3345
|
+
const selectedOrgUnitLabel = useMemo(() => {
|
|
3346
|
+
if (selectedOrgUnit) {
|
|
3347
|
+
return [
|
|
3348
|
+
...(selectedOrgUnit['ancestors'] || []),
|
|
3349
|
+
selectedOrgUnit,
|
|
3350
|
+
]
|
|
3351
|
+
.map((orgUnit) => orgUnit['displayName'])
|
|
3352
|
+
.join(' / ');
|
|
3353
|
+
}
|
|
3354
|
+
return '';
|
|
3355
|
+
}, [selectedOrgUnit]);
|
|
3356
|
+
const handleExpand = ({ path }) => {
|
|
3357
|
+
if (expanded && !expanded.includes(path)) {
|
|
3358
|
+
setExpanded([...expanded, path]);
|
|
3359
|
+
}
|
|
3360
|
+
};
|
|
3361
|
+
const handleCollapse = ({ path }) => {
|
|
3362
|
+
const pathIndex = expanded?.indexOf(path);
|
|
3363
|
+
if (pathIndex && pathIndex !== -1 && expanded) {
|
|
3364
|
+
const updatedExpanded = pathIndex === 0
|
|
3365
|
+
? expanded.slice(1)
|
|
3366
|
+
: [...expanded.slice(0, pathIndex), ...expanded.slice(pathIndex + 1)];
|
|
3367
|
+
setExpanded(updatedExpanded);
|
|
3368
|
+
}
|
|
3369
|
+
};
|
|
3370
|
+
const handleOrgUnitSearch = async (query) => {
|
|
3371
|
+
setSearchLoading(true);
|
|
3372
|
+
try {
|
|
3373
|
+
const searchResponse = await d2.httpInstance.get(`organisationUnits.json?fields=id,displayName,path,publicAccess,access,lastUpdated,children[id,displayName,publicAccess,access,path,children::isNotEmpty]&paging=true&query=${query}&withinUserSearchHierarchy=true&pageSize=15`);
|
|
3374
|
+
setSearchData((searchResponse.data || {})['organisationUnits']);
|
|
3375
|
+
setSearchLoading(false);
|
|
3376
|
+
}
|
|
3377
|
+
catch (e) {
|
|
3378
|
+
setSearchLoading(false);
|
|
3379
|
+
}
|
|
3380
|
+
};
|
|
3381
|
+
const debouncedSearch = useCallback(debounce((value) => {
|
|
3382
|
+
handleOrgUnitSearch(value);
|
|
3383
|
+
}, 500), []);
|
|
3384
|
+
const handleFilterChange = (event) => {
|
|
3385
|
+
setSearchText(event.value);
|
|
3386
|
+
debouncedSearch(event.value);
|
|
3387
|
+
};
|
|
3388
|
+
const ready = useMemo(() => {
|
|
3389
|
+
return searchText?.length ? !searchLoading : !loading;
|
|
3390
|
+
}, [searchText, searchLoading, loading]);
|
|
3391
|
+
const renderOrgUnitTree = () => {
|
|
3392
|
+
if (searchText && searchText?.length > 0) {
|
|
3393
|
+
if (searchLoading) {
|
|
3394
|
+
return (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
|
|
3395
|
+
React__default.createElement(CircularLoader$1, { small: true })));
|
|
3396
|
+
}
|
|
3397
|
+
return (ready && (React__default.createElement(OrganisationUnitTree, { key: `${key}-search`, roots: searchData?.map((orgUnit) => orgUnit.id) || [], singleSelection: true, expanded: expanded, handleExpand: handleExpand, handleCollapse: handleCollapse, selected: highlighted, onChange: (event) => {
|
|
3398
|
+
setSelectedOrgUnit(event);
|
|
3399
|
+
setShowOrgUnitTree(false);
|
|
3400
|
+
onSelectOrgUnit(event);
|
|
3401
|
+
} })));
|
|
3402
|
+
}
|
|
3403
|
+
return (React__default.createElement(OrganisationUnitTree, { key: key, roots: rootOrgUnits?.map((orgUnit) => orgUnit.id) || [], singleSelection: true, expanded: expanded, handleExpand: handleExpand, handleCollapse: handleCollapse, selected: highlighted, onChange: (event) => {
|
|
3404
|
+
setSelectedOrgUnit(event);
|
|
3405
|
+
setShowOrgUnitTree(false);
|
|
3406
|
+
onSelectOrgUnit(event);
|
|
3407
|
+
} }));
|
|
3408
|
+
};
|
|
3409
|
+
const handleBlur = () => {
|
|
3410
|
+
// onBlur && onBlur(null);
|
|
3411
|
+
};
|
|
3412
|
+
return (config && (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false },
|
|
3413
|
+
React__default.createElement("div", null,
|
|
3414
|
+
label && (React__default.createElement("div", { className: classes.orgUnitFieldLabel },
|
|
3415
|
+
React__default.createElement("span", null, label),
|
|
3416
|
+
required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
|
|
3417
|
+
!showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
|
|
3418
|
+
React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
|
|
3419
|
+
React__default.createElement(Chip, { onRemove: () => {
|
|
3420
|
+
setShowOrgUnitTree(true);
|
|
3421
|
+
} }, selectedOrgUnit.displayName)))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
|
|
3422
|
+
React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
|
|
3423
|
+
React__default.createElement("div", { className: classes.debounceFieldContainer },
|
|
3424
|
+
React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
|
|
3425
|
+
loading ? (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
|
|
3426
|
+
React__default.createElement(CircularLoader$1, { small: true }))) : (React__default.createElement("div", { className: classes.orgUnitTreeContainer, style: { maxHeight: '200px', overflowY: 'auto' } }, renderOrgUnitTree()))))))));
|
|
3427
|
+
};
|
|
3428
|
+
|
|
3205
3429
|
// export function buildFilters(filters: AttributeFilter[]): string {
|
|
3206
3430
|
// return filters
|
|
3207
3431
|
// .map(({ attribute, operator, value }) => `filter=${attribute}:${operator}:${value}`)
|
|
@@ -3849,194 +4073,11 @@ const addActionsColumn = (columns, actionOptions) => {
|
|
|
3849
4073
|
];
|
|
3850
4074
|
};
|
|
3851
4075
|
|
|
3852
|
-
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
3853
|
-
// Use of this source code is governed by a BSD-style
|
|
3854
|
-
// license that can be found in the LICENSE file.
|
|
3855
|
-
// @flow
|
|
3856
|
-
const orgUnitFieldStyles$1 = {
|
|
3857
|
-
container: {
|
|
3858
|
-
border: '1px solid',
|
|
3859
|
-
borderColor: colors$1.grey400,
|
|
3860
|
-
borderRadius: '3px',
|
|
3861
|
-
height: '100%',
|
|
3862
|
-
width: '100%',
|
|
3863
|
-
zIndex: 0,
|
|
3864
|
-
backgroundColor: 'white',
|
|
3865
|
-
},
|
|
3866
|
-
searchField: {
|
|
3867
|
-
height: '40px',
|
|
3868
|
-
overflow: 'hidden',
|
|
3869
|
-
borderBottomLeftRadius: 0,
|
|
3870
|
-
borderBottomRightRadius: 0,
|
|
3871
|
-
boxShadow: 'none',
|
|
3872
|
-
border: 'none',
|
|
3873
|
-
},
|
|
3874
|
-
debounceFieldContainer: {
|
|
3875
|
-
padding: '8px',
|
|
3876
|
-
background: colors$1.grey100,
|
|
3877
|
-
borderTopLeftRadius: '3px',
|
|
3878
|
-
borderTopRightRadius: '3px',
|
|
3879
|
-
},
|
|
3880
|
-
orgUnitTreeContainer: {
|
|
3881
|
-
borderBottomLeftRadius: '3px',
|
|
3882
|
-
borderBottomRightRadius: '3px',
|
|
3883
|
-
overflow: 'auto',
|
|
3884
|
-
},
|
|
3885
|
-
orgUnitTreeLoader: {
|
|
3886
|
-
padding: '8px',
|
|
3887
|
-
},
|
|
3888
|
-
orgUnitFieldLabel: {
|
|
3889
|
-
marginBottom: '8px',
|
|
3890
|
-
display: 'block',
|
|
3891
|
-
boxSizing: 'border-box',
|
|
3892
|
-
fontSize: '14px',
|
|
3893
|
-
lineHeight: '19px',
|
|
3894
|
-
color: 'rgb(33, 41, 52)',
|
|
3895
|
-
padding: '0',
|
|
3896
|
-
},
|
|
3897
|
-
orgUnitFieldRequiredLabel: {
|
|
3898
|
-
paddingInlineStart: '4px',
|
|
3899
|
-
},
|
|
3900
|
-
};
|
|
3901
|
-
const OrgUnitFormField$1 = (props) => {
|
|
3902
|
-
const { onSelectOrgUnit, label, required, selected, disabled, key } = props;
|
|
3903
|
-
const d2 = window?.d2Web;
|
|
3904
|
-
const classes = useDynamicStyles$2(orgUnitFieldStyles$1);
|
|
3905
|
-
const config = useMemo(() => {
|
|
3906
|
-
return d2.systemInfo?.toInitObject();
|
|
3907
|
-
}, []);
|
|
3908
|
-
const rootOrgUnits = useMemo(() => {
|
|
3909
|
-
return d2.currentUser?.organisationUnits || [];
|
|
3910
|
-
}, []);
|
|
3911
|
-
const getExpandedItems = () => {
|
|
3912
|
-
if (rootOrgUnits && rootOrgUnits.length === 1) {
|
|
3913
|
-
return [`/${rootOrgUnits[0].id}`];
|
|
3914
|
-
}
|
|
3915
|
-
else if (rootOrgUnits?.length > 1) {
|
|
3916
|
-
return rootOrgUnits.map((root) => root.path);
|
|
3917
|
-
}
|
|
3918
|
-
return undefined;
|
|
3919
|
-
};
|
|
3920
|
-
const initiallyExpanded = getExpandedItems();
|
|
3921
|
-
const [searchText, setSearchText] = useState(undefined);
|
|
3922
|
-
const [loading, setLoading] = useState(true);
|
|
3923
|
-
const [searchLoading, setSearchLoading] = useState();
|
|
3924
|
-
const [searchData, setSearchData] = useState();
|
|
3925
|
-
const [selectedOrgUnit, setSelectedOrgUnit] = useState();
|
|
3926
|
-
const [expanded, setExpanded] = useState(initiallyExpanded);
|
|
3927
|
-
const [showOrgUnitTree, setShowOrgUnitTree] = useState(!selected);
|
|
3928
|
-
useEffect(() => {
|
|
3929
|
-
setLoading(true);
|
|
3930
|
-
if (selected) {
|
|
3931
|
-
d2.httpInstance
|
|
3932
|
-
.get(`organisationUnits/${selected}.json?fields=id,displayName,path,code,ancestors[id,displayName]`)
|
|
3933
|
-
.then((response) => {
|
|
3934
|
-
if (response.data) {
|
|
3935
|
-
setSelectedOrgUnit(response.data);
|
|
3936
|
-
handleExpand({ path: response.data['path'] });
|
|
3937
|
-
setLoading(false);
|
|
3938
|
-
}
|
|
3939
|
-
});
|
|
3940
|
-
}
|
|
3941
|
-
else {
|
|
3942
|
-
setShowOrgUnitTree(true);
|
|
3943
|
-
setLoading(false);
|
|
3944
|
-
}
|
|
3945
|
-
}, []);
|
|
3946
|
-
const highlighted = useMemo(() => {
|
|
3947
|
-
if (selectedOrgUnit) {
|
|
3948
|
-
return [selectedOrgUnit['path']];
|
|
3949
|
-
}
|
|
3950
|
-
return undefined;
|
|
3951
|
-
}, [selectedOrgUnit]);
|
|
3952
|
-
const selectedOrgUnitLabel = useMemo(() => {
|
|
3953
|
-
if (selectedOrgUnit) {
|
|
3954
|
-
return [
|
|
3955
|
-
...(selectedOrgUnit['ancestors'] || []),
|
|
3956
|
-
selectedOrgUnit,
|
|
3957
|
-
]
|
|
3958
|
-
.map((orgUnit) => orgUnit['displayName'])
|
|
3959
|
-
.join(' / ');
|
|
3960
|
-
}
|
|
3961
|
-
return '';
|
|
3962
|
-
}, [selectedOrgUnit]);
|
|
3963
|
-
const handleExpand = ({ path }) => {
|
|
3964
|
-
if (expanded && !expanded.includes(path)) {
|
|
3965
|
-
setExpanded([...expanded, path]);
|
|
3966
|
-
}
|
|
3967
|
-
};
|
|
3968
|
-
const handleCollapse = ({ path }) => {
|
|
3969
|
-
const pathIndex = expanded?.indexOf(path);
|
|
3970
|
-
if (pathIndex && pathIndex !== -1 && expanded) {
|
|
3971
|
-
const updatedExpanded = pathIndex === 0
|
|
3972
|
-
? expanded.slice(1)
|
|
3973
|
-
: [...expanded.slice(0, pathIndex), ...expanded.slice(pathIndex + 1)];
|
|
3974
|
-
setExpanded(updatedExpanded);
|
|
3975
|
-
}
|
|
3976
|
-
};
|
|
3977
|
-
const handleOrgUnitSearch = async (query) => {
|
|
3978
|
-
setSearchLoading(true);
|
|
3979
|
-
try {
|
|
3980
|
-
const searchResponse = await d2.httpInstance.get(`organisationUnits.json?fields=id,displayName,path,publicAccess,access,lastUpdated,children[id,displayName,publicAccess,access,path,children::isNotEmpty]&paging=true&query=${query}&withinUserSearchHierarchy=true&pageSize=15`);
|
|
3981
|
-
setSearchData((searchResponse.data || {})['organisationUnits']);
|
|
3982
|
-
setSearchLoading(false);
|
|
3983
|
-
}
|
|
3984
|
-
catch (e) {
|
|
3985
|
-
setSearchLoading(false);
|
|
3986
|
-
}
|
|
3987
|
-
};
|
|
3988
|
-
const debouncedSearch = useCallback(debounce((value) => {
|
|
3989
|
-
handleOrgUnitSearch(value);
|
|
3990
|
-
}, 500), []);
|
|
3991
|
-
const handleFilterChange = (event) => {
|
|
3992
|
-
setSearchText(event.value);
|
|
3993
|
-
debouncedSearch(event.value);
|
|
3994
|
-
};
|
|
3995
|
-
const ready = useMemo(() => {
|
|
3996
|
-
return searchText?.length ? !searchLoading : !loading;
|
|
3997
|
-
}, [searchText, searchLoading, loading]);
|
|
3998
|
-
const renderOrgUnitTree = () => {
|
|
3999
|
-
if (searchText && searchText?.length > 0) {
|
|
4000
|
-
if (searchLoading) {
|
|
4001
|
-
return (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
|
|
4002
|
-
React__default.createElement(CircularLoader$1, { small: true })));
|
|
4003
|
-
}
|
|
4004
|
-
return (ready && (React__default.createElement(OrganisationUnitTree, { key: `${key}-search`, roots: searchData?.map((orgUnit) => orgUnit.id) || [], singleSelection: true, expanded: expanded, handleExpand: handleExpand, handleCollapse: handleCollapse, selected: highlighted, onChange: (event) => {
|
|
4005
|
-
setSelectedOrgUnit(event);
|
|
4006
|
-
setShowOrgUnitTree(false);
|
|
4007
|
-
onSelectOrgUnit(event);
|
|
4008
|
-
} })));
|
|
4009
|
-
}
|
|
4010
|
-
return (React__default.createElement(OrganisationUnitTree, { key: key, roots: rootOrgUnits?.map((orgUnit) => orgUnit.id) || [], singleSelection: true, expanded: expanded, handleExpand: handleExpand, handleCollapse: handleCollapse, selected: highlighted, onChange: (event) => {
|
|
4011
|
-
setSelectedOrgUnit(event);
|
|
4012
|
-
setShowOrgUnitTree(false);
|
|
4013
|
-
onSelectOrgUnit(event);
|
|
4014
|
-
} }));
|
|
4015
|
-
};
|
|
4016
|
-
const handleBlur = () => {
|
|
4017
|
-
// onBlur && onBlur(null);
|
|
4018
|
-
};
|
|
4019
|
-
return (config && (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false },
|
|
4020
|
-
React__default.createElement("div", null,
|
|
4021
|
-
label && (React__default.createElement("div", { className: classes.orgUnitFieldLabel },
|
|
4022
|
-
React__default.createElement("span", null, label),
|
|
4023
|
-
required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
|
|
4024
|
-
!showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
|
|
4025
|
-
React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
|
|
4026
|
-
React__default.createElement(Chip, { onRemove: () => {
|
|
4027
|
-
setShowOrgUnitTree(true);
|
|
4028
|
-
} }, selectedOrgUnit.displayName)))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
|
|
4029
|
-
React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
|
|
4030
|
-
React__default.createElement("div", { className: classes.debounceFieldContainer },
|
|
4031
|
-
React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
|
|
4032
|
-
loading ? (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
|
|
4033
|
-
React__default.createElement(CircularLoader$1, { small: true }))) : (React__default.createElement("div", { className: classes.orgUnitTreeContainer, style: { maxHeight: '200px', overflowY: 'auto' } }, renderOrgUnitTree()))))))));
|
|
4034
|
-
};
|
|
4035
|
-
|
|
4036
4076
|
// src/app/line-list-table.component.ts
|
|
4037
4077
|
class LineListTableComponent extends ReactWrapperModule {
|
|
4038
4078
|
constructor() {
|
|
4039
4079
|
super(...arguments);
|
|
4080
|
+
this.actionOptionOrientation = 'DROPDOWN';
|
|
4040
4081
|
this.dispatchTeis = false;
|
|
4041
4082
|
this.actionSelected = new EventEmitter();
|
|
4042
4083
|
this.reactStateUpdaters = null;
|
|
@@ -4098,8 +4139,9 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4098
4139
|
}, []);
|
|
4099
4140
|
useEffect(() => {
|
|
4100
4141
|
setLoading(true);
|
|
4101
|
-
this.lineListService
|
|
4142
|
+
const subscription = this.lineListService
|
|
4102
4143
|
.getLineListData(this.programId, orgUnitState, this.programStageId, pager.page, pager.pageSize, attributeFiltersState, startDateState, endDateState, this.ouMode, this.filterRootOrgUnit, this.useOuModeWithOlderDHIS2Instance)
|
|
4144
|
+
.pipe(take(1)) // Automatically unsubscribe after the first emission
|
|
4103
4145
|
.subscribe((response) => {
|
|
4104
4146
|
let entityColumns = [];
|
|
4105
4147
|
let responsePager;
|
|
@@ -4114,7 +4156,7 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4114
4156
|
else if ('trackedEntities' in response.data ||
|
|
4115
4157
|
'instances' in response.data) {
|
|
4116
4158
|
const responseData = response.data;
|
|
4117
|
-
responsePager =
|
|
4159
|
+
responsePager = responseData.pager || {
|
|
4118
4160
|
page: responseData.page,
|
|
4119
4161
|
pageSize: responseData.pageSize,
|
|
4120
4162
|
total: responseData.total,
|
|
@@ -4123,23 +4165,18 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4123
4165
|
const { columns, data, filteredEntityColumns } = getTrackedEntityData(response, this.programId, pager, this.isOptionSetNameVisible, this.filters);
|
|
4124
4166
|
entityColumns = columns;
|
|
4125
4167
|
entityData = data;
|
|
4126
|
-
//TODO: Should be done on the parent
|
|
4127
4168
|
const checkValues = [
|
|
4128
|
-
...new Set(
|
|
4169
|
+
...new Set(responseData?.trackedEntities?.[0]?.enrollments?.[0]?.events?.flatMap((event) => event.dataValues
|
|
4129
4170
|
.filter((dataValue) => /^[A-Za-z]{3}$/.test(dataValue.value))
|
|
4130
4171
|
.map((dataValue) => dataValue.value)) ??
|
|
4131
|
-
|
|
4172
|
+
responseData?.instances?.[0]?.enrollments?.[0]?.events?.flatMap((event) => event.dataValues
|
|
4132
4173
|
.filter((dataValue) => /^[A-Za-z]{3}$/.test(dataValue.value))
|
|
4133
4174
|
.map((dataValue) => dataValue.value))),
|
|
4134
4175
|
];
|
|
4135
|
-
if (checkValues) {
|
|
4136
|
-
// this.firstValue.emit(firstTei);
|
|
4176
|
+
if (checkValues.length > 0) {
|
|
4137
4177
|
setCheckValue(checkValues);
|
|
4138
4178
|
setValuesMatch(!checkValues.includes(this.buttonFilter));
|
|
4139
4179
|
}
|
|
4140
|
-
// setFilteredColumns(filteredEntityColumns);
|
|
4141
|
-
// Ensure filter inputs do not disappear when no data is returned
|
|
4142
|
-
// If filteredEntityColumns is empty, keep the previous columns instead of clearing them
|
|
4143
4180
|
setFilteredColumns((prev) => filteredEntityColumns.length > 0 ? filteredEntityColumns : prev);
|
|
4144
4181
|
filteredDataColumns = filteredEntityColumns;
|
|
4145
4182
|
}
|
|
@@ -4151,10 +4188,13 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4151
4188
|
}
|
|
4152
4189
|
const finalColumns = addActionsColumn([{ label: '#', key: 'index' }, ...entityColumns], this.actionOptions);
|
|
4153
4190
|
setLoading(false);
|
|
4154
|
-
setColumns(
|
|
4155
|
-
setData(
|
|
4156
|
-
setPager(
|
|
4191
|
+
setColumns(finalColumns);
|
|
4192
|
+
setData(entityData);
|
|
4193
|
+
setPager(responsePager);
|
|
4157
4194
|
});
|
|
4195
|
+
return () => {
|
|
4196
|
+
subscription.unsubscribe(); // Ensure cleanup on unmount
|
|
4197
|
+
};
|
|
4158
4198
|
}, [
|
|
4159
4199
|
programIdState,
|
|
4160
4200
|
orgUnitState,
|
|
@@ -4166,19 +4206,11 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4166
4206
|
pager.pageSize,
|
|
4167
4207
|
isOptionSetNameVisibleState,
|
|
4168
4208
|
]);
|
|
4169
|
-
const getDropdownOptions = (row) => {
|
|
4170
|
-
return (this.actionOptions || []).map((option) => ({
|
|
4171
|
-
...option,
|
|
4172
|
-
onClick: () => {
|
|
4173
|
-
option.onClick?.(row);
|
|
4174
|
-
this.actionSelected.emit({ action: option.label, row });
|
|
4175
|
-
},
|
|
4176
|
-
}));
|
|
4177
|
-
};
|
|
4178
4209
|
const handleApprovalClick = () => {
|
|
4179
4210
|
setIsButtonLoading(true);
|
|
4180
|
-
this.lineListService
|
|
4211
|
+
const subscription = this.lineListService
|
|
4181
4212
|
.getLineListData(this.programId, this.orgUnit, this.programStageId, pager.page, 1000, this.attributeFilters, this.startDate, this.endDate, this.ouMode)
|
|
4213
|
+
.pipe(take(1)) // Ensures the observable emits only once
|
|
4182
4214
|
.subscribe((response) => {
|
|
4183
4215
|
if ('trackedEntities' in response.data ||
|
|
4184
4216
|
'instances' in response.data) {
|
|
@@ -4186,9 +4218,7 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4186
4218
|
// Map TEIs to objects with teiId and enrollmentId
|
|
4187
4219
|
const teiEnrollmentList = trackedEntityInstances
|
|
4188
4220
|
.map((tei) => {
|
|
4189
|
-
// Find the enrollment where program matches this.programId
|
|
4190
4221
|
const matchingEnrollment = tei.enrollments?.find((enrollment) => enrollment.program === this.programId);
|
|
4191
|
-
// Return object with teiId and enrollmentId (if found)
|
|
4192
4222
|
return matchingEnrollment
|
|
4193
4223
|
? {
|
|
4194
4224
|
teiId: tei.trackedEntity,
|
|
@@ -4196,13 +4226,17 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4196
4226
|
}
|
|
4197
4227
|
: null;
|
|
4198
4228
|
})
|
|
4199
|
-
.filter(
|
|
4229
|
+
.filter(Boolean); // Removes null entries
|
|
4200
4230
|
this.approvalSelected.emit(teiEnrollmentList);
|
|
4201
4231
|
}
|
|
4202
4232
|
else {
|
|
4203
4233
|
this.approvalSelected.emit([]); // Emit empty array if no TEIs
|
|
4204
4234
|
}
|
|
4235
|
+
setIsButtonLoading(false); // Stop loading after processing
|
|
4205
4236
|
});
|
|
4237
|
+
return () => {
|
|
4238
|
+
subscription.unsubscribe(); // Cleanup to avoid potential memory leaks
|
|
4239
|
+
};
|
|
4206
4240
|
};
|
|
4207
4241
|
const handleInputChange = (key, value) => {
|
|
4208
4242
|
setInputValues((prevValues) => ({
|
|
@@ -4247,15 +4281,7 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4247
4281
|
React__default.createElement(Modal$1, { hide: hide },
|
|
4248
4282
|
React__default.createElement(ModalTitle$1, null, "Select organization unit"),
|
|
4249
4283
|
React__default.createElement(ModalContent$1, null,
|
|
4250
|
-
React__default.createElement(OrgUnitFormField$1
|
|
4251
|
-
// label="Select organization unit"
|
|
4252
|
-
, {
|
|
4253
|
-
// label="Select organization unit"
|
|
4254
|
-
key: selectedOrgUnit, onSelectOrgUnit: (selectedOrgUnit) => {
|
|
4255
|
-
// console.log(
|
|
4256
|
-
// 'this is the selected org unit key',
|
|
4257
|
-
// selectedOrgUnit
|
|
4258
|
-
// );
|
|
4284
|
+
React__default.createElement(OrgUnitFormField$1, { key: selectedOrgUnit, onSelectOrgUnit: (selectedOrgUnit) => {
|
|
4259
4285
|
setSelectedOrgUnit(selectedOrgUnit.displayName);
|
|
4260
4286
|
setOrgUnitState(selectedOrgUnit.id);
|
|
4261
4287
|
setHide(true);
|
|
@@ -4266,17 +4292,18 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4266
4292
|
this.showFilters && (React__default.createElement(DataTableToolbar, { className: "table-top-toolbar" },
|
|
4267
4293
|
React__default.createElement("div", { style: {
|
|
4268
4294
|
display: 'flex',
|
|
4295
|
+
alignItems: 'center',
|
|
4269
4296
|
gap: '10px',
|
|
4270
4297
|
flexWrap: 'wrap',
|
|
4271
4298
|
} },
|
|
4272
|
-
React__default.createElement(InputField$1, { key: "location", label: "
|
|
4273
|
-
React__default.createElement(CalendarInput, { label: "Start
|
|
4299
|
+
React__default.createElement(InputField$1, { key: "location", label: "Registraring unit:", value: selectedOrgUnit, clearable: true, onFocus: () => setHide(false), className: "custom-input" }),
|
|
4300
|
+
React__default.createElement(CalendarInput, { label: "Start date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: startDateState, onDateSelect: (selectedDate) => {
|
|
4274
4301
|
setStartDateState(selectedDate.calendarDateString);
|
|
4275
4302
|
} }),
|
|
4276
|
-
React__default.createElement(CalendarInput, { label: "End
|
|
4303
|
+
React__default.createElement(CalendarInput, { label: "End date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: endDateState, onDateSelect: (selectedDate) => {
|
|
4277
4304
|
setEndDateState(selectedDate.calendarDateString);
|
|
4278
4305
|
} }),
|
|
4279
|
-
(visibleFilters ?? []).map(({ label, key }) => (React__default.createElement(InputField$1, { key: key, label: `${label}:`, className: "custom-input", value: inputValues[key] || '', onChange: (e) => {
|
|
4306
|
+
(visibleFilters ?? []).map(({ label, key }) => (React__default.createElement(InputField$1, { key: key, label: `${label}:`, className: "custom-input", value: inputValues[key] || '', clearable: true, onChange: (e) => {
|
|
4280
4307
|
if ('target' in e && e.target) {
|
|
4281
4308
|
setInputValues((prevValues) => ({
|
|
4282
4309
|
...prevValues,
|
|
@@ -4300,12 +4327,19 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4300
4327
|
}
|
|
4301
4328
|
handleInputChange(key, currentValue);
|
|
4302
4329
|
} }))),
|
|
4303
|
-
React__default.createElement(Button$1, { onClick: () => setShowAllFilters(!showAllFilters)
|
|
4330
|
+
React__default.createElement(Button$1, { onClick: () => setShowAllFilters(!showAllFilters) }, showAllFilters ? 'Less Filters' : 'More Filters')))),
|
|
4304
4331
|
React__default.createElement(DataTable, null,
|
|
4305
4332
|
React__default.createElement(TableHead, null,
|
|
4306
4333
|
React__default.createElement(DataTableRow, null, columns.map((col) => (React__default.createElement(DataTableColumnHeader, { key: col.key }, col.label))))),
|
|
4307
|
-
React__default.createElement(TableBody, null, data.length > 0 ? (data.map((row) => (React__default.createElement(DataTableRow, { key: row.index }, columns.map((col) => (React__default.createElement(DataTableCell, { key: col.key }, col.key === 'actions'
|
|
4308
|
-
|
|
4334
|
+
React__default.createElement(TableBody, null, data.length > 0 ? (data.map((row) => (React__default.createElement(DataTableRow, { key: row.index }, columns.map((col) => (React__default.createElement(DataTableCell, { key: col.key }, col.key === 'actions'
|
|
4335
|
+
? this.actionOptions && (React__default.createElement(DataTableActions, { actionOptions: this.actionOptions, actionOptionOrientation: this.actionOptionOrientation, onClick: (option) => {
|
|
4336
|
+
this.actionSelected.emit({
|
|
4337
|
+
action: option.label,
|
|
4338
|
+
row,
|
|
4339
|
+
});
|
|
4340
|
+
} }))
|
|
4341
|
+
: row[col.key] || '--' // Display '--' if value is undefined or null
|
|
4342
|
+
))))))) : (React__default.createElement(DataTableRow, null,
|
|
4309
4343
|
React__default.createElement(DataTableCell, { colSpan: columns.length?.toString(), style: {
|
|
4310
4344
|
textAlign: 'center',
|
|
4311
4345
|
fontWeight: 'bold',
|
|
@@ -4362,11 +4396,11 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4362
4396
|
this.render();
|
|
4363
4397
|
}
|
|
4364
4398
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListTableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
4365
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.8", type: LineListTableComponent, isStandalone: false, selector: "ng-dhis2-ui-line-list", inputs: { programId: "programId", orgUnit: "orgUnit", programStageId: "programStageId", actionOptions: "actionOptions", attributeFilters: "attributeFilters", useOuModeWithOlderDHIS2Instance: "useOuModeWithOlderDHIS2Instance", startDate: "startDate", endDate: "endDate", filters: "filters", ouMode: "ouMode", dispatchTeis: "dispatchTeis", isButtonLoading: "isButtonLoading", buttonLabel: "buttonLabel", buttonFilter: "buttonFilter", filterRootOrgUnit: "filterRootOrgUnit", showFilters: "showFilters", isOptionSetNameVisible: "isOptionSetNameVisible" }, outputs: { actionSelected: "actionSelected", approvalSelected: "approvalSelected", firstValue: "firstValue" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["::ng-deep .custom-input{display:flex!important;gap:4px!important;align-items:center!important;border:1px solid #
|
|
4399
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.8", type: LineListTableComponent, isStandalone: false, selector: "ng-dhis2-ui-line-list", inputs: { programId: "programId", orgUnit: "orgUnit", programStageId: "programStageId", actionOptions: "actionOptions", actionOptionOrientation: "actionOptionOrientation", attributeFilters: "attributeFilters", useOuModeWithOlderDHIS2Instance: "useOuModeWithOlderDHIS2Instance", startDate: "startDate", endDate: "endDate", filters: "filters", ouMode: "ouMode", dispatchTeis: "dispatchTeis", isButtonLoading: "isButtonLoading", buttonLabel: "buttonLabel", buttonFilter: "buttonFilter", filterRootOrgUnit: "filterRootOrgUnit", showFilters: "showFilters", isOptionSetNameVisible: "isOptionSetNameVisible" }, outputs: { actionSelected: "actionSelected", approvalSelected: "approvalSelected", firstValue: "firstValue" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["::ng-deep .custom-input{display:flex!important;gap:4px!important;align-items:center!important;border:1px solid #9fadba!important;border-radius:4px!important;margin:0;padding:0 0 0 8px;background-color:#fff!important}::ng-deep .custom-input div{margin:0!important}::ng-deep .custom-input label{font-size:12px;padding-right:0}::ng-deep .custom-input input{border:none!important;font-size:12px!important;display:flex;align-items:center;padding-left:4px;height:40px;outline:none!important;box-shadow:none!important}::ng-deep .custom-input input:focus{border:none!important;box-shadow:none!important}::ng-deep .custom-input label{color:gray!important;opacity:1}::ng-deep .table-top-toolbar{background-color:var(--colors-grey100)!important;color:var(--colors-grey900)!important}\n"] }); }
|
|
4366
4400
|
}
|
|
4367
4401
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListTableComponent, decorators: [{
|
|
4368
4402
|
type: Component,
|
|
4369
|
-
args: [{ selector: 'ng-dhis2-ui-line-list', template: '<ng-content></ng-content>', standalone: false, styles: ["::ng-deep .custom-input{display:flex!important;gap:4px!important;align-items:center!important;border:1px solid #
|
|
4403
|
+
args: [{ selector: 'ng-dhis2-ui-line-list', template: '<ng-content></ng-content>', standalone: false, styles: ["::ng-deep .custom-input{display:flex!important;gap:4px!important;align-items:center!important;border:1px solid #9fadba!important;border-radius:4px!important;margin:0;padding:0 0 0 8px;background-color:#fff!important}::ng-deep .custom-input div{margin:0!important}::ng-deep .custom-input label{font-size:12px;padding-right:0}::ng-deep .custom-input input{border:none!important;font-size:12px!important;display:flex;align-items:center;padding-left:4px;height:40px;outline:none!important;box-shadow:none!important}::ng-deep .custom-input input:focus{border:none!important;box-shadow:none!important}::ng-deep .custom-input label{color:gray!important;opacity:1}::ng-deep .table-top-toolbar{background-color:var(--colors-grey100)!important;color:var(--colors-grey900)!important}\n"] }]
|
|
4370
4404
|
}], propDecorators: { programId: [{
|
|
4371
4405
|
type: Input
|
|
4372
4406
|
}], orgUnit: [{
|
|
@@ -4375,6 +4409,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
4375
4409
|
type: Input
|
|
4376
4410
|
}], actionOptions: [{
|
|
4377
4411
|
type: Input
|
|
4412
|
+
}], actionOptionOrientation: [{
|
|
4413
|
+
type: Input
|
|
4378
4414
|
}], attributeFilters: [{
|
|
4379
4415
|
type: Input
|
|
4380
4416
|
}], useOuModeWithOlderDHIS2Instance: [{
|
|
@@ -4424,6 +4460,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
4424
4460
|
}]
|
|
4425
4461
|
}] });
|
|
4426
4462
|
|
|
4463
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
4464
|
+
// Use of this source code is governed by a BSD-style
|
|
4465
|
+
// license that can be found in the LICENSE file.
|
|
4466
|
+
|
|
4427
4467
|
const dropdownStyles = {
|
|
4428
4468
|
layer: {
|
|
4429
4469
|
zIndex: '1 !important',
|
|
@@ -5975,9 +6015,24 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5975
6015
|
checkValueUniqueness();
|
|
5976
6016
|
}
|
|
5977
6017
|
}, [this.isValueAssigned()]);
|
|
6018
|
+
// TODO: START: Improve the approach of handling observables
|
|
6019
|
+
// useEffect(() => {
|
|
6020
|
+
// const fieldErrorSubscription = this.fieldError$
|
|
6021
|
+
// .pipe(filter((error) => error !== initialError))
|
|
6022
|
+
// .subscribe({
|
|
6023
|
+
// next: (error: string | undefined) => {
|
|
6024
|
+
// setInitialError(error);
|
|
6025
|
+
// },
|
|
6026
|
+
// });
|
|
6027
|
+
// return () => {
|
|
6028
|
+
// fieldErrorSubscription.unsubscribe();
|
|
6029
|
+
// };
|
|
6030
|
+
// });
|
|
6031
|
+
// TODO: END: Improve the approach of handling observables
|
|
5978
6032
|
useEffect(() => {
|
|
5979
6033
|
const fieldErrorSubscription = this.fieldError$
|
|
5980
|
-
.pipe(filter((error) => error !== initialError))
|
|
6034
|
+
.pipe(filter((error) => error !== initialError), take(1) // Take only the first emitted value, then unsubscribe
|
|
6035
|
+
)
|
|
5981
6036
|
.subscribe({
|
|
5982
6037
|
next: (error) => {
|
|
5983
6038
|
setInitialError(error);
|
|
@@ -5986,7 +6041,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5986
6041
|
return () => {
|
|
5987
6042
|
fieldErrorSubscription.unsubscribe();
|
|
5988
6043
|
};
|
|
5989
|
-
});
|
|
6044
|
+
}, [initialError]); // Add initialError as a dependency to avoid stale closures
|
|
5990
6045
|
const onChange = (payload) => setSelected(payload.selected);
|
|
5991
6046
|
const arrayValue = useMemo(() => {
|
|
5992
6047
|
if (value && value.length > 0) {
|
|
@@ -6873,14 +6928,30 @@ class SelectionFiltersComponent extends ReactWrapperModule {
|
|
|
6873
6928
|
const [selected, setSelected] = useState([]);
|
|
6874
6929
|
const [rootOrgUnits, setRootOrgUnits] = useState();
|
|
6875
6930
|
const [config, setConfig] = useState();
|
|
6931
|
+
// TODO: START::: Improve approach on handling observables
|
|
6932
|
+
// useEffect(() => {
|
|
6933
|
+
// zip(this.getAppConfig(), this.getRootOrgUnits()).subscribe({
|
|
6934
|
+
// next: ([appConfig, rootOrgUnits]) => {
|
|
6935
|
+
// setConfig(appConfig);
|
|
6936
|
+
// setRootOrgUnits(rootOrgUnits);
|
|
6937
|
+
// },
|
|
6938
|
+
// error: (error) => console.error(error),
|
|
6939
|
+
// });
|
|
6940
|
+
// }, []);
|
|
6941
|
+
// TODO: END::: Improve approach on handling observables
|
|
6876
6942
|
useEffect(() => {
|
|
6877
|
-
zip(this.getAppConfig(), this.getRootOrgUnits())
|
|
6943
|
+
const subscription = zip(this.getAppConfig(), this.getRootOrgUnits())
|
|
6944
|
+
.pipe(take(1)) // Ensures only one emission
|
|
6945
|
+
.subscribe({
|
|
6878
6946
|
next: ([appConfig, rootOrgUnits]) => {
|
|
6879
6947
|
setConfig(appConfig);
|
|
6880
6948
|
setRootOrgUnits(rootOrgUnits);
|
|
6881
6949
|
},
|
|
6882
6950
|
error: (error) => console.error(error),
|
|
6883
6951
|
});
|
|
6952
|
+
return () => {
|
|
6953
|
+
subscription.unsubscribe(); // Cleanup to avoid memory leaks
|
|
6954
|
+
};
|
|
6884
6955
|
}, []);
|
|
6885
6956
|
return config ? (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false }, React__default.createElement(Modal$1, { position: "middle", large: true },
|
|
6886
6957
|
React__default.createElement(ModalTitle$1, null, "Organisation unit"),
|