@iapps/ng-dhis2-ui 1.2.1 → 1.2.3

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.
@@ -25,13 +25,13 @@ import { Layer } from '@dhis2-ui/layer';
25
25
  import { CircularLoader } from '@dhis2-ui/loader';
26
26
  import { MenuItem, MenuDivider } from '@dhis2-ui/menu';
27
27
  import parse from 'html-react-parser';
28
- import { Button as Button$1, IconDimensionData16, IconClock16, IconDimensionOrgUnit16, spacers as spacers$1, colors as colors$1, IconEdit16, theme as theme$1, Tooltip, IconChevronRight16, SingleSelectField, SingleSelectOption, InputField as InputField$1, TabBar, Tab, Transfer, Modal as Modal$1, ModalTitle as ModalTitle$1, ModalContent as ModalContent$1, ModalActions as ModalActions$1, ButtonStrip as ButtonStrip$1, Checkbox, OrganisationUnitTree, MultiSelect, MultiSelectOption, IconWarningFilled16, DataTableToolbar, CalendarInput, TableHead, DataTableRow, DataTableColumnHeader, Layer as Layer$1, Popper, FlyoutMenu, MenuItem as MenuItem$1, IconMore24, DataTableCell, TableBody as TableBody$1, Pagination as Pagination$1, TableFoot, DataTable, CircularLoader as CircularLoader$1, Chip, FileInputField, FileListItem, MultiSelectField, TextAreaField } from '@dhis2/ui';
28
+ import { Button as Button$1, IconDimensionData16, IconClock16, IconDimensionOrgUnit16, spacers as spacers$1, colors as colors$1, IconEdit16, theme as theme$1, Tooltip, IconChevronRight16, SingleSelectField, SingleSelectOption, InputField as InputField$1, TabBar, Tab, Transfer, Modal as Modal$1, ModalTitle as ModalTitle$1, ModalContent as ModalContent$1, ModalActions as ModalActions$1, ButtonStrip as ButtonStrip$1, Checkbox, OrganisationUnitTree, MultiSelect, MultiSelectOption, IconWarningFilled16, CircularLoader as CircularLoader$1, Chip, DataTableToolbar, CalendarInput, TableHead, DataTableRow, DataTableColumnHeader, Layer as Layer$1, Popper, FlyoutMenu, MenuItem as MenuItem$1, IconMore24, DataTableCell, TableBody as TableBody$1, Pagination as Pagination$1, TableFoot, DataTable, FileInputField, FileListItem, MultiSelectField, TextAreaField } from '@dhis2/ui';
29
29
  import { isObject, isString, debounce, sortBy, isArray, find, camelCase, flatten, isUndefined, head, isEmpty } from 'lodash';
30
30
  import cx from 'classnames';
31
31
  import { getNowInCalendar, generateFixedPeriods } from '@dhis2/multi-calendar-dates';
32
+ import { Pager, DataOrderCriteria, DataQueryFilter, DataFilterCondition, ProgramRuleEngine } from '@iapps/d2-web-sdk';
32
33
  import { map as map$1 } from 'rxjs/operators';
33
34
  import { format, parse as parse$1 } from 'date-fns';
34
- import { Pager, DataOrderCriteria, DataQueryFilter, DataFilterCondition, ProgramRuleEngine } from '@iapps/d2-web-sdk';
35
35
  import * as i2 from '@angular/forms';
36
36
  import { Validators, UntypedFormControl, UntypedFormGroup, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
37
37
  import { toObservable } from '@angular/core/rxjs-interop';
@@ -3106,444 +3106,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
3106
3106
  // Use of this source code is governed by a BSD-style
3107
3107
  // license that can be found in the LICENSE file.
3108
3108
 
3109
- class LineListService {
3110
- constructor(httpClient) {
3111
- this.httpClient = httpClient;
3112
- }
3113
- /**
3114
- * Fetch orgUnit names for given orgUnit IDs
3115
- */
3116
- fetchOrgUnits(orgUnitIds) {
3117
- const idsQuery = `filter=id:in:[${orgUnitIds}]`;
3118
- return this.httpClient
3119
- .get(`organisationUnits.json?fields=id,name&paging=false&${idsQuery}`)
3120
- .pipe(map$1((response) => {
3121
- const orgUnitsMap = new Map();
3122
- response.organisationUnits.forEach((orgUnit) => {
3123
- orgUnitsMap.set(orgUnit.id, orgUnit.name);
3124
- });
3125
- return orgUnitsMap;
3126
- }));
3127
- }
3128
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListService, deps: [{ token: i1.NgxDhis2HttpClientService }], target: i0.ɵɵFactoryTarget.Injectable }); }
3129
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListService }); }
3130
- }
3131
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListService, decorators: [{
3132
- type: Injectable
3133
- }], ctorParameters: () => [{ type: i1.NgxDhis2HttpClientService }] });
3134
-
3135
- const getTrackedEntityTableData = (response, programId, pager, metaData) => {
3136
- const teisRaw = response.data
3137
- .trackedEntityInstances;
3138
- const teis = Array.isArray(teisRaw)
3139
- ? teisRaw
3140
- : [teisRaw];
3141
- const orgUnitLabel = metaData.orgUnitLabel;
3142
- const orgUnitMap = response.data
3143
- .orgUnitsMap;
3144
- const attributeColumns = metaData.displayInListTrackedEntityAttributes
3145
- .sort((a, b) => a.sortOrder - b.sortOrder)
3146
- .map((attr) => ({
3147
- label: attr.name,
3148
- key: attr.id,
3149
- }));
3150
- const dataElementColumns = metaData.displayInListDataElements
3151
- .sort((a, b) => a.sortOrder - b.sortOrder)
3152
- .map((element) => ({
3153
- label: element.name,
3154
- key: element.id,
3155
- }));
3156
- const dataElementOptions = metaData.displayInListDataElements.map((element) => ({
3157
- id: element.id,
3158
- options: element.optionSet?.options.map((opt) => ({
3159
- name: opt.name,
3160
- color: opt.style?.color,
3161
- })),
3162
- }));
3163
- const tableColumns = [
3164
- {
3165
- label: orgUnitLabel || 'registering unit',
3166
- key: 'orgUnit',
3167
- },
3168
- ...attributeColumns,
3169
- ...dataElementColumns,
3170
- ];
3171
- const tableFilters = metaData.searchableTrackedEntityAttributes
3172
- .sort((a, b) => a.sortOrder - b.sortOrder)
3173
- .map((attr) => ({
3174
- label: attr.name,
3175
- key: attr.id,
3176
- valueType: attr.valueType,
3177
- options: attr.optionSet ?? undefined,
3178
- }));
3179
- const tableData = teis.map((tei, idx) => {
3180
- const row = {
3181
- trackedEntityInstance: { value: tei.trackedEntity },
3182
- index: { value: (pager.page - 1) * pager.pageSize + idx + 1 },
3183
- };
3184
- const matchingEnrollment = tei.latestEnrollment;
3185
- let attributesData = matchingEnrollment.attributes;
3186
- const dataElementsData = matchingEnrollment.events.flatMap((event) => event.dataValues);
3187
- attributesData = attributesData.map((attr) => {
3188
- if (attr?.valueType?.toLowerCase() === 'date') {
3189
- try {
3190
- return {
3191
- ...attr,
3192
- value: format(parse$1(attr.value, 'yyyy-MM-dd', new Date()), 'dd/MM/yyyy'),
3193
- };
3194
- }
3195
- catch {
3196
- return { ...attr }; // Leave value as is on parse failure
3197
- }
3198
- }
3199
- return attr;
3200
- });
3201
- attributesData.forEach((attr) => {
3202
- row[attr.attribute] = { value: attr.value };
3203
- });
3204
- dataElementsData.forEach((element) => {
3205
- // Find the matching data element in dataElementOptions by ID
3206
- const dataElementOption = dataElementOptions.find((deo) => deo.id === element.dataElement);
3207
- // find a matching option within that data element's options
3208
- const matchingOption = dataElementOption?.options?.find((opt) => opt.name === element.value);
3209
- // Build the row entry with value and optionally style
3210
- if (matchingOption) {
3211
- row[element.dataElement] = {
3212
- value: element.value,
3213
- style: matchingOption.color,
3214
- };
3215
- }
3216
- else {
3217
- row[element.dataElement] = {
3218
- value: element.value,
3219
- };
3220
- }
3221
- });
3222
- // Include orgUnit in the row for id access with style
3223
- row['orgUnitId'] = { value: matchingEnrollment.orgUnit };
3224
- row['orgUnit'] = {
3225
- value: orgUnitMap?.get(matchingEnrollment.orgUnit) || '-',
3226
- };
3227
- row['responseData'] = { value: tei.toObject() };
3228
- return row;
3229
- });
3230
- return {
3231
- columns: tableColumns,
3232
- data: tableData,
3233
- filteredEntityColumns: tableFilters,
3234
- orgUnitLabel: orgUnitLabel,
3235
- };
3236
- };
3237
- const addActionsColumn = (columns, actionOptions) => {
3238
- return [
3239
- ...columns,
3240
- ...(actionOptions && actionOptions.length > 0
3241
- ? [{ label: 'Actions', key: 'actions' }]
3242
- : []),
3243
- ];
3244
- };
3245
-
3246
- const FilterToolbar = ({ orgUnitLabel, selectedOrgUnit, setSelectedOrgUnit, setOrgUnitState, defaultOrgUnit, setHide, startDateState, setStartDateState, endDateState, setEndDateState, visibleFilters, dateStates, inputValues, setInputValues, handleInputChange, handleInputChangeForSelectField, handleDateSelect, prevValue, setPrevValue, showAllFilters, setShowAllFilters, }) => (React__default.createElement(DataTableToolbar, { className: "table-top-toolbar" },
3247
- React__default.createElement("div", { style: {
3248
- display: 'flex',
3249
- alignItems: 'center',
3250
- gap: '10px',
3251
- flexWrap: 'wrap',
3252
- } },
3253
- React__default.createElement(InputField$1, { key: "location", label: orgUnitLabel ? orgUnitLabel : 'registering unit:', value: selectedOrgUnit, onFocus: () => setHide(false), className: "custom-input", clearable: true, onChange: (event) => {
3254
- setSelectedOrgUnit(event.value);
3255
- setOrgUnitState(defaultOrgUnit);
3256
- } }),
3257
- React__default.createElement(CalendarInput, { label: "Start date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: startDateState, onDateSelect: (selectedDate) => {
3258
- setStartDateState(selectedDate.calendarDateString);
3259
- } }),
3260
- React__default.createElement(CalendarInput, { label: "End date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: endDateState, onDateSelect: (selectedDate) => {
3261
- setEndDateState(selectedDate.calendarDateString);
3262
- } }),
3263
- (visibleFilters ?? []).map(({ label, key, valueType, options }) => {
3264
- if (valueType === 'DATE') {
3265
- return (React__default.createElement(CalendarInput, { key: key, label: `${label}:`, calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: dateStates[key] || '', onDateSelect: (selectedDate) => handleDateSelect(key, selectedDate) }));
3266
- }
3267
- if (options && options.options.length > 0) {
3268
- return (React__default.createElement(SingleSelectField, { key: key, label: `${label}:`, selected: inputValues[key] || '', className: "custom-select-input", clearable: true, onChange: ({ selected }) => {
3269
- setInputValues((prevValues) => ({
3270
- ...prevValues,
3271
- [key]: selected ?? '',
3272
- }));
3273
- handleInputChangeForSelectField(key, selected ?? '');
3274
- } }, (options.options ?? []).map((opt) => (React__default.createElement(SingleSelectOption, { key: opt.id, label: opt.name, value: opt.code })))));
3275
- }
3276
- return (React__default.createElement(InputField$1, { key: key, label: `${label}:`, className: "custom-input", value: inputValues[key] || '', clearable: true, onChange: (e) => {
3277
- const currentValue = 'target' in e ? e.target.value : e.value ?? '';
3278
- setInputValues((prevValues) => ({
3279
- ...prevValues,
3280
- [key]: currentValue,
3281
- }));
3282
- if (currentValue === '') {
3283
- handleInputChange(key, '');
3284
- }
3285
- }, onBlur: (e) => {
3286
- const currentValue = 'target' in e ? e.target.value : e.value ?? '';
3287
- if (currentValue !== '' && currentValue !== prevValue) {
3288
- handleInputChange(key, currentValue);
3289
- setPrevValue(currentValue);
3290
- }
3291
- } }));
3292
- }),
3293
- React__default.createElement(Button$1, { onClick: () => setShowAllFilters(!showAllFilters) }, showAllFilters ? 'Less Filters' : 'More Filters'))));
3294
-
3295
- const TableHeader = ({ columns }) => (React__default.createElement(TableHead, null,
3296
- React__default.createElement(DataTableRow, null, columns.map((col) => (React__default.createElement(DataTableColumnHeader, { key: col.key }, col.label))))));
3297
-
3298
- const dropdownStyles$1 = {
3299
- layer: {
3300
- zIndex: '1 !important',
3301
- },
3302
- };
3303
-
3304
- // Helper function to generate a unique class name
3305
- const generateClassName$1 = (base) => `${base}-${Math.random().toString(36).substr(2, 9)}`;
3306
- // Helper function to convert camelCased properties to hyphenated CSS properties
3307
- const convertStylesToCSS$1 = (className, styles) => {
3308
- let cssString = `.${className} {`;
3309
- for (const key in styles) {
3310
- if (typeof styles[key] === "object" && key.startsWith("@media")) {
3311
- const mediaStyles = convertStylesToCSS$1(className, styles[key]);
3312
- cssString += `${key} { ${mediaStyles} }`;
3313
- }
3314
- else if (key.startsWith("&:")) {
3315
- const pseudoClass = key.replace("&", "");
3316
- cssString += `${pseudoClass} { ${convertStylesToCSS$1("", styles[key])} }`;
3317
- }
3318
- else {
3319
- const cssKey = key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
3320
- cssString += `${cssKey}: ${styles[key]}; `;
3321
- }
3322
- }
3323
- cssString += "}";
3324
- return cssString;
3325
- };
3326
- // Custom hook for dynamic styles with generics
3327
- const useDynamicStyles$1 = (stylesObj) => {
3328
- const [classNames, setClassNames] = useState({});
3329
- useEffect(() => {
3330
- const convertedStyles = Object.keys(stylesObj).map((key) => {
3331
- const className = generateClassName$1(key);
3332
- const styleElement = document.createElement("style");
3333
- styleElement.innerHTML = convertStylesToCSS$1(className, stylesObj[key]);
3334
- document.head.appendChild(styleElement);
3335
- return {
3336
- key,
3337
- className,
3338
- styleElement,
3339
- };
3340
- });
3341
- setClassNames(convertedStyles.reduce((classNameEntity, convertedStyle) => {
3342
- return {
3343
- ...classNameEntity,
3344
- [convertedStyle.key]: convertedStyle.className,
3345
- };
3346
- }, {}));
3347
- return () => {
3348
- convertedStyles.forEach((convertedStyle) => {
3349
- document.head.removeChild(convertedStyle.styleElement);
3350
- });
3351
- };
3352
- }, []);
3353
- return classNames;
3354
- };
3355
-
3356
- const useCurrentModal$1 = () => {
3357
- const [CurrentModal, setCurrentModal] = useState();
3358
- return [
3359
- CurrentModal,
3360
- (Modal) => {
3361
- // As setState supports functional updates, we can't pass functional
3362
- // components directly
3363
- setCurrentModal(() => Modal);
3364
- },
3365
- ];
3366
- };
3367
- const ContextMenu$1 = (params) => {
3368
- const { onClose, onMenuClick, anchorRef, dropDownOptions } = params;
3369
- const [CurrentModal, setCurrentModal] = useCurrentModal$1();
3370
- const styles = useDynamicStyles$1(dropdownStyles$1);
3371
- return (React__default.createElement(React__default.Fragment, null,
3372
- React__default.createElement(Layer$1, { onBackdropClick: (event, data) => onClose(event, data), className: styles.layer },
3373
- React__default.createElement(Popper, { reference: anchorRef, placement: "bottom-start" },
3374
- React__default.createElement(FlyoutMenu, null, dropDownOptions.map((dropDownOption, index) => (React__default.createElement(MenuItem$1, { key: index, destructive: dropDownOption.destructive, label: dropDownOption.label, icon: dropDownOption.icon, onClick: () => {
3375
- onMenuClick(dropDownOption);
3376
- onClose();
3377
- }, dense: true })))))),
3378
- CurrentModal && (React__default.createElement(CurrentModal, { onClose: () => {
3379
- onClose();
3380
- setCurrentModal(null);
3381
- } }))));
3382
- };
3383
- const DropdownMenu$1 = (props) => {
3384
- const ref = useRef();
3385
- const [visible, setVisible] = useState(false);
3386
- const { dropdownOptions, onClick } = props;
3387
- return (React__default.createElement("div", { ref: ref, style: { display: 'inline-block' } },
3388
- React__default.createElement(Button$1, { small: true, secondary: true, icon: React__default.createElement(IconMore24, { color: colors$1.grey600 }), onClick: () => setVisible(true) }),
3389
- visible && (React__default.createElement(ContextMenu$1, { dropDownOptions: dropdownOptions, anchorRef: ref, onClose: () => setVisible(false), onMenuClick: (dropDownOption) => {
3390
- onClick(dropDownOption);
3391
- } }))));
3392
- };
3393
-
3394
- // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3395
- // Use of this source code is governed by a BSD-style
3396
- // license that can be found in the LICENSE file.
3397
- const DataTableActions = (props) => {
3398
- const { actionOptions, actionOptionOrientation, onClick } = props;
3399
- switch (actionOptionOrientation) {
3400
- case 'BUTTON':
3401
- 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 : '')))));
3402
- case 'DROPDOWN':
3403
- return (React__default.createElement(DropdownMenu$1, { dropdownOptions: actionOptions, onClick: (option) => {
3404
- onClick(option);
3405
- } }));
3406
- case 'LINK':
3407
- return (React__default.createElement("div", { style: {
3408
- display: 'flex',
3409
- gap: 16,
3410
- alignItems: 'center',
3411
- } }, actionOptions.map((option) => (React__default.createElement("a", { style: {
3412
- cursor: 'pointer',
3413
- textDecoration: 'underline',
3414
- fontSize: 14,
3415
- display: 'flex',
3416
- alignItems: 'center',
3417
- gap: 4,
3418
- color: option.destructive ? colors$1.red700 : colors$1.grey900,
3419
- }, key: option.label, onClick: (event) => {
3420
- event.stopPropagation();
3421
- onClick(option);
3422
- } },
3423
- option.icon ? React__default.createElement(option.icon, null) : React__default.createElement(React__default.Fragment, null),
3424
- !option.iconOnly ? React__default.createElement("span", null, option.label) : React__default.createElement(React__default.Fragment, null))))));
3425
- default:
3426
- return React__default.createElement(React__default.Fragment, null);
3427
- }
3428
- };
3429
-
3430
- // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3431
- // Use of this source code is governed by a BSD-style
3432
- // license that can be found in the LICENSE file.
3433
-
3434
- const TableCell = ({ cell, getTextColorFromBackGround, }) => {
3435
- if (cell?.style && cell?.style !== 'default-value') {
3436
- return (React__default.createElement(DataTableCell, null,
3437
- React__default.createElement("div", { style: { display: 'flex', justifyContent: 'center' } },
3438
- React__default.createElement("span", { style: {
3439
- backgroundColor: cell.style,
3440
- display: 'inline-flex',
3441
- alignItems: 'center',
3442
- padding: 4,
3443
- borderRadius: 3,
3444
- fontSize: 12,
3445
- color: getTextColorFromBackGround(cell.style),
3446
- } }, cell.value))));
3447
- }
3448
- return (React__default.createElement(DataTableCell, null,
3449
- React__default.createElement("div", { className: "text-sm text-gray-800" }, cell?.value || '-')));
3450
- };
3451
-
3452
- const TableRow = ({ row, columns, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, }) => (React__default.createElement(DataTableRow, { key: row.index.value }, columns.map((col) => {
3453
- if (col.key === 'actions') {
3454
- return (React__default.createElement(DataTableCell, { key: col.key }, actionOptions && (React__default.createElement(DataTableActions, { actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, onClick: (option) => {
3455
- const data = row['responseData']?.['value'];
3456
- if (option.onClick)
3457
- option.onClick(data);
3458
- actionSelected.emit({
3459
- action: option.label,
3460
- data,
3461
- });
3462
- } }))));
3463
- }
3464
- return (React__default.createElement(TableCell, { key: col.key, cell: row[col.key], getTextColorFromBackGround: getTextColorFromBackGround }));
3465
- })));
3466
-
3467
- const TableBody = ({ data, columns, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, }) => (React__default.createElement(TableBody$1, null, data.length > 0 ? (data.map((row) => (React__default.createElement(TableRow, { key: row.index.value, row: row, columns: columns, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, actionSelected: actionSelected })))) : (React__default.createElement(DataTableRow, null,
3468
- React__default.createElement(DataTableCell, { colSpan: columns.length.toString(), style: {
3469
- textAlign: 'center',
3470
- fontWeight: 'bold',
3471
- color: 'grey',
3472
- padding: '20px',
3473
- } }, "No data found")))));
3474
-
3475
- const Pagination = ({ pager, setPager }) => {
3476
- if (!pager || pager.page === undefined || pager.pageSize === undefined) {
3477
- return null; //skip rendering until valid
3478
- }
3479
- return (React__default.createElement(Pagination$1, { page: pager.page, pageCount: pager.pageCount, pageSize: pager.pageSize, total: pager.total, onPageChange: (page) => setPager((prev) => new Pager({ ...prev, page })), onPageSizeChange: (pageSize) => setPager((prev) => new Pager({
3480
- ...prev,
3481
- pageSize: Number(pageSize),
3482
- page: 1,
3483
- })), pageSizes: ['10', '20', '50', '100', '500'] }));
3484
- };
3485
-
3486
- const TableFooter = ({ pager, setPager, columns }) => {
3487
- return (React__default.createElement(TableFoot, null,
3488
- React__default.createElement(DataTableRow, null,
3489
- React__default.createElement(DataTableCell, { colSpan: columns.length.toString() },
3490
- React__default.createElement(Pagination, { pager: pager, setPager: setPager })))));
3491
- };
3492
-
3493
- const LineListTable = ({ columns, data, pager, setPager, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, }) => {
3494
- return (React__default.createElement(DataTable, null,
3495
- React__default.createElement(TableHeader, { columns: columns }),
3496
- React__default.createElement(TableBody, { data: data, columns: columns, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, actionSelected: actionSelected }),
3497
- React__default.createElement(TableFooter, { columns: columns, pager: pager, setPager: setPager })));
3498
- };
3499
-
3500
- // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3501
- // Use of this source code is governed by a BSD-style
3502
- // license that can be found in the LICENSE file.
3503
- // @flow
3504
- const orgUnitFieldStyles$1 = {
3505
- container: {
3506
- border: '1px solid',
3507
- borderColor: colors$1.grey400,
3508
- borderRadius: '3px',
3509
- height: '100%',
3510
- width: '100%',
3511
- zIndex: 0,
3512
- backgroundColor: 'white',
3513
- },
3514
- searchField: {
3515
- height: '40px',
3516
- overflow: 'hidden',
3517
- borderBottomLeftRadius: 0,
3518
- borderBottomRightRadius: 0,
3519
- boxShadow: 'none',
3520
- border: 'none',
3521
- },
3522
- debounceFieldContainer: {
3523
- padding: '8px',
3524
- background: colors$1.grey100,
3525
- borderTopLeftRadius: '3px',
3526
- borderTopRightRadius: '3px',
3527
- },
3528
- orgUnitTreeContainer: {
3529
- borderBottomLeftRadius: '3px',
3530
- borderBottomRightRadius: '3px',
3531
- overflow: 'auto',
3532
- },
3533
- orgUnitTreeLoader: {
3534
- padding: '8px',
3535
- },
3536
- orgUnitFieldLabel: {
3537
- marginBottom: '8px',
3538
- display: 'block',
3539
- boxSizing: 'border-box',
3540
- fontSize: '14px',
3541
- lineHeight: '19px',
3542
- color: 'rgb(33, 41, 52)',
3543
- padding: '0',
3544
- },
3545
- orgUnitFieldRequiredLabel: {
3546
- paddingInlineStart: '4px',
3109
+ // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3110
+ // Use of this source code is governed by a BSD-style
3111
+ // license that can be found in the LICENSE file.
3112
+ // @flow
3113
+ const orgUnitFieldStyles$1 = {
3114
+ container: {
3115
+ border: '1px solid',
3116
+ borderColor: colors$1.grey400,
3117
+ borderRadius: '3px',
3118
+ height: '100%',
3119
+ width: '100%',
3120
+ zIndex: 0,
3121
+ backgroundColor: 'white',
3122
+ },
3123
+ searchField: {
3124
+ height: '40px',
3125
+ overflow: 'hidden',
3126
+ borderBottomLeftRadius: 0,
3127
+ borderBottomRightRadius: 0,
3128
+ boxShadow: 'none',
3129
+ border: 'none',
3130
+ },
3131
+ debounceFieldContainer: {
3132
+ padding: '8px',
3133
+ background: colors$1.grey100,
3134
+ borderTopLeftRadius: '3px',
3135
+ borderTopRightRadius: '3px',
3136
+ },
3137
+ orgUnitTreeContainer: {
3138
+ borderBottomLeftRadius: '3px',
3139
+ borderBottomRightRadius: '3px',
3140
+ overflow: 'auto',
3141
+ },
3142
+ orgUnitTreeLoader: {
3143
+ padding: '8px',
3144
+ },
3145
+ orgUnitFieldLabel: {
3146
+ marginBottom: '8px',
3147
+ display: 'block',
3148
+ boxSizing: 'border-box',
3149
+ fontSize: '14px',
3150
+ lineHeight: '19px',
3151
+ color: 'rgb(33, 41, 52)',
3152
+ padding: '0',
3153
+ },
3154
+ orgUnitFieldRequiredLabel: {
3155
+ paddingInlineStart: '4px',
3547
3156
  },
3548
3157
  };
3549
3158
  const OrgUnitFormField$1 = (props) => {
@@ -3640,58 +3249,643 @@ const OrgUnitFormField$1 = (props) => {
3640
3249
  setSearchText(event.value);
3641
3250
  debouncedSearch(event.value);
3642
3251
  };
3643
- const ready = useMemo(() => {
3644
- return searchText?.length ? !searchLoading : !loading;
3645
- }, [searchText, searchLoading, loading]);
3646
- const renderOrgUnitTree = () => {
3647
- if (searchText && searchText?.length > 0) {
3648
- if (searchLoading) {
3649
- return (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3650
- React__default.createElement(CircularLoader$1, { small: true })));
3252
+ const ready = useMemo(() => {
3253
+ return searchText?.length ? !searchLoading : !loading;
3254
+ }, [searchText, searchLoading, loading]);
3255
+ const renderOrgUnitTree = () => {
3256
+ if (searchText && searchText?.length > 0) {
3257
+ if (searchLoading) {
3258
+ return (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3259
+ React__default.createElement(CircularLoader$1, { small: true })));
3260
+ }
3261
+ 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) => {
3262
+ setSelectedOrgUnit(event);
3263
+ setShowOrgUnitTree(false);
3264
+ onSelectOrgUnit(event);
3265
+ } })));
3266
+ }
3267
+ 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) => {
3268
+ setSelectedOrgUnit(event);
3269
+ setShowOrgUnitTree(false);
3270
+ onSelectOrgUnit(event);
3271
+ } }));
3272
+ };
3273
+ const handleBlur = () => {
3274
+ // onBlur && onBlur(null);
3275
+ };
3276
+ return (config && (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false },
3277
+ React__default.createElement("div", null,
3278
+ label && (React__default.createElement("div", { className: classes.orgUnitFieldLabel },
3279
+ React__default.createElement("span", null, label),
3280
+ required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
3281
+ !showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
3282
+ React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
3283
+ React__default.createElement(Chip, { onRemove: () => {
3284
+ setShowOrgUnitTree(true);
3285
+ } }, selectedOrgUnit.displayName)))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3286
+ React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
3287
+ React__default.createElement("div", { className: classes.debounceFieldContainer },
3288
+ React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
3289
+ loading ? (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3290
+ React__default.createElement(CircularLoader$1, { small: true }))) : (React__default.createElement("div", { className: classes.orgUnitTreeContainer, style: { maxHeight: '200px', overflowY: 'auto' } }, renderOrgUnitTree()))))))));
3291
+ };
3292
+
3293
+ const OrgUnitSelector = ({ hide, setHide, selectedOrgUnit, setSelectedOrgUnit, setOrgUnitState, }) => (React__default.createElement(Modal$1, { hide: hide, position: "middle" },
3294
+ React__default.createElement(ModalTitle$1, null, "Select organization unit"),
3295
+ React__default.createElement(ModalContent$1, null,
3296
+ React__default.createElement(OrgUnitFormField$1, { key: selectedOrgUnit, onSelectOrgUnit: (selectedOrgUnit) => {
3297
+ setSelectedOrgUnit(selectedOrgUnit.displayName);
3298
+ setOrgUnitState(selectedOrgUnit.id);
3299
+ setHide(true);
3300
+ } })),
3301
+ React__default.createElement(ModalActions$1, null,
3302
+ React__default.createElement(ButtonStrip$1, { end: true },
3303
+ React__default.createElement(Button$1, { onClick: () => setHide(true), secondary: true }, "Close")))));
3304
+
3305
+ const FilterToolbar = ({ orgUnitLabel, selectedOrgUnit, setSelectedOrgUnit, setOrgUnitState, defaultOrgUnit, setHide, startDateState, setStartDateState, endDateState, setEndDateState, visibleFilters, dateStates, inputValues, setInputValues, handleInputChange, handleInputChangeForSelectField, handleDateSelect, prevValue, setPrevValue, showAllFilters, setShowAllFilters, }) => (React__default.createElement(DataTableToolbar, { className: "table-top-toolbar" },
3306
+ React__default.createElement("div", { style: {
3307
+ display: 'flex',
3308
+ alignItems: 'center',
3309
+ gap: '10px',
3310
+ flexWrap: 'wrap',
3311
+ } },
3312
+ React__default.createElement(InputField$1, { key: "location", label: orgUnitLabel ? orgUnitLabel : 'registering unit:', value: selectedOrgUnit, onFocus: () => setHide(false), className: "custom-input", clearable: true, onChange: (event) => {
3313
+ setSelectedOrgUnit(event.value);
3314
+ setOrgUnitState(defaultOrgUnit);
3315
+ } }),
3316
+ React__default.createElement(CalendarInput, { label: "Start date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", clearable: !!startDateState, date: startDateState, onDateSelect: (selectedDate) => {
3317
+ if (!(selectedDate.calendarDateString === null)) {
3318
+ setStartDateState(selectedDate.calendarDateString);
3319
+ }
3320
+ console.log(selectedDate.calendarDateString);
3321
+ } }),
3322
+ React__default.createElement(CalendarInput, { label: "End date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", clearable: !!endDateState, date: endDateState, onDateSelect: (selectedDate) => {
3323
+ if (!(selectedDate.calendarDateString === null)) {
3324
+ setEndDateState(selectedDate.calendarDateString);
3325
+ }
3326
+ } }),
3327
+ (visibleFilters ?? []).map(({ label, key, valueType, options }) => {
3328
+ if (valueType === 'DATE') {
3329
+ return (React__default.createElement(CalendarInput, { key: key, label: `${label}:`, calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", clearable: !!dateStates[key], date: dateStates[key], onDateSelect: (selectedDate) => {
3330
+ handleDateSelect(key, selectedDate);
3331
+ } }));
3332
+ }
3333
+ if (options && options.options.length > 0) {
3334
+ return (React__default.createElement(SingleSelectField, { key: key, label: `${label}:`, selected: inputValues[key] || '', className: "custom-select-input", clearable: true, onChange: ({ selected }) => {
3335
+ setInputValues((prevValues) => ({
3336
+ ...prevValues,
3337
+ [key]: selected ?? '',
3338
+ }));
3339
+ handleInputChangeForSelectField(key, selected ?? '');
3340
+ } }, (options.options ?? []).map((opt) => (React__default.createElement(SingleSelectOption, { key: opt.id, label: opt.name, value: opt.code })))));
3341
+ }
3342
+ return (React__default.createElement(InputField$1, { key: key, label: `${label}:`, className: "custom-input", value: inputValues[key] || '', clearable: true, onChange: (e) => {
3343
+ const currentValue = 'target' in e ? e.target.value : e.value ?? '';
3344
+ setInputValues((prevValues) => ({
3345
+ ...prevValues,
3346
+ [key]: currentValue,
3347
+ }));
3348
+ if (currentValue === '') {
3349
+ handleInputChange(key, '');
3350
+ }
3351
+ }, onBlur: (e) => {
3352
+ const currentValue = 'target' in e ? e.target.value : e.value ?? '';
3353
+ if (currentValue !== '' && currentValue !== prevValue) {
3354
+ handleInputChange(key, currentValue);
3355
+ setPrevValue(currentValue);
3356
+ }
3357
+ } }));
3358
+ }),
3359
+ React__default.createElement(Button$1, { onClick: () => setShowAllFilters(!showAllFilters) }, showAllFilters ? 'Less Filters' : 'More Filters'))));
3360
+
3361
+ // export const TableHeader = ({
3362
+ // columns,
3363
+ // data,
3364
+ // }: {
3365
+ // columns: any[];
3366
+ // data: TableRow;
3367
+ // }) => {
3368
+ // const [checked, setChecked] = useState(false);
3369
+ // const handleCheckboxChange = () => {
3370
+ // const newChecked = !checked;
3371
+ // setChecked(newChecked);
3372
+ // console.log('Header checkbox toggled. Checked:', newChecked);
3373
+ // console.log('Row selected:', data);
3374
+ // };
3375
+ // return (
3376
+ // <TableHead>
3377
+ // <DataTableRow>
3378
+ // <DataTableColumnHeader width="48px">
3379
+ // <Checkbox checked={checked} onChange={handleCheckboxChange} />
3380
+ // </DataTableColumnHeader>
3381
+ // {columns.map((col) => (
3382
+ // <DataTableColumnHeader key={col.key}>
3383
+ // {col.label}
3384
+ // </DataTableColumnHeader>
3385
+ // ))}
3386
+ // </DataTableRow>
3387
+ // </TableHead>
3388
+ // );
3389
+ // };
3390
+ const TableHeader = ({ columns, allSelected, onSelectAll, selectable, }) => {
3391
+ const handleCheckboxChange = () => {
3392
+ onSelectAll(!allSelected);
3393
+ };
3394
+ return (React__default.createElement(TableHead, null,
3395
+ React__default.createElement(DataTableRow, null,
3396
+ selectable && (React__default.createElement(DataTableColumnHeader, { width: "48px" },
3397
+ React__default.createElement(Checkbox, { checked: allSelected, onChange: handleCheckboxChange }))),
3398
+ columns.map((col) => (React__default.createElement(DataTableColumnHeader, { key: col.key }, col.label))))));
3399
+ };
3400
+
3401
+ const dropdownStyles$1 = {
3402
+ layer: {
3403
+ zIndex: '1 !important',
3404
+ },
3405
+ };
3406
+
3407
+ // Helper function to generate a unique class name
3408
+ const generateClassName$1 = (base) => `${base}-${Math.random().toString(36).substr(2, 9)}`;
3409
+ // Helper function to convert camelCased properties to hyphenated CSS properties
3410
+ const convertStylesToCSS$1 = (className, styles) => {
3411
+ let cssString = `.${className} {`;
3412
+ for (const key in styles) {
3413
+ if (typeof styles[key] === "object" && key.startsWith("@media")) {
3414
+ const mediaStyles = convertStylesToCSS$1(className, styles[key]);
3415
+ cssString += `${key} { ${mediaStyles} }`;
3416
+ }
3417
+ else if (key.startsWith("&:")) {
3418
+ const pseudoClass = key.replace("&", "");
3419
+ cssString += `${pseudoClass} { ${convertStylesToCSS$1("", styles[key])} }`;
3420
+ }
3421
+ else {
3422
+ const cssKey = key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
3423
+ cssString += `${cssKey}: ${styles[key]}; `;
3424
+ }
3425
+ }
3426
+ cssString += "}";
3427
+ return cssString;
3428
+ };
3429
+ // Custom hook for dynamic styles with generics
3430
+ const useDynamicStyles$1 = (stylesObj) => {
3431
+ const [classNames, setClassNames] = useState({});
3432
+ useEffect(() => {
3433
+ const convertedStyles = Object.keys(stylesObj).map((key) => {
3434
+ const className = generateClassName$1(key);
3435
+ const styleElement = document.createElement("style");
3436
+ styleElement.innerHTML = convertStylesToCSS$1(className, stylesObj[key]);
3437
+ document.head.appendChild(styleElement);
3438
+ return {
3439
+ key,
3440
+ className,
3441
+ styleElement,
3442
+ };
3443
+ });
3444
+ setClassNames(convertedStyles.reduce((classNameEntity, convertedStyle) => {
3445
+ return {
3446
+ ...classNameEntity,
3447
+ [convertedStyle.key]: convertedStyle.className,
3448
+ };
3449
+ }, {}));
3450
+ return () => {
3451
+ convertedStyles.forEach((convertedStyle) => {
3452
+ document.head.removeChild(convertedStyle.styleElement);
3453
+ });
3454
+ };
3455
+ }, []);
3456
+ return classNames;
3457
+ };
3458
+
3459
+ const useCurrentModal$1 = () => {
3460
+ const [CurrentModal, setCurrentModal] = useState();
3461
+ return [
3462
+ CurrentModal,
3463
+ (Modal) => {
3464
+ // As setState supports functional updates, we can't pass functional
3465
+ // components directly
3466
+ setCurrentModal(() => Modal);
3467
+ },
3468
+ ];
3469
+ };
3470
+ const ContextMenu$1 = (params) => {
3471
+ const { onClose, onMenuClick, anchorRef, dropDownOptions } = params;
3472
+ const [CurrentModal, setCurrentModal] = useCurrentModal$1();
3473
+ const styles = useDynamicStyles$1(dropdownStyles$1);
3474
+ return (React__default.createElement(React__default.Fragment, null,
3475
+ React__default.createElement(Layer$1, { onBackdropClick: (event, data) => onClose(event, data), className: styles.layer },
3476
+ React__default.createElement(Popper, { reference: anchorRef, placement: "bottom-start" },
3477
+ React__default.createElement(FlyoutMenu, null, dropDownOptions.map((dropDownOption, index) => (React__default.createElement(MenuItem$1, { key: index, destructive: dropDownOption.destructive, label: dropDownOption.label, icon: dropDownOption.icon, onClick: () => {
3478
+ onMenuClick(dropDownOption);
3479
+ onClose();
3480
+ }, dense: true })))))),
3481
+ CurrentModal && (React__default.createElement(CurrentModal, { onClose: () => {
3482
+ onClose();
3483
+ setCurrentModal(null);
3484
+ } }))));
3485
+ };
3486
+ const DropdownMenu$1 = (props) => {
3487
+ const ref = useRef();
3488
+ const [visible, setVisible] = useState(false);
3489
+ const { dropdownOptions, onClick } = props;
3490
+ return (React__default.createElement("div", { ref: ref, style: { display: 'inline-block' } },
3491
+ React__default.createElement(Button$1, { small: true, secondary: true, icon: React__default.createElement(IconMore24, { color: colors$1.grey600 }), onClick: () => setVisible(true) }),
3492
+ visible && (React__default.createElement(ContextMenu$1, { dropDownOptions: dropdownOptions, anchorRef: ref, onClose: () => setVisible(false), onMenuClick: (dropDownOption) => {
3493
+ onClick(dropDownOption);
3494
+ } }))));
3495
+ };
3496
+
3497
+ // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3498
+ // Use of this source code is governed by a BSD-style
3499
+ // license that can be found in the LICENSE file.
3500
+ const DataTableActions = (props) => {
3501
+ const { data, actionOptions, actionOptionOrientation, onClick } = props;
3502
+ switch (actionOptionOrientation) {
3503
+ case 'BUTTON':
3504
+ 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 : '')))));
3505
+ case 'DROPDOWN':
3506
+ return (React__default.createElement(DropdownMenu$1, { dropdownOptions: actionOptions, onClick: (option) => {
3507
+ onClick(option);
3508
+ } }));
3509
+ case 'LINK':
3510
+ return (React__default.createElement("div", { style: {
3511
+ display: 'flex',
3512
+ gap: 16,
3513
+ alignItems: 'center',
3514
+ } }, actionOptions.map((option) => (React__default.createElement("a", { style: {
3515
+ cursor: 'pointer',
3516
+ textDecoration: 'underline',
3517
+ fontSize: 14,
3518
+ display: 'flex',
3519
+ alignItems: 'center',
3520
+ gap: 4,
3521
+ color: option.destructive ? colors$1.red700 : colors$1.grey900,
3522
+ }, key: option.label, onClick: (event) => {
3523
+ event.stopPropagation();
3524
+ onClick(option);
3525
+ } },
3526
+ option.icon ? React__default.createElement(option.icon, null) : React__default.createElement(React__default.Fragment, null),
3527
+ !option.iconOnly ? React__default.createElement("span", null, option.label) : React__default.createElement(React__default.Fragment, null))))));
3528
+ default:
3529
+ return React__default.createElement(React__default.Fragment, null);
3530
+ }
3531
+ };
3532
+
3533
+ // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3534
+ // Use of this source code is governed by a BSD-style
3535
+ // license that can be found in the LICENSE file.
3536
+
3537
+ const TableCell = ({ cell, getTextColorFromBackGround, }) => {
3538
+ if (cell?.style && cell?.style !== 'default-value') {
3539
+ return (React__default.createElement(DataTableCell, null,
3540
+ React__default.createElement("div", { style: { display: 'flex', justifyContent: 'center' } },
3541
+ React__default.createElement("span", { style: {
3542
+ backgroundColor: cell.style,
3543
+ display: 'inline-flex',
3544
+ alignItems: 'center',
3545
+ fontWeight: 'lighter',
3546
+ paddingTop: 4,
3547
+ paddingBottom: 4,
3548
+ paddingLeft: 8,
3549
+ paddingRight: 8,
3550
+ borderRadius: 3,
3551
+ fontSize: 12,
3552
+ color: getTextColorFromBackGround(cell.style),
3553
+ } }, cell.value))));
3554
+ }
3555
+ return (React__default.createElement(DataTableCell, null,
3556
+ React__default.createElement("div", { className: "text-sm text-gray-800" }, cell?.value || '-')));
3557
+ };
3558
+
3559
+ // export const TableRow = ({
3560
+ // row,
3561
+ // columns,
3562
+ // getTextColorFromBackGround,
3563
+ // actionOptions,
3564
+ // actionOptionOrientation,
3565
+ // actionSelected,
3566
+ // }: any) => {
3567
+ // const [isChecked, setIsChecked] = useState(false);
3568
+ // const handleCheckBoxChange = () => {
3569
+ // const newState = !isChecked;
3570
+ // setIsChecked(newState);
3571
+ // console.log('Row selected:', row, 'Checked:', newState);
3572
+ // };
3573
+ // return (
3574
+ // <DataTableRow key={row.index.value}>
3575
+ // <DataTableCell width="48px">
3576
+ // <Checkbox
3577
+ // onChange={handleCheckBoxChange}
3578
+ // value="id_1"
3579
+ // checked={isChecked}
3580
+ // />
3581
+ // </DataTableCell>
3582
+ // {columns.map((col: any) => {
3583
+ // if (col.key === 'actions') {
3584
+ // return (
3585
+ // <DataTableCell key={col.key}>
3586
+ // {actionOptions && (
3587
+ // <DataTableActions
3588
+ // actionOptions={actionOptions}
3589
+ // actionOptionOrientation={actionOptionOrientation}
3590
+ // onClick={(option) => {
3591
+ // const data = row['responseData']?.['value'];
3592
+ // if (option.onClick) option.onClick(data);
3593
+ // actionSelected.emit({
3594
+ // action: option.label,
3595
+ // data,
3596
+ // });
3597
+ // }}
3598
+ // />
3599
+ // )}
3600
+ // </DataTableCell>
3601
+ // );
3602
+ // }
3603
+ // return (
3604
+ // <TableCell
3605
+ // key={col.key}
3606
+ // cell={row[col.key]}
3607
+ // getTextColorFromBackGround={getTextColorFromBackGround}
3608
+ // />
3609
+ // );
3610
+ // })}
3611
+ // </DataTableRow>
3612
+ // );
3613
+ // };
3614
+ const TableRow = ({ row, columns, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, isChecked, onToggle, selectable, }) => {
3615
+ const handleCheckBoxChange = () => {
3616
+ onToggle(row);
3617
+ };
3618
+ return (React__default.createElement(DataTableRow, { key: row.index.value, selected: isChecked },
3619
+ selectable && (React__default.createElement(DataTableCell, { width: "48px" },
3620
+ React__default.createElement(Checkbox, { onChange: handleCheckBoxChange, checked: isChecked }))),
3621
+ columns.map((col) => {
3622
+ if (col.key === 'actions') {
3623
+ return (React__default.createElement(DataTableCell, { key: col.key }, actionOptions && (React__default.createElement(DataTableActions, { actionOptions: actionOptions, data: row, actionOptionOrientation: actionOptionOrientation, onClick: (option) => {
3624
+ const data = row['responseData']?.['value'];
3625
+ if (option.onClick)
3626
+ option.onClick(data);
3627
+ actionSelected.emit({
3628
+ action: option.label,
3629
+ data,
3630
+ });
3631
+ } }))));
3651
3632
  }
3652
- 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) => {
3653
- setSelectedOrgUnit(event);
3654
- setShowOrgUnitTree(false);
3655
- onSelectOrgUnit(event);
3656
- } })));
3657
- }
3658
- 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) => {
3659
- setSelectedOrgUnit(event);
3660
- setShowOrgUnitTree(false);
3661
- onSelectOrgUnit(event);
3662
- } }));
3633
+ return (React__default.createElement(TableCell, { key: col.key, cell: row[col.key], getTextColorFromBackGround: getTextColorFromBackGround }));
3634
+ })));
3635
+ };
3636
+
3637
+ // export const TableBody = ({
3638
+ // data,
3639
+ // columns,
3640
+ // getTextColorFromBackGround,
3641
+ // actionOptions,
3642
+ // actionOptionOrientation,
3643
+ // actionSelected,
3644
+ // }: any) => (
3645
+ // <DHISTableBody>
3646
+ // {data.length > 0 ? (
3647
+ // data.map((row: any) => (
3648
+ // <TableRow
3649
+ // key={row.index.value}
3650
+ // row={row}
3651
+ // columns={columns}
3652
+ // getTextColorFromBackGround={getTextColorFromBackGround}
3653
+ // actionOptions={actionOptions}
3654
+ // actionOptionOrientation={actionOptionOrientation}
3655
+ // actionSelected={actionSelected}
3656
+ // />
3657
+ // ))
3658
+ // ) : (
3659
+ // <DataTableRow>
3660
+ // <DataTableCell
3661
+ // colSpan={columns.length.toString()}
3662
+ // style={{
3663
+ // textAlign: 'center',
3664
+ // fontWeight: 'bold',
3665
+ // color: 'grey',
3666
+ // padding: '20px',
3667
+ // }}
3668
+ // >
3669
+ // No data found
3670
+ // </DataTableCell>
3671
+ // </DataTableRow>
3672
+ // )}
3673
+ // </DHISTableBody>
3674
+ // );
3675
+ const TableBody = ({ data, columns, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, selectedRows, onRowToggle, selectable, }) => (React__default.createElement(TableBody$1, null, data.length > 0 ? (data.map((row) => (React__default.createElement(TableRow, { key: row.index.value, row: row, columns: columns, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, actionSelected: actionSelected, isChecked: selectedRows.some((r) => r.index?.value === row.index?.value), onToggle: onRowToggle, selectable: selectable })))) : (React__default.createElement(DataTableRow, null,
3676
+ React__default.createElement(DataTableCell, { colSpan: columns.length.toString(), style: {
3677
+ textAlign: 'center',
3678
+ fontWeight: 'bold',
3679
+ color: 'grey',
3680
+ padding: '20px',
3681
+ } }, "No data found")))));
3682
+
3683
+ const Pagination = ({ pager, setPager }) => {
3684
+ if (!pager || pager.page === undefined || pager.pageSize === undefined) {
3685
+ return null; //skip rendering until valid
3686
+ }
3687
+ return (React__default.createElement(Pagination$1, { page: pager.page, pageCount: pager.pageCount, pageSize: pager.pageSize, total: pager.total, onPageChange: (page) => setPager((prev) => new Pager({ ...prev, page })), onPageSizeChange: (pageSize) => setPager((prev) => new Pager({
3688
+ ...prev,
3689
+ pageSize: Number(pageSize),
3690
+ page: 1,
3691
+ })), pageSizes: ['10', '20', '50', '100', '500'] }));
3692
+ };
3693
+
3694
+ const TableFooter = ({ pager, setPager, columns }) => {
3695
+ return (React__default.createElement(TableFoot, null,
3696
+ React__default.createElement(DataTableRow, null,
3697
+ React__default.createElement(DataTableCell, { colSpan: columns.length.toString() },
3698
+ React__default.createElement(Pagination, { pager: pager, setPager: setPager })))));
3699
+ };
3700
+
3701
+ // import { DataTable } from '@dhis2/ui';
3702
+ // import React from 'react';
3703
+ // import { TableHeader } from './tableHeader';
3704
+ // //import { TableBody } from './TableBody';
3705
+ // import { TableFooter } from './tableFooter';
3706
+ // import { TableBody } from './tableBody';
3707
+ // export const LineListTable = ({
3708
+ // columns,
3709
+ // data,
3710
+ // pager,
3711
+ // setPager,
3712
+ // getTextColorFromBackGround,
3713
+ // actionOptions,
3714
+ // actionOptionOrientation,
3715
+ // actionSelected,
3716
+ // }: any) => {
3717
+ // return (
3718
+ // <DataTable>
3719
+ // <TableHeader columns={columns} data={data} />
3720
+ // <TableBody
3721
+ // data={data}
3722
+ // columns={columns}
3723
+ // getTextColorFromBackGround={getTextColorFromBackGround}
3724
+ // actionOptions={actionOptions}
3725
+ // actionOptionOrientation={actionOptionOrientation}
3726
+ // actionSelected={actionSelected}
3727
+ // />
3728
+ // <TableFooter columns={columns} pager={pager} setPager={setPager} />
3729
+ // </DataTable>
3730
+ // );
3731
+ // };
3732
+ const LineListTable = ({ columns, data, pager, setPager, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, selectable, rowsSelected, }) => {
3733
+ const [selectedRows, setSelectedRows] = useState([]);
3734
+ const handleRowToggle = (row) => {
3735
+ const exists = selectedRows.find((r) => r.index?.value === row.index?.value);
3736
+ const updatedRows = exists
3737
+ ? selectedRows.filter((r) => r.index?.value !== row.index?.value)
3738
+ : [...selectedRows, row];
3739
+ setSelectedRows(updatedRows);
3740
+ rowsSelected.emit(updatedRows.map((row) => row['responseData']?.value));
3663
3741
  };
3664
- const handleBlur = () => {
3665
- // onBlur && onBlur(null);
3742
+ const handleSelectAll = (checked) => {
3743
+ const updatedRows = checked ? data : [];
3744
+ setSelectedRows(updatedRows);
3745
+ rowsSelected.emit(updatedRows);
3666
3746
  };
3667
- return (config && (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false },
3668
- React__default.createElement("div", null,
3669
- label && (React__default.createElement("div", { className: classes.orgUnitFieldLabel },
3670
- React__default.createElement("span", null, label),
3671
- required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
3672
- !showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
3673
- React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
3674
- React__default.createElement(Chip, { onRemove: () => {
3675
- setShowOrgUnitTree(true);
3676
- } }, selectedOrgUnit.displayName)))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3677
- React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
3678
- React__default.createElement("div", { className: classes.debounceFieldContainer },
3679
- React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
3680
- loading ? (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3681
- React__default.createElement(CircularLoader$1, { small: true }))) : (React__default.createElement("div", { className: classes.orgUnitTreeContainer, style: { maxHeight: '200px', overflowY: 'auto' } }, renderOrgUnitTree()))))))));
3747
+ return (React__default.createElement(DataTable, null,
3748
+ React__default.createElement(TableHeader, { columns: columns, allSelected: selectedRows.length === data.length && data.length > 0, onSelectAll: handleSelectAll, selectable: selectable }),
3749
+ React__default.createElement(TableBody, { data: data, columns: columns, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, actionSelected: actionSelected, selectedRows: selectedRows, onRowToggle: handleRowToggle, selectable: selectable }),
3750
+ React__default.createElement(TableFooter, { columns: columns, pager: pager, setPager: setPager })));
3682
3751
  };
3683
3752
 
3684
- const OrgUnitSelector = ({ hide, setHide, selectedOrgUnit, setSelectedOrgUnit, setOrgUnitState, }) => (React__default.createElement(Modal$1, { hide: hide, position: "middle" },
3685
- React__default.createElement(ModalTitle$1, null, "Select organization unit"),
3686
- React__default.createElement(ModalContent$1, null,
3687
- React__default.createElement(OrgUnitFormField$1, { key: selectedOrgUnit, onSelectOrgUnit: (selectedOrgUnit) => {
3688
- setSelectedOrgUnit(selectedOrgUnit.displayName);
3689
- setOrgUnitState(selectedOrgUnit.id);
3690
- setHide(true);
3691
- } })),
3692
- React__default.createElement(ModalActions$1, null,
3693
- React__default.createElement(ButtonStrip$1, { end: true },
3694
- React__default.createElement(Button$1, { onClick: () => setHide(true), secondary: true }, "Close")))));
3753
+ class LineListService {
3754
+ constructor(httpClient) {
3755
+ this.httpClient = httpClient;
3756
+ }
3757
+ /**
3758
+ * Fetch orgUnit names for given orgUnit IDs
3759
+ */
3760
+ fetchOrgUnits(orgUnitIds) {
3761
+ const idsQuery = `filter=id:in:[${orgUnitIds}]`;
3762
+ return this.httpClient
3763
+ .get(`organisationUnits.json?fields=id,name&paging=false&${idsQuery}`)
3764
+ .pipe(map$1((response) => {
3765
+ const orgUnitsMap = new Map();
3766
+ response.organisationUnits.forEach((orgUnit) => {
3767
+ orgUnitsMap.set(orgUnit.id, orgUnit.name);
3768
+ });
3769
+ return orgUnitsMap;
3770
+ }));
3771
+ }
3772
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListService, deps: [{ token: i1.NgxDhis2HttpClientService }], target: i0.ɵɵFactoryTarget.Injectable }); }
3773
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListService }); }
3774
+ }
3775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListService, decorators: [{
3776
+ type: Injectable
3777
+ }], ctorParameters: () => [{ type: i1.NgxDhis2HttpClientService }] });
3778
+
3779
+ const getTrackedEntityTableData = (response, programId, pager, metaData) => {
3780
+ const teisRaw = response.data
3781
+ .trackedEntityInstances;
3782
+ const teis = Array.isArray(teisRaw)
3783
+ ? teisRaw
3784
+ : [teisRaw];
3785
+ const orgUnitLabel = metaData.orgUnitLabel;
3786
+ const orgUnitMap = response.data
3787
+ .orgUnitsMap;
3788
+ const attributeColumns = metaData.displayInListTrackedEntityAttributes
3789
+ .sort((a, b) => a.sortOrder - b.sortOrder)
3790
+ .map((attr) => ({
3791
+ label: attr.name,
3792
+ key: attr.id,
3793
+ }));
3794
+ const dataElementColumns = metaData.displayInListDataElements
3795
+ .sort((a, b) => a.sortOrder - b.sortOrder)
3796
+ .map((element) => ({
3797
+ label: element.name,
3798
+ key: element.id,
3799
+ }));
3800
+ const dataElementOptions = metaData.displayInListDataElements.map((element) => ({
3801
+ id: element.id,
3802
+ options: element.optionSet?.options.map((opt) => ({
3803
+ name: opt.name,
3804
+ color: opt.style?.color,
3805
+ })),
3806
+ }));
3807
+ const tableColumns = [
3808
+ {
3809
+ label: orgUnitLabel || 'registering unit',
3810
+ key: 'orgUnit',
3811
+ },
3812
+ ...attributeColumns,
3813
+ ...dataElementColumns,
3814
+ ];
3815
+ const tableFilters = metaData.searchableTrackedEntityAttributes
3816
+ .sort((a, b) => a.sortOrder - b.sortOrder)
3817
+ .map((attr) => ({
3818
+ label: attr.name,
3819
+ key: attr.id,
3820
+ valueType: attr.valueType,
3821
+ options: attr.optionSet ?? undefined,
3822
+ }));
3823
+ const tableData = teis.map((tei, idx) => {
3824
+ const row = {
3825
+ trackedEntityInstance: { value: tei.trackedEntity },
3826
+ index: { value: (pager.page - 1) * pager.pageSize + idx + 1 },
3827
+ };
3828
+ const matchingEnrollment = tei.latestEnrollment;
3829
+ let attributesData = matchingEnrollment.attributes;
3830
+ const dataElementsData = matchingEnrollment.events.flatMap((event) => event.dataValues);
3831
+ attributesData = attributesData.map((attr) => {
3832
+ if (attr?.valueType?.toLowerCase() === 'date') {
3833
+ try {
3834
+ return {
3835
+ ...attr,
3836
+ value: format(parse$1(attr.value, 'yyyy-MM-dd', new Date()), 'dd/MM/yyyy'),
3837
+ };
3838
+ }
3839
+ catch {
3840
+ return { ...attr }; // Leave value as is on parse failure
3841
+ }
3842
+ }
3843
+ return attr;
3844
+ });
3845
+ attributesData.forEach((attr) => {
3846
+ row[attr.attribute] = { value: attr.value };
3847
+ });
3848
+ dataElementsData.forEach((element) => {
3849
+ // Find the matching data element in dataElementOptions by ID
3850
+ const dataElementOption = dataElementOptions.find((deo) => deo.id === element.dataElement);
3851
+ // find a matching option within that data element's options
3852
+ const matchingOption = dataElementOption?.options?.find((opt) => opt.name === element.value);
3853
+ // Build the row entry with value and optionally style
3854
+ if (matchingOption) {
3855
+ row[element.dataElement] = {
3856
+ value: element.value,
3857
+ style: matchingOption.color,
3858
+ };
3859
+ }
3860
+ else {
3861
+ row[element.dataElement] = {
3862
+ value: element.value,
3863
+ };
3864
+ }
3865
+ });
3866
+ // Include orgUnit in the row for id access with style
3867
+ row['orgUnitId'] = { value: matchingEnrollment.orgUnit };
3868
+ row['orgUnit'] = {
3869
+ value: orgUnitMap?.get(matchingEnrollment.orgUnit) || '-',
3870
+ };
3871
+ row['responseData'] = { value: tei.toObject() };
3872
+ return row;
3873
+ });
3874
+ return {
3875
+ columns: tableColumns,
3876
+ data: tableData,
3877
+ filteredEntityColumns: tableFilters,
3878
+ orgUnitLabel: orgUnitLabel,
3879
+ };
3880
+ };
3881
+ const addActionsColumn = (columns, actionOptions) => {
3882
+ return [
3883
+ ...columns,
3884
+ ...(actionOptions && actionOptions.length > 0
3885
+ ? [{ label: 'Actions', key: 'actions' }]
3886
+ : []),
3887
+ ];
3888
+ };
3695
3889
 
3696
3890
  // src/app/line-list-table.component.ts
3697
3891
  class LineListTableComponent extends ReactWrapperModule {
@@ -3702,8 +3896,9 @@ class LineListTableComponent extends ReactWrapperModule {
3702
3896
  this.filterRootOrgUnit = false;
3703
3897
  this.showFilters = false;
3704
3898
  this.isOptionSetNameVisible = false;
3899
+ this.allowRowsSelection = false;
3705
3900
  this.actionSelected = new EventEmitter();
3706
- this.approvalSelected = new EventEmitter();
3901
+ this.rowsSelected = new EventEmitter();
3707
3902
  this.reactStateUpdaters = null;
3708
3903
  this.setReactStateUpdaters = (updaters) => {
3709
3904
  this.reactStateUpdaters = updaters;
@@ -3741,6 +3936,7 @@ class LineListTableComponent extends ReactWrapperModule {
3741
3936
  const [prevValue, setPrevValue] = useState();
3742
3937
  const [dateStates, setDateStates] = useState({});
3743
3938
  const [metaData, setMetaData] = useState(null);
3939
+ const [selectable, setSelectable] = useState(this.allowRowsSelection);
3744
3940
  const d2 = window.d2Web;
3745
3941
  // Store updaters in refs for Angular to access
3746
3942
  const updateRefs = useRef({
@@ -3751,6 +3947,7 @@ class LineListTableComponent extends ReactWrapperModule {
3751
3947
  setStartDateState,
3752
3948
  setEndDateState,
3753
3949
  setOptionSetNameVisible,
3950
+ setSelectable,
3754
3951
  });
3755
3952
  useEffect(() => {
3756
3953
  this.setReactStateUpdaters?.(updateRefs.current);
@@ -3933,7 +4130,7 @@ class LineListTableComponent extends ReactWrapperModule {
3933
4130
  } }, "Loading"))) : (React__default.createElement("div", null,
3934
4131
  React__default.createElement(OrgUnitSelector, { hide: hide, setHide: setHide, selectedOrgUnit: selectedOrgUnit, setSelectedOrgUnit: setSelectedOrgUnit, setOrgUnitState: setOrgUnitState }),
3935
4132
  this.showFilters && (React__default.createElement(FilterToolbar, { orgUnitLabel: orgUnitLabel, selectedOrgUnit: selectedOrgUnit, setSelectedOrgUnit: setSelectedOrgUnit, setOrgUnitState: setOrgUnitState, defaultOrgUnit: defaultOrgUnit, setHide: setHide, startDateState: startDateState, setStartDateState: setStartDateState, endDateState: endDateState, setEndDateState: setEndDateState, visibleFilters: visibleFilters, dateStates: dateStates, inputValues: inputValues, setInputValues: setInputValues, handleInputChange: handleInputChange, handleInputChangeForSelectField: handleInputChangeForSelectField, handleDateSelect: handleDateSelect, prevValue: prevValue, setPrevValue: setPrevValue, showAllFilters: showAllFilters, setShowAllFilters: setShowAllFilters })),
3936
- React__default.createElement(LineListTable, { columns: columns, data: data, pager: pager, setPager: setPager, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: this.actionOptions, actionOptionOrientation: this.actionOptionOrientation, actionSelected: this.actionSelected })))));
4133
+ React__default.createElement(LineListTable, { columns: columns, data: data, pager: pager, setPager: setPager, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: this.actionOptions, actionOptionOrientation: this.actionOptionOrientation, actionSelected: this.actionSelected, selectable: selectable, rowsSelected: this.rowsSelected })))));
3937
4134
  };
3938
4135
  }
3939
4136
  ngOnChanges(changes) {
@@ -3962,6 +4159,9 @@ class LineListTableComponent extends ReactWrapperModule {
3962
4159
  if (changes['isButtonLoading']) {
3963
4160
  this.reactStateUpdaters.setIsButtonLoading(this.isButtonLoading);
3964
4161
  }
4162
+ if (changes['isSelectable']) {
4163
+ this.reactStateUpdaters.setIsButtonLoading(this.allowRowsSelection);
4164
+ }
3965
4165
  }
3966
4166
  }
3967
4167
  async ngAfterViewInit() {
@@ -3972,11 +4172,11 @@ class LineListTableComponent extends ReactWrapperModule {
3972
4172
  this.render();
3973
4173
  }
3974
4174
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListTableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3975
- 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", dataQueryFilters: "dataQueryFilters", ouMode: "ouMode", isButtonLoading: "isButtonLoading", buttonFilter: "buttonFilter", filterRootOrgUnit: "filterRootOrgUnit", showFilters: "showFilters", isOptionSetNameVisible: "isOptionSetNameVisible" }, outputs: { actionSelected: "actionSelected", approvalSelected: "approvalSelected" }, 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 [data-test=calendar-clear-button]{background-color:#f2f2f2!important;color:#870808!important;border-radius:6px!important;padding:4px 10px!important;font-size:14px!important}::ng-deep .custom-input [data-test=calendar-clear-button]:hover{background-color:#ddd}::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}::ng-deep .custom-select-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-select-input div{margin:0!important}::ng-deep .custom-select-input [data-test=dhis2-uiwidgets-singleselectfield-label]{font-size:12px;color:gray!important}::ng-deep .custom-select-input [data-test=dhis2-uicore-select-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-select-input [data-test=dhis2-uicore-select-input]:focus-within{box-shadow:none!important}::ng-deep .custom-select-input input:focus{border:none!important;box-shadow:none!important}\n"] }); }
4175
+ 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", dataQueryFilters: "dataQueryFilters", ouMode: "ouMode", isButtonLoading: "isButtonLoading", buttonFilter: "buttonFilter", filterRootOrgUnit: "filterRootOrgUnit", showFilters: "showFilters", isOptionSetNameVisible: "isOptionSetNameVisible", allowRowsSelection: "allowRowsSelection" }, outputs: { actionSelected: "actionSelected", rowsSelected: "rowsSelected" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: ["@charset \"UTF-8\";::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 [data-test=calendar-clear-button]{background-color:#f2f2f2!important;color:#870808!important;border-radius:6px!important;padding:4px 10px!important;font-size:0!important}::ng-deep .custom-input [data-test=calendar-clear-button]:before{content:\"\\2715\";font-size:14px;color:#870808}::ng-deep .custom-input [data-test=calendar-clear-button]:hover{background-color:#ddd}::ng-deep .calendar-input-wrapper{position:relative}::ng-deep .calendar-input-wrapper .custom-input{position:relative;width:100%;display:flex;align-items:center}::ng-deep .calendar-input-wrapper [data-test=calendar-clear-button]{right:8px;bottom:14px;margin:auto;display:flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:0!important;background-color:#a0adba!important;border-radius:50%;padding:2px;cursor:pointer}::ng-deep .calendar-input-wrapper [data-test=calendar-clear-button]:before{content:\"\\2715\";font-size:10px;color:#f0f0f0}::ng-deep .calendar-input-wrapper input{padding-right:40px!important;height:40px;line-height:40px;box-sizing:border-box}::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}::ng-deep .custom-select-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-select-input div{margin:0!important}::ng-deep .custom-select-input [data-test=dhis2-uiwidgets-singleselectfield-label]{font-size:12px;color:gray!important}::ng-deep .custom-select-input [data-test=dhis2-uicore-select-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-select-input [data-test=dhis2-uicore-select-input]:focus-within{box-shadow:none!important}::ng-deep .custom-select-input input:focus{border:none!important;box-shadow:none!important}\n"] }); }
3976
4176
  }
3977
4177
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListTableComponent, decorators: [{
3978
4178
  type: Component,
3979
- 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 [data-test=calendar-clear-button]{background-color:#f2f2f2!important;color:#870808!important;border-radius:6px!important;padding:4px 10px!important;font-size:14px!important}::ng-deep .custom-input [data-test=calendar-clear-button]:hover{background-color:#ddd}::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}::ng-deep .custom-select-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-select-input div{margin:0!important}::ng-deep .custom-select-input [data-test=dhis2-uiwidgets-singleselectfield-label]{font-size:12px;color:gray!important}::ng-deep .custom-select-input [data-test=dhis2-uicore-select-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-select-input [data-test=dhis2-uicore-select-input]:focus-within{box-shadow:none!important}::ng-deep .custom-select-input input:focus{border:none!important;box-shadow:none!important}\n"] }]
4179
+ args: [{ selector: 'ng-dhis2-ui-line-list', template: '<ng-content></ng-content>', standalone: false, styles: ["@charset \"UTF-8\";::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 [data-test=calendar-clear-button]{background-color:#f2f2f2!important;color:#870808!important;border-radius:6px!important;padding:4px 10px!important;font-size:0!important}::ng-deep .custom-input [data-test=calendar-clear-button]:before{content:\"\\2715\";font-size:14px;color:#870808}::ng-deep .custom-input [data-test=calendar-clear-button]:hover{background-color:#ddd}::ng-deep .calendar-input-wrapper{position:relative}::ng-deep .calendar-input-wrapper .custom-input{position:relative;width:100%;display:flex;align-items:center}::ng-deep .calendar-input-wrapper [data-test=calendar-clear-button]{right:8px;bottom:14px;margin:auto;display:flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:0!important;background-color:#a0adba!important;border-radius:50%;padding:2px;cursor:pointer}::ng-deep .calendar-input-wrapper [data-test=calendar-clear-button]:before{content:\"\\2715\";font-size:10px;color:#f0f0f0}::ng-deep .calendar-input-wrapper input{padding-right:40px!important;height:40px;line-height:40px;box-sizing:border-box}::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}::ng-deep .custom-select-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-select-input div{margin:0!important}::ng-deep .custom-select-input [data-test=dhis2-uiwidgets-singleselectfield-label]{font-size:12px;color:gray!important}::ng-deep .custom-select-input [data-test=dhis2-uicore-select-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-select-input [data-test=dhis2-uicore-select-input]:focus-within{box-shadow:none!important}::ng-deep .custom-select-input input:focus{border:none!important;box-shadow:none!important}\n"] }]
3980
4180
  }], propDecorators: { programId: [{
3981
4181
  type: Input
3982
4182
  }], orgUnit: [{
@@ -4009,9 +4209,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
4009
4209
  type: Input
4010
4210
  }], isOptionSetNameVisible: [{
4011
4211
  type: Input
4212
+ }], allowRowsSelection: [{
4213
+ type: Input
4012
4214
  }], actionSelected: [{
4013
4215
  type: Output
4014
- }], approvalSelected: [{
4216
+ }], rowsSelected: [{
4015
4217
  type: Output
4016
4218
  }] } });
4017
4219
 
@@ -5098,6 +5300,7 @@ class FormMetaData {
5098
5300
  code: 'orgUnit',
5099
5301
  required: true,
5100
5302
  controlType: 'org-unit',
5303
+ isOrgUnit: true,
5101
5304
  }),
5102
5305
  ],
5103
5306
  },
@@ -5520,10 +5723,9 @@ const OrgUnitFormField = (props) => {
5520
5723
  React__default.createElement("span", null, label),
5521
5724
  required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
5522
5725
  !showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
5523
- React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
5524
- React__default.createElement(Chip, { onRemove: () => {
5525
- setShowOrgUnitTree(true);
5526
- } }, selectedOrgUnit.displayName)))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
5726
+ React__default.createElement(Tooltip, { content: selectedOrgUnitLabel }, disabled ? (React__default.createElement(Chip, null, selectedOrgUnit.displayName)) : (React__default.createElement(Chip, { onRemove: () => {
5727
+ setShowOrgUnitTree(true);
5728
+ } }, selectedOrgUnit.displayName))))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
5527
5729
  React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
5528
5730
  React__default.createElement("div", { className: classes.debounceFieldContainer },
5529
5731
  React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
@@ -5593,20 +5795,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
5593
5795
  checkValueUniqueness();
5594
5796
  }
5595
5797
  }, [this.isValueAssigned()]);
5596
- // TODO: START: Improve the approach of handling observables
5597
- // useEffect(() => {
5598
- // const fieldErrorSubscription = this.fieldError$
5599
- // .pipe(filter((error) => error !== initialError))
5600
- // .subscribe({
5601
- // next: (error: string | undefined) => {
5602
- // setInitialError(error);
5603
- // },
5604
- // });
5605
- // return () => {
5606
- // fieldErrorSubscription.unsubscribe();
5607
- // };
5608
- // });
5609
- // TODO: END: Improve the approach of handling observables
5798
+ // TODO: Review error handling as take() has potential to missed any other updated error information
5610
5799
  useEffect(() => {
5611
5800
  const fieldErrorSubscription = this.fieldError$
5612
5801
  .pipe(filter((error) => error !== initialError), take(1) // Take only the first emitted value, then unsubscribe
@@ -5670,7 +5859,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
5670
5859
  const formFieldContent = () => {
5671
5860
  switch (this.field().controlType) {
5672
5861
  case 'textarea':
5673
- return (React__default.createElement(TextAreaField, { error: hasError, validationText: validationError, inputWidth: this.fieldConfig()?.inputWidth, required: this.field().required, name: this.field().id, label: this.label(), rows: 5, placeholder: this.placeholder(), value: value, onChange: (event) => {
5862
+ return (React__default.createElement(TextAreaField, { error: hasError, validationText: validationError, inputWidth: this.fieldConfig()?.inputWidth, required: this.field().required, name: this.field().id, disabled: disabled, label: this.label(), rows: 5, placeholder: this.placeholder(), value: value, onChange: (event) => {
5674
5863
  this.ngZone.run(() => {
5675
5864
  (this.form().get(this.field().id) ||
5676
5865
  this.form().get(this.field().key))?.setValue(event.value);
@@ -5688,7 +5877,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
5688
5877
  });
5689
5878
  } }));
5690
5879
  case 'org-unit':
5691
- return (React__default.createElement(OrgUnitFormField, { label: this.label(), key: this.field().id, required: this.field().required, onSelectOrgUnit: (selectedOrgUnit) => {
5880
+ return (React__default.createElement(OrgUnitFormField, { label: this.label(), key: this.field().id, required: this.field().required, disabled: disabled, onSelectOrgUnit: (selectedOrgUnit) => {
5692
5881
  this.ngZone.run(() => {
5693
5882
  (this.form().get(this.field().id) ||
5694
5883
  this.form().get(this.field().key))?.setValue(selectedOrgUnit);
@@ -6435,11 +6624,11 @@ class FlatFormComponent extends BaseFormWrapperComponent {
6435
6624
  this.updateFormValidity(this.formGroup.valid);
6436
6625
  }
6437
6626
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FlatFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
6438
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.8", type: FlatFormComponent, isStandalone: false, selector: "ng-dhis2-ui-flat-form", usesInheritance: true, ngImport: i0, template: "<!-- <ng-dhis2-ui-form\n*ngIf=\"fieldGroup.fields.length > 0\"\n[fields]=\"fieldGroup.fields\"\n[form]=\"formGroup\"\n[dataEntities]=\"dataValueEntities()\"\n[programRuleActions]=\"ruleActions()\"\n[isFormHorizontal]=\"fieldGroup.isFormHorizontal || false\"\n(formUpdate)=\"onFormUpdate($event, fieldGroup.id)\"\n></ng-dhis2-ui-form> -->\n\n<ng-dhis2-ui-form\n [fields]=\"fields()\"\n [form]=\"formGroup\"\n [dataEntities]=\"dataValues()\"\n [programRuleActions]=\"ruleActions()\"\n (formUpdate)=\"onFormUpdate()\"\n/>\n", dependencies: [{ kind: "component", type: FormComponent, selector: "ng-dhis2-ui-form", inputs: ["formConfig", "fields", "form", "isFormHorizontal", "showSaveButton", "fieldsData", "fieldClass", "shouldRenderAsCheckBoxesButton", "programRuleActions", "dataEntities"], outputs: ["formUpdate"] }] }); }
6627
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.8", type: FlatFormComponent, isStandalone: false, selector: "ng-dhis2-ui-flat-form", usesInheritance: true, ngImport: i0, template: "<ng-dhis2-ui-form\n [fields]=\"fields()\"\n [form]=\"formGroup\"\n [dataEntities]=\"dataValues()\"\n [programRuleActions]=\"ruleActions()\"\n (formUpdate)=\"onFormUpdate()\"\n/>\n", dependencies: [{ kind: "component", type: FormComponent, selector: "ng-dhis2-ui-form", inputs: ["formConfig", "fields", "form", "isFormHorizontal", "showSaveButton", "fieldsData", "fieldClass", "shouldRenderAsCheckBoxesButton", "programRuleActions", "dataEntities"], outputs: ["formUpdate"] }] }); }
6439
6628
  }
6440
6629
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FlatFormComponent, decorators: [{
6441
6630
  type: Component,
6442
- args: [{ selector: 'ng-dhis2-ui-flat-form', standalone: false, template: "<!-- <ng-dhis2-ui-form\n*ngIf=\"fieldGroup.fields.length > 0\"\n[fields]=\"fieldGroup.fields\"\n[form]=\"formGroup\"\n[dataEntities]=\"dataValueEntities()\"\n[programRuleActions]=\"ruleActions()\"\n[isFormHorizontal]=\"fieldGroup.isFormHorizontal || false\"\n(formUpdate)=\"onFormUpdate($event, fieldGroup.id)\"\n></ng-dhis2-ui-form> -->\n\n<ng-dhis2-ui-form\n [fields]=\"fields()\"\n [form]=\"formGroup\"\n [dataEntities]=\"dataValues()\"\n [programRuleActions]=\"ruleActions()\"\n (formUpdate)=\"onFormUpdate()\"\n/>\n" }]
6631
+ args: [{ selector: 'ng-dhis2-ui-flat-form', standalone: false, template: "<ng-dhis2-ui-form\n [fields]=\"fields()\"\n [form]=\"formGroup\"\n [dataEntities]=\"dataValues()\"\n [programRuleActions]=\"ruleActions()\"\n (formUpdate)=\"onFormUpdate()\"\n/>\n" }]
6443
6632
  }] });
6444
6633
 
6445
6634
  class D2FormModule {
@@ -6858,6 +7047,7 @@ class TrackerFormComponent {
6858
7047
  }
6859
7048
  onFormUpdate(values) {
6860
7049
  const instance = this.instance;
7050
+ console.log(instance);
6861
7051
  instance?.updateDataValues(values);
6862
7052
  }
6863
7053
  onSave(event) { }
@@ -7008,11 +7198,12 @@ class ProgramEntryFormFieldUtil {
7008
7198
  return new FormField({
7009
7199
  id: 'orgUnit',
7010
7200
  key: 'orgUnit',
7011
- label: this.program.orgUnitLabel || 'Registering unit',
7201
+ label: this.program.orgUnitLabel ?? 'Registering unit',
7012
7202
  code: 'orgUnit',
7013
7203
  required: true,
7014
7204
  controlType: 'org-unit',
7015
7205
  disabled: this.config.disableRegistrationUnit,
7206
+ isOrgUnit: true,
7016
7207
  });
7017
7208
  }
7018
7209
  #getEnrollmentDateField() {
@@ -7395,7 +7586,7 @@ class ProgramEntryFormModule {
7395
7586
  this.instanceQuery = this.d2.trackerModule.trackedEntity
7396
7587
  .setProgram(this.config().program)
7397
7588
  .setOrgUnit(this.orgUnit());
7398
- if (!this.trackedEntity) {
7589
+ if (!this.trackedEntity()) {
7399
7590
  return await this.instanceQuery.create();
7400
7591
  }
7401
7592
  const instance = (await this.instanceQuery