@iapps/ng-dhis2-ui 1.1.68 → 1.1.69
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.
|
@@ -8,7 +8,7 @@ import { NgxDhis2HttpClientService } from '@iapps/ngx-dhis2-http-client';
|
|
|
8
8
|
import * as React from 'react';
|
|
9
9
|
import React__default, { useState, useCallback, useRef, useEffect, createContext, useContext, useMemo } from 'react';
|
|
10
10
|
import * as ReactDOM from 'react-dom/client';
|
|
11
|
-
import { catchError, of, map, zip, firstValueFrom, filter, Subject, takeUntil } from 'rxjs';
|
|
11
|
+
import { catchError, of, map, zip, firstValueFrom, take, filter, Subject, takeUntil } from 'rxjs';
|
|
12
12
|
import i18n from '@dhis2/d2-i18n';
|
|
13
13
|
import { colors, theme, spacers } from '@dhis2/ui-constants';
|
|
14
14
|
import PropTypes from 'prop-types';
|
|
@@ -4096,10 +4096,132 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4096
4096
|
useEffect(() => {
|
|
4097
4097
|
this.setReactStateUpdaters?.(updateRefs.current);
|
|
4098
4098
|
}, []);
|
|
4099
|
+
// TODO: START: Improve the approach of handling observables
|
|
4100
|
+
// useEffect(() => {
|
|
4101
|
+
// setLoading(true);
|
|
4102
|
+
// this.lineListService
|
|
4103
|
+
// .getLineListData(
|
|
4104
|
+
// this.programId,
|
|
4105
|
+
// orgUnitState,
|
|
4106
|
+
// this.programStageId,
|
|
4107
|
+
// pager.page,
|
|
4108
|
+
// pager.pageSize,
|
|
4109
|
+
// attributeFiltersState,
|
|
4110
|
+
// startDateState,
|
|
4111
|
+
// endDateState,
|
|
4112
|
+
// this.ouMode,
|
|
4113
|
+
// this.filterRootOrgUnit,
|
|
4114
|
+
// this.useOuModeWithOlderDHIS2Instance
|
|
4115
|
+
// )
|
|
4116
|
+
// .subscribe((response: LineListResponse) => {
|
|
4117
|
+
// let entityColumns: ColumnDefinition[] = [];
|
|
4118
|
+
// let responsePager: Pager;
|
|
4119
|
+
// let entityData: TableRow[] = [];
|
|
4120
|
+
// let filteredDataColumns: ColumnDefinition[] = [];
|
|
4121
|
+
// if (this.programStageId) {
|
|
4122
|
+
// responsePager = (response.data as EventsResponse).pager;
|
|
4123
|
+
// const { columns, data } = getProgramStageData(
|
|
4124
|
+
// response,
|
|
4125
|
+
// this.programStageId,
|
|
4126
|
+
// pager,
|
|
4127
|
+
// this.isOptionSetNameVisible
|
|
4128
|
+
// );
|
|
4129
|
+
// entityColumns = columns;
|
|
4130
|
+
// entityData = data;
|
|
4131
|
+
// } else if (
|
|
4132
|
+
// 'trackedEntities' in response.data ||
|
|
4133
|
+
// 'instances' in response.data
|
|
4134
|
+
// ) {
|
|
4135
|
+
// const responseData: any = response.data as TrackedEntityResponse;
|
|
4136
|
+
// responsePager = (response.data as TrackedEntityResponse).pager || {
|
|
4137
|
+
// page: responseData.page,
|
|
4138
|
+
// pageSize: responseData.pageSize,
|
|
4139
|
+
// total: responseData.total,
|
|
4140
|
+
// pageCount: responseData.pageCount,
|
|
4141
|
+
// };
|
|
4142
|
+
// const { columns, data, filteredEntityColumns } =
|
|
4143
|
+
// getTrackedEntityData(
|
|
4144
|
+
// response,
|
|
4145
|
+
// this.programId,
|
|
4146
|
+
// pager,
|
|
4147
|
+
// this.isOptionSetNameVisible,
|
|
4148
|
+
// this.filters
|
|
4149
|
+
// );
|
|
4150
|
+
// entityColumns = columns;
|
|
4151
|
+
// entityData = data;
|
|
4152
|
+
// //TODO: Should be done on the parent
|
|
4153
|
+
// const checkValues = [
|
|
4154
|
+
// ...new Set(
|
|
4155
|
+
// (
|
|
4156
|
+
// response.data as TrackedEntityResponse
|
|
4157
|
+
// )?.trackedEntities?.[0]?.enrollments?.[0]?.events?.flatMap(
|
|
4158
|
+
// (event) =>
|
|
4159
|
+
// event.dataValues
|
|
4160
|
+
// .filter((dataValue) =>
|
|
4161
|
+
// /^[A-Za-z]{3}$/.test(dataValue.value)
|
|
4162
|
+
// )
|
|
4163
|
+
// .map((dataValue) => dataValue.value)
|
|
4164
|
+
// ) ??
|
|
4165
|
+
// (
|
|
4166
|
+
// response.data as TrackedEntityResponse
|
|
4167
|
+
// )?.instances?.[0]?.enrollments?.[0]?.events?.flatMap(
|
|
4168
|
+
// (event) =>
|
|
4169
|
+
// event.dataValues
|
|
4170
|
+
// .filter((dataValue) =>
|
|
4171
|
+
// /^[A-Za-z]{3}$/.test(dataValue.value)
|
|
4172
|
+
// )
|
|
4173
|
+
// .map((dataValue) => dataValue.value)
|
|
4174
|
+
// )
|
|
4175
|
+
// ),
|
|
4176
|
+
// ];
|
|
4177
|
+
// if (checkValues) {
|
|
4178
|
+
// // this.firstValue.emit(firstTei);
|
|
4179
|
+
// setCheckValue(checkValues);
|
|
4180
|
+
// setValuesMatch(!checkValues.includes(this.buttonFilter));
|
|
4181
|
+
// }
|
|
4182
|
+
// // setFilteredColumns(filteredEntityColumns);
|
|
4183
|
+
// // Ensure filter inputs do not disappear when no data is returned
|
|
4184
|
+
// // If filteredEntityColumns is empty, keep the previous columns instead of clearing them
|
|
4185
|
+
// setFilteredColumns((prev) =>
|
|
4186
|
+
// filteredEntityColumns.length > 0 ? filteredEntityColumns : prev
|
|
4187
|
+
// );
|
|
4188
|
+
// filteredDataColumns = filteredEntityColumns;
|
|
4189
|
+
// } else {
|
|
4190
|
+
// responsePager = (response.data as EventsResponse).pager;
|
|
4191
|
+
// const { columns, data } = getEventData(
|
|
4192
|
+
// response,
|
|
4193
|
+
// pager,
|
|
4194
|
+
// this.isOptionSetNameVisible
|
|
4195
|
+
// );
|
|
4196
|
+
// entityColumns = columns;
|
|
4197
|
+
// entityData = data;
|
|
4198
|
+
// }
|
|
4199
|
+
// const finalColumns: ColumnDefinition[] = addActionsColumn(
|
|
4200
|
+
// [{ label: '#', key: 'index' }, ...entityColumns],
|
|
4201
|
+
// this.actionOptions
|
|
4202
|
+
// );
|
|
4203
|
+
// setLoading(false);
|
|
4204
|
+
// setColumns(...[finalColumns]);
|
|
4205
|
+
// setData(...[entityData]);
|
|
4206
|
+
// setPager(...[responsePager]);
|
|
4207
|
+
// });
|
|
4208
|
+
// }, [
|
|
4209
|
+
// programIdState,
|
|
4210
|
+
// orgUnitState,
|
|
4211
|
+
// programStageIdState,
|
|
4212
|
+
// attributeFiltersState,
|
|
4213
|
+
// startDateState,
|
|
4214
|
+
// endDateState,
|
|
4215
|
+
// pager.page,
|
|
4216
|
+
// pager.pageSize,
|
|
4217
|
+
// isOptionSetNameVisibleState,
|
|
4218
|
+
// ]);
|
|
4219
|
+
// TODO: END: Improve the approach of handling observables
|
|
4099
4220
|
useEffect(() => {
|
|
4100
4221
|
setLoading(true);
|
|
4101
|
-
this.lineListService
|
|
4222
|
+
const subscription = this.lineListService
|
|
4102
4223
|
.getLineListData(this.programId, orgUnitState, this.programStageId, pager.page, pager.pageSize, attributeFiltersState, startDateState, endDateState, this.ouMode, this.filterRootOrgUnit, this.useOuModeWithOlderDHIS2Instance)
|
|
4224
|
+
.pipe(take(1)) // Automatically unsubscribe after the first emission
|
|
4103
4225
|
.subscribe((response) => {
|
|
4104
4226
|
let entityColumns = [];
|
|
4105
4227
|
let responsePager;
|
|
@@ -4111,10 +4233,10 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4111
4233
|
entityColumns = columns;
|
|
4112
4234
|
entityData = data;
|
|
4113
4235
|
}
|
|
4114
|
-
else if (
|
|
4115
|
-
|
|
4236
|
+
else if ("trackedEntities" in response.data ||
|
|
4237
|
+
"instances" in response.data) {
|
|
4116
4238
|
const responseData = response.data;
|
|
4117
|
-
responsePager =
|
|
4239
|
+
responsePager = responseData.pager || {
|
|
4118
4240
|
page: responseData.page,
|
|
4119
4241
|
pageSize: responseData.pageSize,
|
|
4120
4242
|
total: responseData.total,
|
|
@@ -4123,23 +4245,18 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4123
4245
|
const { columns, data, filteredEntityColumns } = getTrackedEntityData(response, this.programId, pager, this.isOptionSetNameVisible, this.filters);
|
|
4124
4246
|
entityColumns = columns;
|
|
4125
4247
|
entityData = data;
|
|
4126
|
-
//TODO: Should be done on the parent
|
|
4127
4248
|
const checkValues = [
|
|
4128
|
-
...new Set(
|
|
4249
|
+
...new Set(responseData?.trackedEntities?.[0]?.enrollments?.[0]?.events?.flatMap((event) => event.dataValues
|
|
4129
4250
|
.filter((dataValue) => /^[A-Za-z]{3}$/.test(dataValue.value))
|
|
4130
4251
|
.map((dataValue) => dataValue.value)) ??
|
|
4131
|
-
|
|
4252
|
+
responseData?.instances?.[0]?.enrollments?.[0]?.events?.flatMap((event) => event.dataValues
|
|
4132
4253
|
.filter((dataValue) => /^[A-Za-z]{3}$/.test(dataValue.value))
|
|
4133
4254
|
.map((dataValue) => dataValue.value))),
|
|
4134
4255
|
];
|
|
4135
|
-
if (checkValues) {
|
|
4136
|
-
// this.firstValue.emit(firstTei);
|
|
4256
|
+
if (checkValues.length > 0) {
|
|
4137
4257
|
setCheckValue(checkValues);
|
|
4138
4258
|
setValuesMatch(!checkValues.includes(this.buttonFilter));
|
|
4139
4259
|
}
|
|
4140
|
-
// setFilteredColumns(filteredEntityColumns);
|
|
4141
|
-
// Ensure filter inputs do not disappear when no data is returned
|
|
4142
|
-
// If filteredEntityColumns is empty, keep the previous columns instead of clearing them
|
|
4143
4260
|
setFilteredColumns((prev) => filteredEntityColumns.length > 0 ? filteredEntityColumns : prev);
|
|
4144
4261
|
filteredDataColumns = filteredEntityColumns;
|
|
4145
4262
|
}
|
|
@@ -4149,12 +4266,15 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4149
4266
|
entityColumns = columns;
|
|
4150
4267
|
entityData = data;
|
|
4151
4268
|
}
|
|
4152
|
-
const finalColumns = addActionsColumn([{ label:
|
|
4269
|
+
const finalColumns = addActionsColumn([{ label: "#", key: "index" }, ...entityColumns], this.actionOptions);
|
|
4153
4270
|
setLoading(false);
|
|
4154
|
-
setColumns(
|
|
4155
|
-
setData(
|
|
4156
|
-
setPager(
|
|
4271
|
+
setColumns(finalColumns);
|
|
4272
|
+
setData(entityData);
|
|
4273
|
+
setPager(responsePager);
|
|
4157
4274
|
});
|
|
4275
|
+
return () => {
|
|
4276
|
+
subscription.unsubscribe(); // Ensure cleanup on unmount
|
|
4277
|
+
};
|
|
4158
4278
|
}, [
|
|
4159
4279
|
programIdState,
|
|
4160
4280
|
orgUnitState,
|
|
@@ -4175,20 +4295,64 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4175
4295
|
},
|
|
4176
4296
|
}));
|
|
4177
4297
|
};
|
|
4298
|
+
// TODO: START::: Improve the approach on handling observables
|
|
4299
|
+
// const handleApprovalClick = () => {
|
|
4300
|
+
// setIsButtonLoading(true);
|
|
4301
|
+
// this.lineListService
|
|
4302
|
+
// .getLineListData(
|
|
4303
|
+
// this.programId,
|
|
4304
|
+
// this.orgUnit,
|
|
4305
|
+
// this.programStageId,
|
|
4306
|
+
// pager.page,
|
|
4307
|
+
// 1000,
|
|
4308
|
+
// this.attributeFilters,
|
|
4309
|
+
// this.startDate,
|
|
4310
|
+
// this.endDate,
|
|
4311
|
+
// this.ouMode
|
|
4312
|
+
// )
|
|
4313
|
+
// .subscribe((response: LineListResponse) => {
|
|
4314
|
+
// if (
|
|
4315
|
+
// 'trackedEntities' in response.data ||
|
|
4316
|
+
// 'instances' in response.data
|
|
4317
|
+
// ) {
|
|
4318
|
+
// const trackedEntityInstances = (
|
|
4319
|
+
// response.data as TrackedEntityResponse
|
|
4320
|
+
// ).trackedEntities;
|
|
4321
|
+
// // Map TEIs to objects with teiId and enrollmentId
|
|
4322
|
+
// const teiEnrollmentList = trackedEntityInstances
|
|
4323
|
+
// .map((tei) => {
|
|
4324
|
+
// // Find the enrollment where program matches this.programId
|
|
4325
|
+
// const matchingEnrollment = tei.enrollments?.find(
|
|
4326
|
+
// (enrollment) => enrollment.program === this.programId
|
|
4327
|
+
// );
|
|
4328
|
+
// // Return object with teiId and enrollmentId (if found)
|
|
4329
|
+
// return matchingEnrollment
|
|
4330
|
+
// ? {
|
|
4331
|
+
// teiId: tei.trackedEntity,
|
|
4332
|
+
// enrollmentId: matchingEnrollment.enrollment,
|
|
4333
|
+
// }
|
|
4334
|
+
// : null;
|
|
4335
|
+
// })
|
|
4336
|
+
// .filter((item) => item !== null); // Remove null entries (no matching enrollment)
|
|
4337
|
+
// this.approvalSelected.emit(teiEnrollmentList);
|
|
4338
|
+
// } else {
|
|
4339
|
+
// this.approvalSelected.emit([]); // Emit empty array if no TEIs
|
|
4340
|
+
// }
|
|
4341
|
+
// });
|
|
4342
|
+
// };
|
|
4343
|
+
// TODO: END::: Improve the approach on handling observables
|
|
4178
4344
|
const handleApprovalClick = () => {
|
|
4179
4345
|
setIsButtonLoading(true);
|
|
4180
|
-
this.lineListService
|
|
4346
|
+
const subscription = this.lineListService
|
|
4181
4347
|
.getLineListData(this.programId, this.orgUnit, this.programStageId, pager.page, 1000, this.attributeFilters, this.startDate, this.endDate, this.ouMode)
|
|
4348
|
+
.pipe(take(1)) // Ensures the observable emits only once
|
|
4182
4349
|
.subscribe((response) => {
|
|
4183
|
-
if (
|
|
4184
|
-
'instances' in response.data) {
|
|
4350
|
+
if ("trackedEntities" in response.data || "instances" in response.data) {
|
|
4185
4351
|
const trackedEntityInstances = response.data.trackedEntities;
|
|
4186
4352
|
// Map TEIs to objects with teiId and enrollmentId
|
|
4187
4353
|
const teiEnrollmentList = trackedEntityInstances
|
|
4188
4354
|
.map((tei) => {
|
|
4189
|
-
// Find the enrollment where program matches this.programId
|
|
4190
4355
|
const matchingEnrollment = tei.enrollments?.find((enrollment) => enrollment.program === this.programId);
|
|
4191
|
-
// Return object with teiId and enrollmentId (if found)
|
|
4192
4356
|
return matchingEnrollment
|
|
4193
4357
|
? {
|
|
4194
4358
|
teiId: tei.trackedEntity,
|
|
@@ -4196,13 +4360,17 @@ class LineListTableComponent extends ReactWrapperModule {
|
|
|
4196
4360
|
}
|
|
4197
4361
|
: null;
|
|
4198
4362
|
})
|
|
4199
|
-
.filter(
|
|
4363
|
+
.filter(Boolean); // Removes null entries
|
|
4200
4364
|
this.approvalSelected.emit(teiEnrollmentList);
|
|
4201
4365
|
}
|
|
4202
4366
|
else {
|
|
4203
4367
|
this.approvalSelected.emit([]); // Emit empty array if no TEIs
|
|
4204
4368
|
}
|
|
4369
|
+
setIsButtonLoading(false); // Stop loading after processing
|
|
4205
4370
|
});
|
|
4371
|
+
return () => {
|
|
4372
|
+
subscription.unsubscribe(); // Cleanup to avoid potential memory leaks
|
|
4373
|
+
};
|
|
4206
4374
|
};
|
|
4207
4375
|
const handleInputChange = (key, value) => {
|
|
4208
4376
|
setInputValues((prevValues) => ({
|
|
@@ -5975,9 +6143,24 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5975
6143
|
checkValueUniqueness();
|
|
5976
6144
|
}
|
|
5977
6145
|
}, [this.isValueAssigned()]);
|
|
6146
|
+
// TODO: START: Improve the approach of handling observables
|
|
6147
|
+
// useEffect(() => {
|
|
6148
|
+
// const fieldErrorSubscription = this.fieldError$
|
|
6149
|
+
// .pipe(filter((error) => error !== initialError))
|
|
6150
|
+
// .subscribe({
|
|
6151
|
+
// next: (error: string | undefined) => {
|
|
6152
|
+
// setInitialError(error);
|
|
6153
|
+
// },
|
|
6154
|
+
// });
|
|
6155
|
+
// return () => {
|
|
6156
|
+
// fieldErrorSubscription.unsubscribe();
|
|
6157
|
+
// };
|
|
6158
|
+
// });
|
|
6159
|
+
// TODO: END: Improve the approach of handling observables
|
|
5978
6160
|
useEffect(() => {
|
|
5979
6161
|
const fieldErrorSubscription = this.fieldError$
|
|
5980
|
-
.pipe(filter((error) => error !== initialError))
|
|
6162
|
+
.pipe(filter((error) => error !== initialError), take(1) // Take only the first emitted value, then unsubscribe
|
|
6163
|
+
)
|
|
5981
6164
|
.subscribe({
|
|
5982
6165
|
next: (error) => {
|
|
5983
6166
|
setInitialError(error);
|
|
@@ -5986,7 +6169,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5986
6169
|
return () => {
|
|
5987
6170
|
fieldErrorSubscription.unsubscribe();
|
|
5988
6171
|
};
|
|
5989
|
-
});
|
|
6172
|
+
}, [initialError]); // Add initialError as a dependency to avoid stale closures
|
|
5990
6173
|
const onChange = (payload) => setSelected(payload.selected);
|
|
5991
6174
|
const arrayValue = useMemo(() => {
|
|
5992
6175
|
if (value && value.length > 0) {
|
|
@@ -6873,14 +7056,30 @@ class SelectionFiltersComponent extends ReactWrapperModule {
|
|
|
6873
7056
|
const [selected, setSelected] = useState([]);
|
|
6874
7057
|
const [rootOrgUnits, setRootOrgUnits] = useState();
|
|
6875
7058
|
const [config, setConfig] = useState();
|
|
7059
|
+
// TODO: START::: Improve approach on handling observables
|
|
7060
|
+
// useEffect(() => {
|
|
7061
|
+
// zip(this.getAppConfig(), this.getRootOrgUnits()).subscribe({
|
|
7062
|
+
// next: ([appConfig, rootOrgUnits]) => {
|
|
7063
|
+
// setConfig(appConfig);
|
|
7064
|
+
// setRootOrgUnits(rootOrgUnits);
|
|
7065
|
+
// },
|
|
7066
|
+
// error: (error) => console.error(error),
|
|
7067
|
+
// });
|
|
7068
|
+
// }, []);
|
|
7069
|
+
// TODO: END::: Improve approach on handling observables
|
|
6876
7070
|
useEffect(() => {
|
|
6877
|
-
zip(this.getAppConfig(), this.getRootOrgUnits())
|
|
7071
|
+
const subscription = zip(this.getAppConfig(), this.getRootOrgUnits())
|
|
7072
|
+
.pipe(take(1)) // Ensures only one emission
|
|
7073
|
+
.subscribe({
|
|
6878
7074
|
next: ([appConfig, rootOrgUnits]) => {
|
|
6879
7075
|
setConfig(appConfig);
|
|
6880
7076
|
setRootOrgUnits(rootOrgUnits);
|
|
6881
7077
|
},
|
|
6882
7078
|
error: (error) => console.error(error),
|
|
6883
7079
|
});
|
|
7080
|
+
return () => {
|
|
7081
|
+
subscription.unsubscribe(); // Cleanup to avoid memory leaks
|
|
7082
|
+
};
|
|
6884
7083
|
}, []);
|
|
6885
7084
|
return config ? (React__default.createElement(Provider, { config: config, plugin: false, parentAlertsAdd: undefined, showAlertsInPlugin: false }, React__default.createElement(Modal$1, { position: "middle", large: true },
|
|
6886
7085
|
React__default.createElement(ModalTitle$1, null, "Organisation unit"),
|