@iapps/ng-dhis2-ui 1.2.0 → 1.2.2

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,215 +3106,317 @@ 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
- let teisRaw = response.data
3137
- .trackedEntityInstances;
3138
- const teis = Array.isArray(teisRaw)
3139
- ? teisRaw
3140
- : [teisRaw];
3141
- const programTrackedEntityAttributes = metaData.programTrackedEntityAttributes;
3142
- const orgUnitLabel = metaData.orgUnitLabel;
3143
- const orgUnitMap = response.data
3144
- .orgUnitsMap;
3145
- const attributeColumns = metaData.displayInListTrackedEntityAttributes
3146
- .sort((a, b) => a.sortOrder - b.sortOrder)
3147
- .map((attr) => ({
3148
- label: attr.name,
3149
- key: attr.id,
3150
- }));
3151
- const dataElementColumns = metaData.displayInListDataElements
3152
- .sort((a, b) => a.sortOrder - b.sortOrder)
3153
- .map((element) => ({
3154
- label: element.name,
3155
- key: element.id,
3156
- }));
3157
- const dataElementOptions = metaData.displayInListDataElements.map((element) => ({
3158
- id: element.id,
3159
- options: element.optionSet?.options.map((opt) => ({
3160
- name: opt.name,
3161
- color: opt.style?.color,
3162
- })),
3163
- }));
3164
- const tableColumns = [
3165
- {
3166
- label: orgUnitLabel || 'registering unit',
3167
- key: 'orgUnit',
3168
- },
3169
- ...attributeColumns,
3170
- ...dataElementColumns,
3171
- ];
3172
- const tableFilters = metaData.searchableTrackedEntityAttributes
3173
- .sort((a, b) => a.sortOrder - b.sortOrder)
3174
- .map((attr) => ({
3175
- label: attr.name,
3176
- key: attr.id,
3177
- valueType: attr.valueType,
3178
- options: attr.optionSet ?? undefined,
3179
- }));
3180
- const tableData = teis.map((tei, idx) => {
3181
- const row = {
3182
- trackedEntityInstance: { value: tei.trackedEntity },
3183
- index: { value: (pager.page - 1) * pager.pageSize + idx + 1 },
3184
- };
3185
- const matchingEnrollment = tei.latestEnrollment;
3186
- //let disaplayInListAttributes = metaData.displayInListTrackedEntityAttributes;
3187
- let attributesData = matchingEnrollment.attributes;
3188
- let dataElementsData = matchingEnrollment.events.flatMap((event) => event.dataValues);
3189
- attributesData = attributesData.map((attr) => {
3190
- if (attr?.valueType?.toLowerCase() === 'date') {
3191
- try {
3192
- return {
3193
- ...attr,
3194
- value: format(parse$1(attr.value, 'yyyy-MM-dd', new Date()), 'dd-MM-yyyy'),
3195
- };
3196
- }
3197
- catch {
3198
- return { ...attr }; // Leave value as is on parse failure
3199
- }
3200
- }
3201
- return attr;
3202
- });
3203
- attributesData.forEach((attr) => {
3204
- row[attr.attribute] = { value: attr.value };
3205
- });
3206
- dataElementsData.forEach((element) => {
3207
- // Find the matching data element in dataElementOptions by ID
3208
- const dataElementOption = dataElementOptions.find((deo) => deo.id === element.dataElement);
3209
- // find a matching option within that data element's options
3210
- const matchingOption = dataElementOption?.options?.find((opt) => opt.name === element.value);
3211
- // Build the row entry with value and optionally style
3212
- if (matchingOption) {
3213
- row[element.dataElement] = {
3214
- value: element.value,
3215
- style: matchingOption.color,
3216
- };
3217
- }
3218
- else {
3219
- row[element.dataElement] = {
3220
- value: element.value,
3221
- };
3222
- }
3223
- });
3224
- // Include orgUnit in the row for id access with style
3225
- row['orgUnitId'] = { value: matchingEnrollment.orgUnit };
3226
- row['orgUnit'] = {
3227
- value: orgUnitMap?.get(matchingEnrollment.orgUnit) || '-',
3228
- };
3229
- return row;
3230
- });
3231
- return {
3232
- columns: tableColumns,
3233
- data: tableData,
3234
- filteredEntityColumns: tableFilters,
3235
- orgUnitLabel: orgUnitLabel,
3236
- };
3237
- };
3238
- const addActionsColumn = (columns, actionOptions) => {
3239
- return [
3240
- ...columns,
3241
- ...(actionOptions && actionOptions.length > 0
3242
- ? [{ label: 'Actions', key: 'actions' }]
3243
- : []),
3244
- ];
3245
- };
3246
-
3247
- 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" },
3248
- React__default.createElement("div", { style: {
3249
- display: 'flex',
3250
- alignItems: 'center',
3251
- gap: '10px',
3252
- flexWrap: 'wrap',
3253
- } },
3254
- React__default.createElement(InputField$1, { key: "location", label: orgUnitLabel ? orgUnitLabel : 'registering unit:', value: selectedOrgUnit, onFocus: () => setHide(false), className: "custom-input", clearable: true, onChange: (event) => {
3255
- setSelectedOrgUnit(event.value);
3256
- setOrgUnitState(defaultOrgUnit);
3257
- } }),
3258
- React__default.createElement(CalendarInput, { label: "Start date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: startDateState, onDateSelect: (selectedDate) => {
3259
- setStartDateState(selectedDate.calendarDateString);
3260
- } }),
3261
- React__default.createElement(CalendarInput, { label: "End date:", calendar: "gregory", locale: "en-GB", timeZone: "Africa/Dar_es_Salaam", className: "custom-input", date: endDateState, onDateSelect: (selectedDate) => {
3262
- setEndDateState(selectedDate.calendarDateString);
3263
- } }),
3264
- (visibleFilters ?? []).map(({ label, key, valueType, options }) => {
3265
- if (valueType === 'DATE') {
3266
- 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) }));
3267
- }
3268
- if (options && options.options.length > 0) {
3269
- return (React__default.createElement(SingleSelectField, { key: key, label: `${label}:`, selected: inputValues[key] || '', className: "custom-select-input", clearable: true, onChange: ({ selected }) => {
3270
- setInputValues((prevValues) => ({
3271
- ...prevValues,
3272
- [key]: selected ?? '',
3273
- }));
3274
- handleInputChangeForSelectField(key, selected ?? '');
3275
- } }, (options.options ?? []).map((opt) => (React__default.createElement(SingleSelectOption, { key: opt.id, label: opt.name, value: opt.code })))));
3276
- }
3277
- return (React__default.createElement(InputField$1, { key: key, label: `${label}:`, className: "custom-input", value: inputValues[key] || '', clearable: true, onChange: (e) => {
3278
- const currentValue = 'target' in e ? e.target.value : e.value ?? '';
3279
- setInputValues((prevValues) => ({
3280
- ...prevValues,
3281
- [key]: currentValue,
3282
- }));
3283
- if (currentValue === '') {
3284
- handleInputChange(key, '');
3285
- }
3286
- }, onBlur: (e) => {
3287
- const currentValue = 'target' in e ? e.target.value : e.value ?? '';
3288
- if (currentValue !== '' && currentValue !== prevValue) {
3289
- handleInputChange(key, currentValue);
3290
- setPrevValue(currentValue);
3291
- }
3292
- } }));
3293
- }),
3294
- React__default.createElement(Button$1, { onClick: () => setShowAllFilters(!showAllFilters) }, showAllFilters ? 'Less Filters' : 'More Filters'))));
3295
-
3296
- const TableHeader = ({ columns }) => (React__default.createElement(TableHead, null,
3297
- React__default.createElement(DataTableRow, null, columns.map((col) => (React__default.createElement(DataTableColumnHeader, { key: col.key }, col.label))))));
3298
-
3299
- const dropdownStyles$1 = {
3300
- layer: {
3301
- zIndex: '1 !important',
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',
3302
3156
  },
3303
3157
  };
3304
-
3305
- // Helper function to generate a unique class name
3306
- const generateClassName$1 = (base) => `${base}-${Math.random().toString(36).substr(2, 9)}`;
3307
- // Helper function to convert camelCased properties to hyphenated CSS properties
3308
- const convertStylesToCSS$1 = (className, styles) => {
3309
- let cssString = `.${className} {`;
3310
- for (const key in styles) {
3311
- if (typeof styles[key] === "object" && key.startsWith("@media")) {
3312
- const mediaStyles = convertStylesToCSS$1(className, styles[key]);
3313
- cssString += `${key} { ${mediaStyles} }`;
3158
+ const OrgUnitFormField$1 = (props) => {
3159
+ const { onSelectOrgUnit, label, required, selected, disabled, key } = props;
3160
+ const d2 = window?.d2Web;
3161
+ const classes = useDynamicStyles$2(orgUnitFieldStyles$1);
3162
+ const config = useMemo(() => {
3163
+ return d2.systemInfo?.toInitObject();
3164
+ }, []);
3165
+ const rootOrgUnits = useMemo(() => {
3166
+ return d2.currentUser?.organisationUnits || [];
3167
+ }, []);
3168
+ const getExpandedItems = () => {
3169
+ if (rootOrgUnits && rootOrgUnits.length === 1) {
3170
+ return [`/${rootOrgUnits[0].id}`];
3314
3171
  }
3315
- else if (key.startsWith("&:")) {
3316
- const pseudoClass = key.replace("&", "");
3317
- cssString += `${pseudoClass} { ${convertStylesToCSS$1("", styles[key])} }`;
3172
+ else if (rootOrgUnits?.length > 1) {
3173
+ return rootOrgUnits.map((root) => root.path);
3174
+ }
3175
+ return undefined;
3176
+ };
3177
+ const initiallyExpanded = getExpandedItems();
3178
+ const [searchText, setSearchText] = useState(undefined);
3179
+ const [loading, setLoading] = useState(true);
3180
+ const [searchLoading, setSearchLoading] = useState();
3181
+ const [searchData, setSearchData] = useState();
3182
+ const [selectedOrgUnit, setSelectedOrgUnit] = useState();
3183
+ const [expanded, setExpanded] = useState(initiallyExpanded);
3184
+ const [showOrgUnitTree, setShowOrgUnitTree] = useState(!selected);
3185
+ useEffect(() => {
3186
+ setLoading(true);
3187
+ if (selected) {
3188
+ d2.httpInstance
3189
+ .get(`organisationUnits/${selected}.json?fields=id,displayName,path,code,ancestors[id,displayName]`)
3190
+ .then((response) => {
3191
+ if (response.data) {
3192
+ setSelectedOrgUnit(response.data);
3193
+ handleExpand({ path: response.data['path'] });
3194
+ setLoading(false);
3195
+ }
3196
+ });
3197
+ }
3198
+ else {
3199
+ setShowOrgUnitTree(true);
3200
+ setLoading(false);
3201
+ }
3202
+ }, []);
3203
+ const highlighted = useMemo(() => {
3204
+ if (selectedOrgUnit) {
3205
+ return [selectedOrgUnit['path']];
3206
+ }
3207
+ return undefined;
3208
+ }, [selectedOrgUnit]);
3209
+ const selectedOrgUnitLabel = useMemo(() => {
3210
+ if (selectedOrgUnit) {
3211
+ return [
3212
+ ...(selectedOrgUnit['ancestors'] || []),
3213
+ selectedOrgUnit,
3214
+ ]
3215
+ .map((orgUnit) => orgUnit['displayName'])
3216
+ .join(' / ');
3217
+ }
3218
+ return '';
3219
+ }, [selectedOrgUnit]);
3220
+ const handleExpand = ({ path }) => {
3221
+ if (expanded && !expanded.includes(path)) {
3222
+ setExpanded([...expanded, path]);
3223
+ }
3224
+ };
3225
+ const handleCollapse = ({ path }) => {
3226
+ const pathIndex = expanded?.indexOf(path);
3227
+ if (pathIndex && pathIndex !== -1 && expanded) {
3228
+ const updatedExpanded = pathIndex === 0
3229
+ ? expanded.slice(1)
3230
+ : [...expanded.slice(0, pathIndex), ...expanded.slice(pathIndex + 1)];
3231
+ setExpanded(updatedExpanded);
3232
+ }
3233
+ };
3234
+ const handleOrgUnitSearch = async (query) => {
3235
+ setSearchLoading(true);
3236
+ try {
3237
+ 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`);
3238
+ setSearchData((searchResponse.data || {})['organisationUnits']);
3239
+ setSearchLoading(false);
3240
+ }
3241
+ catch (e) {
3242
+ setSearchLoading(false);
3243
+ }
3244
+ };
3245
+ const debouncedSearch = useCallback(debounce((value) => {
3246
+ handleOrgUnitSearch(value);
3247
+ }, 500), []);
3248
+ const handleFilterChange = (event) => {
3249
+ setSearchText(event.value);
3250
+ debouncedSearch(event.value);
3251
+ };
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])} }`;
3318
3420
  }
3319
3421
  else {
3320
3422
  const cssKey = key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
@@ -3396,7 +3498,7 @@ const DropdownMenu$1 = (props) => {
3396
3498
  // Use of this source code is governed by a BSD-style
3397
3499
  // license that can be found in the LICENSE file.
3398
3500
  const DataTableActions = (props) => {
3399
- const { actionOptions, actionOptionOrientation, onClick } = props;
3501
+ const { data, actionOptions, actionOptionOrientation, onClick } = props;
3400
3502
  switch (actionOptionOrientation) {
3401
3503
  case 'BUTTON':
3402
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 : '')))));
@@ -3419,289 +3521,385 @@ const DataTableActions = (props) => {
3419
3521
  color: option.destructive ? colors$1.red700 : colors$1.grey900,
3420
3522
  }, key: option.label, onClick: (event) => {
3421
3523
  event.stopPropagation();
3422
- onClick(option);
3423
- } },
3424
- option.icon ? React__default.createElement(option.icon, null) : React__default.createElement(React__default.Fragment, null),
3425
- !option.iconOnly ? React__default.createElement("span", null, option.label) : React__default.createElement(React__default.Fragment, null))))));
3426
- default:
3427
- return React__default.createElement(React__default.Fragment, null);
3428
- }
3429
- };
3430
-
3431
- // Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
3432
- // Use of this source code is governed by a BSD-style
3433
- // license that can be found in the LICENSE file.
3434
-
3435
- const TableCell = ({ cell, getTextColorFromBackGround, }) => {
3436
- if (cell?.style && cell?.style !== 'default-value') {
3437
- return (React__default.createElement(DataTableCell, null,
3438
- React__default.createElement("div", { style: { display: 'flex', justifyContent: 'center' } },
3439
- React__default.createElement("span", { style: {
3440
- backgroundColor: cell.style,
3441
- display: 'inline-flex',
3442
- alignItems: 'center',
3443
- padding: 4,
3444
- borderRadius: 3,
3445
- fontSize: 12,
3446
- color: getTextColorFromBackGround(cell.style),
3447
- } }, cell.value))));
3448
- }
3449
- return (React__default.createElement(DataTableCell, null,
3450
- React__default.createElement("div", { className: "text-sm text-gray-800" }, cell?.value || '-')));
3451
- };
3452
-
3453
- const TableRow = ({ row, columns, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, }) => (React__default.createElement(DataTableRow, { key: row.index.value }, columns.map((col) => {
3454
- if (col.key === 'actions') {
3455
- return (React__default.createElement(DataTableCell, { key: col.key }, actionOptions && (React__default.createElement(DataTableActions, { actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, onClick: (option) => {
3456
- if (option.onClick)
3457
- option.onClick(row);
3458
- actionSelected.emit({ action: option.label, row });
3459
- } }))));
3460
- }
3461
- return (React__default.createElement(TableCell, { key: col.key, cell: row[col.key], getTextColorFromBackGround: getTextColorFromBackGround }));
3462
- })));
3463
-
3464
- 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,
3465
- React__default.createElement(DataTableCell, { colSpan: columns.length.toString(), style: {
3466
- textAlign: 'center',
3467
- fontWeight: 'bold',
3468
- color: 'grey',
3469
- padding: '20px',
3470
- } }, "No data found")))));
3471
-
3472
- const Pagination = ({ pager, setPager }) => {
3473
- if (!pager || pager.page === undefined || pager.pageSize === undefined) {
3474
- return null; //skip rendering until valid
3475
- }
3476
- 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({
3477
- ...prev,
3478
- pageSize: Number(pageSize),
3479
- page: 1,
3480
- })), pageSizes: ['10', '20', '50', '100', '500'] }));
3481
- };
3482
-
3483
- const TableFooter = ({ pager, setPager, columns }) => {
3484
- return (React__default.createElement(TableFoot, null,
3485
- React__default.createElement(DataTableRow, null,
3486
- React__default.createElement(DataTableCell, { colSpan: columns.length.toString() },
3487
- React__default.createElement(Pagination, { pager: pager, setPager: setPager })))));
3488
- };
3489
-
3490
- const LineListTable = ({ columns, data, pager, setPager, getTextColorFromBackGround, actionOptions, actionOptionOrientation, actionSelected, }) => {
3491
- return (React__default.createElement(DataTable, null,
3492
- React__default.createElement(TableHeader, { columns: columns }),
3493
- React__default.createElement(TableBody, { data: data, columns: columns, getTextColorFromBackGround: getTextColorFromBackGround, actionOptions: actionOptions, actionOptionOrientation: actionOptionOrientation, actionSelected: actionSelected }),
3494
- React__default.createElement(TableFooter, { columns: columns, pager: pager, setPager: setPager })));
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
- // @flow
3501
- const orgUnitFieldStyles$1 = {
3502
- container: {
3503
- border: '1px solid',
3504
- borderColor: colors$1.grey400,
3505
- borderRadius: '3px',
3506
- height: '100%',
3507
- width: '100%',
3508
- zIndex: 0,
3509
- backgroundColor: 'white',
3510
- },
3511
- searchField: {
3512
- height: '40px',
3513
- overflow: 'hidden',
3514
- borderBottomLeftRadius: 0,
3515
- borderBottomRightRadius: 0,
3516
- boxShadow: 'none',
3517
- border: 'none',
3518
- },
3519
- debounceFieldContainer: {
3520
- padding: '8px',
3521
- background: colors$1.grey100,
3522
- borderTopLeftRadius: '3px',
3523
- borderTopRightRadius: '3px',
3524
- },
3525
- orgUnitTreeContainer: {
3526
- borderBottomLeftRadius: '3px',
3527
- borderBottomRightRadius: '3px',
3528
- overflow: 'auto',
3529
- },
3530
- orgUnitTreeLoader: {
3531
- padding: '8px',
3532
- },
3533
- orgUnitFieldLabel: {
3534
- marginBottom: '8px',
3535
- display: 'block',
3536
- boxSizing: 'border-box',
3537
- fontSize: '14px',
3538
- lineHeight: '19px',
3539
- color: 'rgb(33, 41, 52)',
3540
- padding: '0',
3541
- },
3542
- orgUnitFieldRequiredLabel: {
3543
- paddingInlineStart: '4px',
3544
- },
3545
- };
3546
- const OrgUnitFormField$1 = (props) => {
3547
- const { onSelectOrgUnit, label, required, selected, disabled, key } = props;
3548
- const d2 = window?.d2Web;
3549
- const classes = useDynamicStyles$2(orgUnitFieldStyles$1);
3550
- const config = useMemo(() => {
3551
- return d2.systemInfo?.toInitObject();
3552
- }, []);
3553
- const rootOrgUnits = useMemo(() => {
3554
- return d2.currentUser?.organisationUnits || [];
3555
- }, []);
3556
- const getExpandedItems = () => {
3557
- if (rootOrgUnits && rootOrgUnits.length === 1) {
3558
- return [`/${rootOrgUnits[0].id}`];
3559
- }
3560
- else if (rootOrgUnits?.length > 1) {
3561
- return rootOrgUnits.map((root) => root.path);
3562
- }
3563
- return undefined;
3564
- };
3565
- const initiallyExpanded = getExpandedItems();
3566
- const [searchText, setSearchText] = useState(undefined);
3567
- const [loading, setLoading] = useState(true);
3568
- const [searchLoading, setSearchLoading] = useState();
3569
- const [searchData, setSearchData] = useState();
3570
- const [selectedOrgUnit, setSelectedOrgUnit] = useState();
3571
- const [expanded, setExpanded] = useState(initiallyExpanded);
3572
- const [showOrgUnitTree, setShowOrgUnitTree] = useState(!selected);
3573
- useEffect(() => {
3574
- setLoading(true);
3575
- if (selected) {
3576
- d2.httpInstance
3577
- .get(`organisationUnits/${selected}.json?fields=id,displayName,path,code,ancestors[id,displayName]`)
3578
- .then((response) => {
3579
- if (response.data) {
3580
- setSelectedOrgUnit(response.data);
3581
- handleExpand({ path: response.data['path'] });
3582
- setLoading(false);
3583
- }
3584
- });
3585
- }
3586
- else {
3587
- setShowOrgUnitTree(true);
3588
- setLoading(false);
3589
- }
3590
- }, []);
3591
- const highlighted = useMemo(() => {
3592
- if (selectedOrgUnit) {
3593
- return [selectedOrgUnit['path']];
3594
- }
3595
- return undefined;
3596
- }, [selectedOrgUnit]);
3597
- const selectedOrgUnitLabel = useMemo(() => {
3598
- if (selectedOrgUnit) {
3599
- return [
3600
- ...(selectedOrgUnit['ancestors'] || []),
3601
- selectedOrgUnit,
3602
- ]
3603
- .map((orgUnit) => orgUnit['displayName'])
3604
- .join(' / ');
3605
- }
3606
- return '';
3607
- }, [selectedOrgUnit]);
3608
- const handleExpand = ({ path }) => {
3609
- if (expanded && !expanded.includes(path)) {
3610
- setExpanded([...expanded, path]);
3611
- }
3612
- };
3613
- const handleCollapse = ({ path }) => {
3614
- const pathIndex = expanded?.indexOf(path);
3615
- if (pathIndex && pathIndex !== -1 && expanded) {
3616
- const updatedExpanded = pathIndex === 0
3617
- ? expanded.slice(1)
3618
- : [...expanded.slice(0, pathIndex), ...expanded.slice(pathIndex + 1)];
3619
- setExpanded(updatedExpanded);
3620
- }
3621
- };
3622
- const handleOrgUnitSearch = async (query) => {
3623
- setSearchLoading(true);
3624
- try {
3625
- 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`);
3626
- setSearchData((searchResponse.data || {})['organisationUnits']);
3627
- setSearchLoading(false);
3628
- }
3629
- catch (e) {
3630
- setSearchLoading(false);
3631
- }
3632
- };
3633
- const debouncedSearch = useCallback(debounce((value) => {
3634
- handleOrgUnitSearch(value);
3635
- }, 500), []);
3636
- const handleFilterChange = (event) => {
3637
- setSearchText(event.value);
3638
- debouncedSearch(event.value);
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);
3639
3617
  };
3640
- const ready = useMemo(() => {
3641
- return searchText?.length ? !searchLoading : !loading;
3642
- }, [searchText, searchLoading, loading]);
3643
- const renderOrgUnitTree = () => {
3644
- if (searchText && searchText?.length > 0) {
3645
- if (searchLoading) {
3646
- return (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3647
- React__default.createElement(CircularLoader$1, { small: true })));
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
+ } }))));
3648
3632
  }
3649
- 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) => {
3650
- setSelectedOrgUnit(event);
3651
- setShowOrgUnitTree(false);
3652
- onSelectOrgUnit(event);
3653
- } })));
3654
- }
3655
- 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) => {
3656
- setSelectedOrgUnit(event);
3657
- setShowOrgUnitTree(false);
3658
- onSelectOrgUnit(event);
3659
- } }));
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));
3660
3741
  };
3661
- const handleBlur = () => {
3662
- // onBlur && onBlur(null);
3742
+ const handleSelectAll = (checked) => {
3743
+ const updatedRows = checked ? data : [];
3744
+ setSelectedRows(updatedRows);
3745
+ rowsSelected.emit(updatedRows);
3663
3746
  };
3664
- return (config && (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false },
3665
- React__default.createElement("div", null,
3666
- label && (React__default.createElement("div", { className: classes.orgUnitFieldLabel },
3667
- React__default.createElement("span", null, label),
3668
- required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
3669
- !showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
3670
- React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
3671
- React__default.createElement(Chip, { onRemove: () => {
3672
- setShowOrgUnitTree(true);
3673
- } }, selectedOrgUnit.displayName)))) : (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3674
- React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
3675
- React__default.createElement("div", { className: classes.debounceFieldContainer },
3676
- React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
3677
- loading ? (React__default.createElement("div", { className: classes.orgUnitTreeLoader },
3678
- 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 })));
3679
3751
  };
3680
3752
 
3681
- const OrgUnitSelector = ({ hide, setHide, selectedOrgUnit, setSelectedOrgUnit, setOrgUnitState, }) => (React__default.createElement(Modal$1, { hide: hide, position: "middle" },
3682
- React__default.createElement(ModalTitle$1, null, "Select organization unit"),
3683
- React__default.createElement(ModalContent$1, null,
3684
- React__default.createElement(OrgUnitFormField$1, { key: selectedOrgUnit, onSelectOrgUnit: (selectedOrgUnit) => {
3685
- setSelectedOrgUnit(selectedOrgUnit.displayName);
3686
- setOrgUnitState(selectedOrgUnit.id);
3687
- setHide(true);
3688
- } })),
3689
- React__default.createElement(ModalActions$1, null,
3690
- React__default.createElement(ButtonStrip$1, { end: true },
3691
- 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
+ };
3692
3889
 
3693
3890
  // src/app/line-list-table.component.ts
3694
3891
  class LineListTableComponent extends ReactWrapperModule {
3695
3892
  constructor() {
3696
3893
  super(...arguments);
3697
3894
  this.actionOptionOrientation = 'DROPDOWN';
3698
- this.actionSelected = new EventEmitter();
3699
- this.reactStateUpdaters = null;
3700
- this.approvalSelected = new EventEmitter();
3701
3895
  this.isButtonLoading = false;
3702
3896
  this.filterRootOrgUnit = false;
3703
3897
  this.showFilters = false;
3704
3898
  this.isOptionSetNameVisible = false;
3899
+ this.allowRowsSelection = false;
3900
+ this.actionSelected = new EventEmitter();
3901
+ this.rowsSelected = new EventEmitter();
3902
+ this.reactStateUpdaters = null;
3705
3903
  this.setReactStateUpdaters = (updaters) => {
3706
3904
  this.reactStateUpdaters = updaters;
3707
3905
  };
@@ -3738,6 +3936,7 @@ class LineListTableComponent extends ReactWrapperModule {
3738
3936
  const [prevValue, setPrevValue] = useState();
3739
3937
  const [dateStates, setDateStates] = useState({});
3740
3938
  const [metaData, setMetaData] = useState(null);
3939
+ const [selectable, setSelectable] = useState(this.allowRowsSelection);
3741
3940
  const d2 = window.d2Web;
3742
3941
  // Store updaters in refs for Angular to access
3743
3942
  const updateRefs = useRef({
@@ -3748,6 +3947,7 @@ class LineListTableComponent extends ReactWrapperModule {
3748
3947
  setStartDateState,
3749
3948
  setEndDateState,
3750
3949
  setOptionSetNameVisible,
3950
+ setSelectable,
3751
3951
  });
3752
3952
  useEffect(() => {
3753
3953
  this.setReactStateUpdaters?.(updateRefs.current);
@@ -3828,7 +4028,6 @@ class LineListTableComponent extends ReactWrapperModule {
3828
4028
  else {
3829
4029
  //TODO: TO IMPLEMEMNT EVENT QUERY FOR FILTERING EVENTS WHEN PROGRAM STAGE IS PASSED OR DEALING WITH EVENT PROGRAM USING TRACKER SDK QUERY
3830
4030
  }
3831
- ;
3832
4031
  }, [
3833
4032
  metaData,
3834
4033
  programIdState,
@@ -3931,7 +4130,7 @@ class LineListTableComponent extends ReactWrapperModule {
3931
4130
  } }, "Loading"))) : (React__default.createElement("div", null,
3932
4131
  React__default.createElement(OrgUnitSelector, { hide: hide, setHide: setHide, selectedOrgUnit: selectedOrgUnit, setSelectedOrgUnit: setSelectedOrgUnit, setOrgUnitState: setOrgUnitState }),
3933
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 })),
3934
- 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 })))));
3935
4134
  };
3936
4135
  }
3937
4136
  ngOnChanges(changes) {
@@ -3960,6 +4159,9 @@ class LineListTableComponent extends ReactWrapperModule {
3960
4159
  if (changes['isButtonLoading']) {
3961
4160
  this.reactStateUpdaters.setIsButtonLoading(this.isButtonLoading);
3962
4161
  }
4162
+ if (changes['isSelectable']) {
4163
+ this.reactStateUpdaters.setIsButtonLoading(this.allowRowsSelection);
4164
+ }
3963
4165
  }
3964
4166
  }
3965
4167
  async ngAfterViewInit() {
@@ -3970,11 +4172,11 @@ class LineListTableComponent extends ReactWrapperModule {
3970
4172
  this.render();
3971
4173
  }
3972
4174
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListTableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3973
- 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"] }); }
3974
4176
  }
3975
4177
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: LineListTableComponent, decorators: [{
3976
4178
  type: Component,
3977
- 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"] }]
3978
4180
  }], propDecorators: { programId: [{
3979
4181
  type: Input
3980
4182
  }], orgUnit: [{
@@ -3997,10 +4199,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
3997
4199
  type: Input
3998
4200
  }], ouMode: [{
3999
4201
  type: Input
4000
- }], actionSelected: [{
4001
- type: Output
4002
- }], approvalSelected: [{
4003
- type: Output
4004
4202
  }], isButtonLoading: [{
4005
4203
  type: Input
4006
4204
  }], buttonFilter: [{
@@ -4011,6 +4209,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
4011
4209
  type: Input
4012
4210
  }], isOptionSetNameVisible: [{
4013
4211
  type: Input
4212
+ }], allowRowsSelection: [{
4213
+ type: Input
4214
+ }], actionSelected: [{
4215
+ type: Output
4216
+ }], rowsSelected: [{
4217
+ type: Output
4014
4218
  }] } });
4015
4219
 
4016
4220
  class LineListModule {
@@ -5096,6 +5300,7 @@ class FormMetaData {
5096
5300
  code: 'orgUnit',
5097
5301
  required: true,
5098
5302
  controlType: 'org-unit',
5303
+ isOrgUnit: true,
5099
5304
  }),
5100
5305
  ],
5101
5306
  },
@@ -5518,10 +5723,9 @@ const OrgUnitFormField = (props) => {
5518
5723
  React__default.createElement("span", null, label),
5519
5724
  required ? (React__default.createElement("span", { className: classes.orgUnitFieldRequiredLabel }, "*")) : (React__default.createElement(React__default.Fragment, null)))),
5520
5725
  !showOrgUnitTree ? (selectedOrgUnit ? (React__default.createElement(React__default.Fragment, null,
5521
- React__default.createElement(Tooltip, { content: selectedOrgUnitLabel },
5522
- React__default.createElement(Chip, { onRemove: () => {
5523
- setShowOrgUnitTree(true);
5524
- } }, 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 },
5525
5729
  React__default.createElement(CircularLoader$1, { small: true })))) : (React__default.createElement("div", { className: classes.container },
5526
5730
  React__default.createElement("div", { className: classes.debounceFieldContainer },
5527
5731
  React__default.createElement(InputField$1, { placeholder: "Search", value: searchText, disabled: disabled, onChange: handleFilterChange })),
@@ -5591,20 +5795,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
5591
5795
  checkValueUniqueness();
5592
5796
  }
5593
5797
  }, [this.isValueAssigned()]);
5594
- // TODO: START: Improve the approach of handling observables
5595
- // useEffect(() => {
5596
- // const fieldErrorSubscription = this.fieldError$
5597
- // .pipe(filter((error) => error !== initialError))
5598
- // .subscribe({
5599
- // next: (error: string | undefined) => {
5600
- // setInitialError(error);
5601
- // },
5602
- // });
5603
- // return () => {
5604
- // fieldErrorSubscription.unsubscribe();
5605
- // };
5606
- // });
5607
- // TODO: END: Improve the approach of handling observables
5798
+ // TODO: Review error handling as take() has potential to missed any other updated error information
5608
5799
  useEffect(() => {
5609
5800
  const fieldErrorSubscription = this.fieldError$
5610
5801
  .pipe(filter((error) => error !== initialError), take(1) // Take only the first emitted value, then unsubscribe
@@ -5668,7 +5859,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
5668
5859
  const formFieldContent = () => {
5669
5860
  switch (this.field().controlType) {
5670
5861
  case 'textarea':
5671
- 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) => {
5672
5863
  this.ngZone.run(() => {
5673
5864
  (this.form().get(this.field().id) ||
5674
5865
  this.form().get(this.field().key))?.setValue(event.value);
@@ -5686,7 +5877,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
5686
5877
  });
5687
5878
  } }));
5688
5879
  case 'org-unit':
5689
- 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) => {
5690
5881
  this.ngZone.run(() => {
5691
5882
  (this.form().get(this.field().id) ||
5692
5883
  this.form().get(this.field().key))?.setValue(selectedOrgUnit);
@@ -6433,11 +6624,11 @@ class FlatFormComponent extends BaseFormWrapperComponent {
6433
6624
  this.updateFormValidity(this.formGroup.valid);
6434
6625
  }
6435
6626
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FlatFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
6436
- 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"] }] }); }
6437
6628
  }
6438
6629
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FlatFormComponent, decorators: [{
6439
6630
  type: Component,
6440
- 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" }]
6441
6632
  }] });
6442
6633
 
6443
6634
  class D2FormModule {
@@ -6856,6 +7047,7 @@ class TrackerFormComponent {
6856
7047
  }
6857
7048
  onFormUpdate(values) {
6858
7049
  const instance = this.instance;
7050
+ console.log(instance);
6859
7051
  instance?.updateDataValues(values);
6860
7052
  }
6861
7053
  onSave(event) { }
@@ -7006,11 +7198,12 @@ class ProgramEntryFormFieldUtil {
7006
7198
  return new FormField({
7007
7199
  id: 'orgUnit',
7008
7200
  key: 'orgUnit',
7009
- label: this.program.orgUnitLabel || 'Registering unit',
7201
+ label: this.program.orgUnitLabel ?? 'Registering unit',
7010
7202
  code: 'orgUnit',
7011
7203
  required: true,
7012
7204
  controlType: 'org-unit',
7013
7205
  disabled: this.config.disableRegistrationUnit,
7206
+ isOrgUnit: true,
7014
7207
  });
7015
7208
  }
7016
7209
  #getEnrollmentDateField() {