@iapps/ng-dhis2-ui 1.1.55 → 1.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/iapps-ng-dhis2-ui.mjs +815 -133
- package/fesm2022/iapps-ng-dhis2-ui.mjs.map +1 -1
- package/index.d.ts +1 -0
- package/lib/modules/form/components/base-form-field.component.d.ts +3 -1
- package/lib/modules/form/containers/flat-form/flat-form.component.d.ts +11 -0
- package/lib/modules/form/containers/form-field/form-field.component.d.ts +1 -0
- package/lib/modules/form/form.module.d.ts +7 -6
- package/lib/modules/form/hooks/field-validation.hook.d.ts +3 -1
- package/lib/modules/form/index.d.ts +1 -0
- package/lib/modules/form/interfaces/form-field.interface.d.ts +1 -0
- package/lib/modules/form/models/form-field.model.d.ts +1 -0
- package/lib/modules/form/models/form-metadata-section.model.d.ts +1 -0
- package/lib/modules/form/shared/components/base-form-wrapper.component.d.ts +26 -0
- package/lib/modules/form/shared/components/index.d.ts +1 -0
- package/lib/modules/form/shared/index.d.ts +1 -0
- package/lib/modules/form/utils/field-type.util.d.ts +1 -1
- package/lib/modules/form/utils/field.util.d.ts +1 -1
- package/lib/modules/program-entry-form/index.d.ts +2 -0
- package/lib/modules/program-entry-form/models/index.d.ts +3 -0
- package/lib/modules/program-entry-form/models/program-entry-form-metadata.d.ts +28 -0
- package/lib/modules/program-entry-form/models/program-entry-form-section.model.d.ts +16 -0
- package/lib/modules/program-entry-form/models/program-entry-form.config.d.ts +47 -0
- package/lib/modules/program-entry-form/program-entry-form.component.d.ts +35 -0
- package/lib/modules/program-entry-form/utils/index.d.ts +2 -0
- package/lib/modules/program-entry-form/utils/program-entry-form-field.util.d.ts +63 -0
- package/lib/modules/program-entry-form/utils/program-entry-form-section.util.d.ts +8 -0
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { NgxDhis2HttpClientService } from '@iapps/ngx-dhis2-http-client';
|
|
|
8
8
|
import * as React from 'react';
|
|
9
9
|
import React__default, { useState, useCallback, useRef, useEffect, createContext, useContext, useMemo } from 'react';
|
|
10
10
|
import * as ReactDOM from 'react-dom/client';
|
|
11
|
-
import { catchError, of, map, zip, firstValueFrom, Subject, takeUntil } from 'rxjs';
|
|
11
|
+
import { catchError, of, map, zip, firstValueFrom, 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';
|
|
@@ -34,8 +34,8 @@ import * as i2 from '@angular/forms';
|
|
|
34
34
|
import { Validators, UntypedFormControl, UntypedFormGroup, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
|
35
35
|
import { toObservable } from '@angular/core/rxjs-interop';
|
|
36
36
|
import { format } from 'date-fns';
|
|
37
|
+
import { DataQueryFilter, DataFilterCondition, ProgramRuleEngine } from '@iapps/d2-web-sdk';
|
|
37
38
|
import moment from 'moment';
|
|
38
|
-
import { ProgramRuleEngine } from '@iapps/d2-web-sdk';
|
|
39
39
|
|
|
40
40
|
class SharedDhis2UiModule {
|
|
41
41
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: SharedDhis2UiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
@@ -4065,11 +4065,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
4065
4065
|
// Use of this source code is governed by a BSD-style
|
|
4066
4066
|
// license that can be found in the LICENSE file.
|
|
4067
4067
|
const useFieldValidation = (props) => {
|
|
4068
|
-
const { form, touched, field, value } = props;
|
|
4068
|
+
const { form, touched, field, value, initialError, recordExistError } = props;
|
|
4069
4069
|
const hasError = useMemo(() => {
|
|
4070
|
+
if (recordExistError) {
|
|
4071
|
+
return true;
|
|
4072
|
+
}
|
|
4073
|
+
if (initialError && value) {
|
|
4074
|
+
return true;
|
|
4075
|
+
}
|
|
4070
4076
|
return touched && (form.get(field.id) || form.get(field.key))?.invalid;
|
|
4071
|
-
}, [value, touched]);
|
|
4077
|
+
}, [value, touched, initialError, recordExistError]);
|
|
4072
4078
|
const validationError = useMemo(() => {
|
|
4079
|
+
if (recordExistError) {
|
|
4080
|
+
return recordExistError;
|
|
4081
|
+
}
|
|
4082
|
+
if (initialError && value) {
|
|
4083
|
+
return initialError;
|
|
4084
|
+
}
|
|
4073
4085
|
if (!touched) {
|
|
4074
4086
|
return undefined;
|
|
4075
4087
|
}
|
|
@@ -4080,25 +4092,26 @@ const useFieldValidation = (props) => {
|
|
|
4080
4092
|
if (error['min']) {
|
|
4081
4093
|
return `${field.label || 'Value'} should not be less than ${error['min'].min}!`;
|
|
4082
4094
|
}
|
|
4083
|
-
|
|
4095
|
+
if (error['max']) {
|
|
4084
4096
|
return `${field.label || 'Value'} should not be greater than ${error['max'].max}!`;
|
|
4085
4097
|
}
|
|
4086
|
-
|
|
4098
|
+
if (error['pattern']) {
|
|
4087
4099
|
if (field.type === 'email') {
|
|
4088
4100
|
return `The email address provided is not valid`;
|
|
4089
4101
|
}
|
|
4090
|
-
|
|
4102
|
+
if (field.type === 'tel') {
|
|
4091
4103
|
return 'Phone number provided is not valid';
|
|
4092
4104
|
}
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4105
|
+
return `${field.label || 'Value'} should have appropriate format`;
|
|
4106
|
+
}
|
|
4107
|
+
if (error['customError']) {
|
|
4108
|
+
return error['customError'];
|
|
4096
4109
|
}
|
|
4097
4110
|
return error['required']
|
|
4098
4111
|
? `${field.label || 'Value'} is required`
|
|
4099
4112
|
: undefined;
|
|
4100
|
-
}, [
|
|
4101
|
-
return {
|
|
4113
|
+
}, [touched, value, initialError, recordExistError]);
|
|
4114
|
+
return { validationError, hasError };
|
|
4102
4115
|
};
|
|
4103
4116
|
|
|
4104
4117
|
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
@@ -4134,6 +4147,7 @@ class FormField {
|
|
|
4134
4147
|
this.programStage = options.programStage;
|
|
4135
4148
|
this.program = options.program;
|
|
4136
4149
|
this.trackedEntityInstance = options.trackedEntityInstance;
|
|
4150
|
+
this.trackedEntityType = options.trackedEntityType;
|
|
4137
4151
|
this.hasOptions = options.hasOptions;
|
|
4138
4152
|
this.dependentField = options.dependentField;
|
|
4139
4153
|
this.displayInList = options.displayInList;
|
|
@@ -4319,6 +4333,8 @@ class FieldUtil {
|
|
|
4319
4333
|
return 'number';
|
|
4320
4334
|
case FieldType.PHONE_NUMBER:
|
|
4321
4335
|
return 'tel';
|
|
4336
|
+
case FieldType.EMAIL:
|
|
4337
|
+
return 'email';
|
|
4322
4338
|
case FieldType.ORG_UNIT:
|
|
4323
4339
|
return 'org-unit';
|
|
4324
4340
|
case FieldType.DATE:
|
|
@@ -4435,8 +4451,11 @@ class FormUtil {
|
|
|
4435
4451
|
const maxValidators = field.max
|
|
4436
4452
|
? [Validators.max(field.max)]
|
|
4437
4453
|
: [];
|
|
4438
|
-
const phoneNumberValidator = field.type === 'tel'
|
|
4439
|
-
|
|
4454
|
+
const phoneNumberValidator = field.type === 'tel' ? [] : [];
|
|
4455
|
+
const emailValidator = field.type === 'email'
|
|
4456
|
+
? [
|
|
4457
|
+
Validators.pattern('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$'),
|
|
4458
|
+
]
|
|
4440
4459
|
: [];
|
|
4441
4460
|
group[field.key] = field.required
|
|
4442
4461
|
? new UntypedFormControl({ value, disabled: field.disabled }, {
|
|
@@ -4445,6 +4464,7 @@ class FormUtil {
|
|
|
4445
4464
|
...minValidators,
|
|
4446
4465
|
...maxValidators,
|
|
4447
4466
|
...phoneNumberValidator,
|
|
4467
|
+
...emailValidator,
|
|
4448
4468
|
],
|
|
4449
4469
|
updateOn: 'change',
|
|
4450
4470
|
})
|
|
@@ -4453,6 +4473,7 @@ class FormUtil {
|
|
|
4453
4473
|
...minValidators,
|
|
4454
4474
|
...maxValidators,
|
|
4455
4475
|
...phoneNumberValidator,
|
|
4476
|
+
...emailValidator,
|
|
4456
4477
|
],
|
|
4457
4478
|
});
|
|
4458
4479
|
if (field.referenceKey) {
|
|
@@ -4466,6 +4487,7 @@ class FormUtil {
|
|
|
4466
4487
|
...minValidators,
|
|
4467
4488
|
...maxValidators,
|
|
4468
4489
|
...phoneNumberValidator,
|
|
4490
|
+
...emailValidator,
|
|
4469
4491
|
],
|
|
4470
4492
|
updateOn: 'change',
|
|
4471
4493
|
})
|
|
@@ -4474,6 +4496,7 @@ class FormUtil {
|
|
|
4474
4496
|
...minValidators,
|
|
4475
4497
|
...maxValidators,
|
|
4476
4498
|
...phoneNumberValidator,
|
|
4499
|
+
...emailValidator,
|
|
4477
4500
|
],
|
|
4478
4501
|
});
|
|
4479
4502
|
}
|
|
@@ -4692,6 +4715,9 @@ class MetadataRule {
|
|
|
4692
4715
|
const regex = /(A|#|V)\{([^}]+)\}/g;
|
|
4693
4716
|
return this.rule?.condition?.replace(regex, (match, _, ruleVariable) => {
|
|
4694
4717
|
const ruleVariableObject = this.ruleVariables?.find((variable) => variable.name === ruleVariable);
|
|
4718
|
+
if (!ruleVariableObject) {
|
|
4719
|
+
return `{${ruleVariable}}`;
|
|
4720
|
+
}
|
|
4695
4721
|
const code = camelCase(ruleVariableObject?.dataElement?.code) ||
|
|
4696
4722
|
ruleVariableObject?.dataElement?.id ||
|
|
4697
4723
|
camelCase(ruleVariableObject?.trackedEntityAttribute?.code) ||
|
|
@@ -4719,6 +4745,7 @@ class FormMetadataSection {
|
|
|
4719
4745
|
sortOrder: programTrackedEntityAttribute['sortOrder'],
|
|
4720
4746
|
mandatory: programTrackedEntityAttribute['mandatory'],
|
|
4721
4747
|
allowFutureDate: programTrackedEntityAttribute['allowFutureDate'],
|
|
4748
|
+
trackedEntityType: (this.params.program['trackedEntityType'] || {})['id'],
|
|
4722
4749
|
metaType: 'ATTRIBUTE',
|
|
4723
4750
|
};
|
|
4724
4751
|
});
|
|
@@ -5331,6 +5358,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5331
5358
|
this.httpClient = inject(NgxDhis2HttpClientService);
|
|
5332
5359
|
this.fieldType = 'textbox';
|
|
5333
5360
|
this.field = input.required();
|
|
5361
|
+
this.fieldError = input();
|
|
5334
5362
|
this.fieldConfig = input(new FieldConfig());
|
|
5335
5363
|
this.form = model.required();
|
|
5336
5364
|
this.isValid = input();
|
|
@@ -5338,6 +5366,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5338
5366
|
this.value = model();
|
|
5339
5367
|
this.value$ = toObservable(this.value);
|
|
5340
5368
|
this.isValueAssigned$ = toObservable(this.isValueAssigned);
|
|
5369
|
+
this.fieldError$ = toObservable(this.fieldError);
|
|
5341
5370
|
this.label = computed(() => {
|
|
5342
5371
|
return !this.fieldConfig()?.hideLabel ? this.field().label : undefined;
|
|
5343
5372
|
});
|
|
@@ -5369,13 +5398,30 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5369
5398
|
const [selected, setSelected] = useState();
|
|
5370
5399
|
const [touched, setTouched] = useState(false);
|
|
5371
5400
|
const [disabled, setDisabled] = useState(this.field()?.disabled ?? this.field()?.generated ?? false);
|
|
5401
|
+
const [initialError, setInitialError] = useState();
|
|
5402
|
+
const [recordExistError, setRecordExistError] = useState();
|
|
5403
|
+
const [checkingUniqueness, setCheckingUniqueness] = useState();
|
|
5372
5404
|
useEffect(() => {
|
|
5373
5405
|
if (this.isValueAssigned()) {
|
|
5406
|
+
const value = this.form().get(this.field().id)?.value ||
|
|
5407
|
+
this.form().get(this.field().key)?.value;
|
|
5374
5408
|
setDisabled(true);
|
|
5375
|
-
setValue(
|
|
5376
|
-
|
|
5409
|
+
setValue(value);
|
|
5410
|
+
checkValueUniqueness();
|
|
5377
5411
|
}
|
|
5378
5412
|
}, [this.isValueAssigned()]);
|
|
5413
|
+
useEffect(() => {
|
|
5414
|
+
const fieldErrorSubscription = this.fieldError$
|
|
5415
|
+
.pipe(filter((error) => error !== initialError))
|
|
5416
|
+
.subscribe({
|
|
5417
|
+
next: (error) => {
|
|
5418
|
+
setInitialError(error);
|
|
5419
|
+
},
|
|
5420
|
+
});
|
|
5421
|
+
return () => {
|
|
5422
|
+
fieldErrorSubscription.unsubscribe();
|
|
5423
|
+
};
|
|
5424
|
+
});
|
|
5379
5425
|
const onChange = (payload) => setSelected(payload.selected);
|
|
5380
5426
|
const arrayValue = useMemo(() => {
|
|
5381
5427
|
if (value && value.length > 0) {
|
|
@@ -5383,131 +5429,186 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5383
5429
|
}
|
|
5384
5430
|
return [];
|
|
5385
5431
|
}, [value]);
|
|
5386
|
-
const {
|
|
5432
|
+
const { validationError, hasError } = useFieldValidation({
|
|
5387
5433
|
field: this.field(),
|
|
5388
5434
|
form: this.form(),
|
|
5435
|
+
initialError,
|
|
5436
|
+
recordExistError,
|
|
5389
5437
|
value,
|
|
5390
5438
|
touched,
|
|
5391
5439
|
});
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5440
|
+
const checkValueUniqueness = async () => {
|
|
5441
|
+
if (this.field().unique && this.field().trackedEntityType) {
|
|
5442
|
+
setCheckingUniqueness(true);
|
|
5443
|
+
setRecordExistError(undefined);
|
|
5444
|
+
const d2 = window.d2Web;
|
|
5445
|
+
try {
|
|
5446
|
+
const response = (await d2.trackerModule.trackedEntity
|
|
5447
|
+
.setTrackedEntityType(this.field().trackedEntityType)
|
|
5448
|
+
.setOuMode('ACCESSIBLE')
|
|
5449
|
+
.setFilters([
|
|
5450
|
+
new DataQueryFilter()
|
|
5451
|
+
.setAttribute(this.field().id)
|
|
5452
|
+
.setCondition(DataFilterCondition.Equal)
|
|
5453
|
+
.setValue(value),
|
|
5454
|
+
])
|
|
5455
|
+
.get())?.data;
|
|
5456
|
+
setCheckingUniqueness(false);
|
|
5457
|
+
if (response?.length > 0) {
|
|
5458
|
+
const customError = `Record with this ${this.label()} is already registered`;
|
|
5459
|
+
(this.form().controls[this.field().id] ||
|
|
5460
|
+
this.form().controls[this.field().key])?.setErrors({
|
|
5461
|
+
customError,
|
|
5402
5462
|
});
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5463
|
+
setRecordExistError(customError);
|
|
5464
|
+
}
|
|
5465
|
+
}
|
|
5466
|
+
catch (e) {
|
|
5467
|
+
setCheckingUniqueness(false);
|
|
5468
|
+
setRecordExistError(undefined);
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
};
|
|
5472
|
+
const formFieldContent = () => {
|
|
5473
|
+
switch (this.field().controlType) {
|
|
5474
|
+
case 'textarea':
|
|
5475
|
+
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) => {
|
|
5476
|
+
this.ngZone.run(() => {
|
|
5477
|
+
(this.form().get(this.field().id) ||
|
|
5478
|
+
this.form().get(this.field().key))?.setValue(event.value);
|
|
5479
|
+
this.immediateUpdate.emit({
|
|
5480
|
+
form: this.form(),
|
|
5481
|
+
value: event.value,
|
|
5482
|
+
});
|
|
5418
5483
|
});
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5484
|
+
setValue(event.value);
|
|
5485
|
+
setTouched(true);
|
|
5486
|
+
}, onBlur: () => {
|
|
5487
|
+
checkValueUniqueness();
|
|
5488
|
+
this.ngZone.run(() => {
|
|
5489
|
+
this.update.emit({ form: this.form(), value });
|
|
5490
|
+
});
|
|
5491
|
+
} }));
|
|
5492
|
+
case 'org-unit':
|
|
5493
|
+
return (React__default.createElement(OrgUnitFormField, { label: this.label(), key: this.field().id, required: this.field().required, onSelectOrgUnit: (selectedOrgUnit) => {
|
|
5494
|
+
this.ngZone.run(() => {
|
|
5495
|
+
(this.form().get(this.field().id) ||
|
|
5496
|
+
this.form().get(this.field().key))?.setValue(selectedOrgUnit);
|
|
5497
|
+
this.update.emit({
|
|
5498
|
+
form: this.form(),
|
|
5499
|
+
value: selectedOrgUnit,
|
|
5500
|
+
});
|
|
5501
|
+
});
|
|
5502
|
+
setValue(selectedOrgUnit);
|
|
5503
|
+
setTouched(true);
|
|
5504
|
+
}, selected: value }));
|
|
5505
|
+
case 'transfer':
|
|
5506
|
+
return (React__default.createElement(Transfer, { filterable: true, filterPlaceholder: "Search", selected: selected, leftHeader: React__default.createElement("div", { style: {
|
|
5507
|
+
fontSize: 14,
|
|
5508
|
+
padding: '8px 4px',
|
|
5509
|
+
} }, this.field().availableOptionsLabel), rightHeader: React__default.createElement("div", { style: {
|
|
5510
|
+
fontSize: 14,
|
|
5511
|
+
padding: '8px 4px',
|
|
5512
|
+
} }, this.field().selectedOptionsLabel), options: this.field().options, onChange: (event) => {
|
|
5513
|
+
onChange({ selected: event.selected });
|
|
5514
|
+
this.ngZone.run(() => {
|
|
5515
|
+
(this.form().get(this.field().id) ||
|
|
5516
|
+
this.form().get(this.field().key))?.setValue(event.selected);
|
|
5517
|
+
});
|
|
5518
|
+
setValue(event.selected);
|
|
5519
|
+
setTouched(true);
|
|
5450
5520
|
this.update.emit({ form: this.form(), value });
|
|
5451
|
-
});
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
this.form().get(this.field().key))?.setValue(event.selected);
|
|
5458
|
-
this.update.emit({
|
|
5459
|
-
form: this.form(),
|
|
5460
|
-
value: event.selected,
|
|
5521
|
+
} }));
|
|
5522
|
+
case 'checkbox':
|
|
5523
|
+
return (React__default.createElement(Checkbox, { checked: Boolean(value), error: hasError, label: this.label(), name: this.field().id, disabled: disabled, onChange: (event) => {
|
|
5524
|
+
this.ngZone.run(() => {
|
|
5525
|
+
(this.form().get(this.field().id) ||
|
|
5526
|
+
this.form().get(this.field().key))?.setValue(event.checked);
|
|
5461
5527
|
});
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
const selectedValue = (event.selected || []).join(',');
|
|
5469
|
-
this.ngZone.run(() => {
|
|
5470
|
-
(this.form().get(this.field().id) ||
|
|
5471
|
-
this.form().get(this.field().key))?.setValue(selectedValue);
|
|
5472
|
-
this.update.emit({
|
|
5473
|
-
form: this.form(),
|
|
5474
|
-
value: selectedValue,
|
|
5528
|
+
setValue(event.checked);
|
|
5529
|
+
setTouched(true);
|
|
5530
|
+
}, onBlur: () => {
|
|
5531
|
+
checkValueUniqueness();
|
|
5532
|
+
this.ngZone.run(() => {
|
|
5533
|
+
this.update.emit({ form: this.form(), value });
|
|
5475
5534
|
});
|
|
5476
|
-
});
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
}, selected: arrayValue }, (this.field().options || []).map((option) => (React__default.createElement(MultiSelectOption, { key: option.key, label: option.label, value: option.value })))));
|
|
5480
|
-
case 'file':
|
|
5481
|
-
return (React__default.createElement(React__default.Fragment, null,
|
|
5482
|
-
React__default.createElement(FileUploadField, { label: this.label(), id: this.field().id, hasError: hasError, required: this.field().required, validationText: validationError, performUpload: true, uploadUrl: 'fileResources', onUploadSuccess: (fileId) => {
|
|
5535
|
+
} }));
|
|
5536
|
+
case 'dropdown':
|
|
5537
|
+
return (React__default.createElement(SingleSelectField, { filterable: (this.field().options || []).length > 5, clearable: true, error: hasError, validationText: validationError, inputWidth: this.fieldConfig()?.inputWidth, disabled: disabled, required: this.field().required, className: "select", label: this.label(), selected: value, onChange: (event) => {
|
|
5483
5538
|
this.ngZone.run(() => {
|
|
5484
|
-
this.form().get(this.field().id) ||
|
|
5485
|
-
this.form().get(this.field().key)?.setValue(
|
|
5539
|
+
(this.form().get(this.field().id) ||
|
|
5540
|
+
this.form().get(this.field().key))?.setValue(event.selected);
|
|
5486
5541
|
this.update.emit({
|
|
5487
5542
|
form: this.form(),
|
|
5488
|
-
value:
|
|
5543
|
+
value: event.selected,
|
|
5489
5544
|
});
|
|
5490
5545
|
});
|
|
5491
|
-
setValue(
|
|
5546
|
+
setValue(event.selected);
|
|
5492
5547
|
setTouched(true);
|
|
5493
|
-
}
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
this.
|
|
5500
|
-
|
|
5501
|
-
|
|
5548
|
+
}, onBlur: () => {
|
|
5549
|
+
checkValueUniqueness();
|
|
5550
|
+
} }, (this.field().options || []).map((option) => (React__default.createElement(SingleSelectOption, { key: crypto.randomUUID() || option.key, label: option.label, value: option.value })))));
|
|
5551
|
+
case 'multi-dropdown':
|
|
5552
|
+
return (React__default.createElement(MultiSelectField, { clearText: "Clear", clearable: true, empty: "No data found", filterable: (this.field().options || []).length > 5, filterPlaceholder: "Type to filter options", error: hasError, validationText: validationError, inputWidth: this.fieldConfig()?.inputWidth, disabled: disabled, label: this.label(), required: this.field().required, loadingText: "Loading options", noMatchText: "No options found", onChange: (event) => {
|
|
5553
|
+
const selectedValue = (event.selected || []).join(',');
|
|
5554
|
+
this.ngZone.run(() => {
|
|
5555
|
+
(this.form().get(this.field().id) ||
|
|
5556
|
+
this.form().get(this.field().key))?.setValue(selectedValue);
|
|
5557
|
+
this.update.emit({
|
|
5558
|
+
form: this.form(),
|
|
5559
|
+
value: selectedValue,
|
|
5560
|
+
});
|
|
5502
5561
|
});
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
this.
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5562
|
+
setValue(selectedValue);
|
|
5563
|
+
setTouched(true);
|
|
5564
|
+
}, onBlur: () => {
|
|
5565
|
+
checkValueUniqueness();
|
|
5566
|
+
}, selected: arrayValue }, (this.field().options || []).map((option) => (React__default.createElement(MultiSelectOption, { key: option.key, label: option.label, value: option.value })))));
|
|
5567
|
+
case 'file':
|
|
5568
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
5569
|
+
React__default.createElement(FileUploadField, { label: this.label(), id: this.field().id, hasError: hasError, required: this.field().required, validationText: validationError, performUpload: true, uploadUrl: 'fileResources', onUploadSuccess: (fileId) => {
|
|
5570
|
+
this.ngZone.run(() => {
|
|
5571
|
+
this.form().get(this.field().id) ||
|
|
5572
|
+
this.form().get(this.field().key)?.setValue(fileId);
|
|
5573
|
+
this.update.emit({
|
|
5574
|
+
form: this.form(),
|
|
5575
|
+
value: fileId,
|
|
5576
|
+
});
|
|
5577
|
+
});
|
|
5578
|
+
setValue(fileId);
|
|
5579
|
+
setTouched(true);
|
|
5580
|
+
} })));
|
|
5581
|
+
default:
|
|
5582
|
+
return (React__default.createElement(InputField$1, { error: hasError, validationText: validationError, type: this.field().type, inputWidth: this.fieldConfig()?.inputWidth, required: this.field().required, name: this.field().id, label: this.label(), min: this.field().min?.toString(), max: this.field().max?.toString(), placeholder: this.placeholder(), value: value, readOnly: disabled, onChange: (event) => {
|
|
5583
|
+
this.ngZone.run(() => {
|
|
5584
|
+
(this.form().get(this.field().id) ||
|
|
5585
|
+
this.form().get(this.field().key))?.setValue(event.value);
|
|
5586
|
+
this.immediateUpdate.emit({
|
|
5587
|
+
form: this.form(),
|
|
5588
|
+
value: event.value,
|
|
5589
|
+
});
|
|
5590
|
+
});
|
|
5591
|
+
setValue(event.value);
|
|
5592
|
+
setTouched(true);
|
|
5593
|
+
}, onBlur: () => {
|
|
5594
|
+
checkValueUniqueness();
|
|
5595
|
+
this.ngZone.run(() => {
|
|
5596
|
+
this.update.emit({ form: this.form(), value });
|
|
5597
|
+
});
|
|
5598
|
+
} }));
|
|
5599
|
+
}
|
|
5600
|
+
};
|
|
5601
|
+
{
|
|
5602
|
+
return (React__default.createElement(React__default.Fragment, null,
|
|
5603
|
+
formFieldContent(),
|
|
5604
|
+
checkingUniqueness && (React__default.createElement("div", { style: {
|
|
5605
|
+
display: 'flex',
|
|
5606
|
+
alignItems: 'center',
|
|
5607
|
+
gap: 8,
|
|
5608
|
+
paddingTop: 8,
|
|
5609
|
+
} },
|
|
5610
|
+
React__default.createElement(CircularLoader$1, { small: true }),
|
|
5611
|
+
React__default.createElement("div", { style: { color: colors$1.grey800, fontSize: 14 } }, "Checking...")))));
|
|
5511
5612
|
}
|
|
5512
5613
|
};
|
|
5513
5614
|
}
|
|
@@ -5515,7 +5616,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
5515
5616
|
this.value.set(event);
|
|
5516
5617
|
}
|
|
5517
5618
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: BaseFormFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
5518
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.1.8", type: BaseFormFieldComponent, isStandalone: true, inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, fieldConfig: { classPropertyName: "fieldConfig", publicName: "fieldConfig", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, isValid: { classPropertyName: "isValid", publicName: "isValid", isSignal: true, isRequired: false, transformFunction: null }, isValueAssigned: { classPropertyName: "isValueAssigned", publicName: "isValueAssigned", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { form: "formChange", value: "valueChange", update: "update", immediateUpdate: "immediateUpdate" }, usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
|
|
5619
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.1.8", type: BaseFormFieldComponent, isStandalone: true, inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, fieldError: { classPropertyName: "fieldError", publicName: "fieldError", isSignal: true, isRequired: false, transformFunction: null }, fieldConfig: { classPropertyName: "fieldConfig", publicName: "fieldConfig", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, isValid: { classPropertyName: "isValid", publicName: "isValid", isSignal: true, isRequired: false, transformFunction: null }, isValueAssigned: { classPropertyName: "isValueAssigned", publicName: "isValueAssigned", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { form: "formChange", value: "valueChange", update: "update", immediateUpdate: "immediateUpdate" }, usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
|
|
5519
5620
|
}
|
|
5520
5621
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: BaseFormFieldComponent, decorators: [{
|
|
5521
5622
|
type: Directive
|
|
@@ -5548,6 +5649,7 @@ class FormFieldComponent {
|
|
|
5548
5649
|
this.immediateFieldUpdate = new EventEmitter();
|
|
5549
5650
|
this.runtimeOptionChange = new EventEmitter();
|
|
5550
5651
|
this.value = signal('');
|
|
5652
|
+
this.runtimeError = signal(undefined);
|
|
5551
5653
|
this._runtimeOptions = [];
|
|
5552
5654
|
this.runtimeOptions = [];
|
|
5553
5655
|
this.fieldFilterControl = new FormControl();
|
|
@@ -5581,9 +5683,10 @@ class FormFieldComponent {
|
|
|
5581
5683
|
});
|
|
5582
5684
|
}
|
|
5583
5685
|
#processRules(ruleActions) {
|
|
5584
|
-
ruleActions
|
|
5585
|
-
|
|
5586
|
-
|
|
5686
|
+
const fieldRuleActions = ruleActions.filter((ruleAction) => ruleAction.field === this.field().id);
|
|
5687
|
+
let runtimeError;
|
|
5688
|
+
let isValueAssigned = false;
|
|
5689
|
+
fieldRuleActions.forEach((ruleAction) => {
|
|
5587
5690
|
switch (ruleAction.actionType) {
|
|
5588
5691
|
case 'ASSIGN': {
|
|
5589
5692
|
if (ruleAction.assignedData) {
|
|
@@ -5592,16 +5695,26 @@ class FormFieldComponent {
|
|
|
5592
5695
|
this.form
|
|
5593
5696
|
?.get(this.field().key)
|
|
5594
5697
|
?.setValue(ruleAction.assignedData);
|
|
5595
|
-
|
|
5698
|
+
isValueAssigned = true;
|
|
5596
5699
|
this.onValueChange();
|
|
5597
5700
|
}
|
|
5598
5701
|
}
|
|
5599
5702
|
break;
|
|
5600
5703
|
}
|
|
5704
|
+
case 'SHOWERROR': {
|
|
5705
|
+
runtimeError = ruleAction.displayedContent;
|
|
5706
|
+
(this.form.controls[this.field().id] ||
|
|
5707
|
+
this.form.controls[this.field().key])?.setErrors({
|
|
5708
|
+
customError: runtimeError,
|
|
5709
|
+
});
|
|
5710
|
+
break;
|
|
5711
|
+
}
|
|
5601
5712
|
default:
|
|
5602
5713
|
break;
|
|
5603
5714
|
}
|
|
5604
5715
|
});
|
|
5716
|
+
this.runtimeError.set(runtimeError);
|
|
5717
|
+
this.isValueAssigned.set(isValueAssigned);
|
|
5605
5718
|
}
|
|
5606
5719
|
ngOnDestroy() {
|
|
5607
5720
|
this._onDestroy.next();
|
|
@@ -5709,11 +5822,11 @@ class FormFieldComponent {
|
|
|
5709
5822
|
this._runtimeOptions = [...options];
|
|
5710
5823
|
}
|
|
5711
5824
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5712
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.1.8", type: FormFieldComponent, isStandalone: false, selector: "ng-dhis2-ui-form-field", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, fieldConfig: { classPropertyName: "fieldConfig", publicName: "fieldConfig", isSignal: false, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: false, isRequired: false, transformFunction: null }, isCheckBoxButton: { classPropertyName: "isCheckBoxButton", publicName: "isCheckBoxButton", isSignal: false, isRequired: false, transformFunction: null }, fieldClass: { classPropertyName: "fieldClass", publicName: "fieldClass", isSignal: false, isRequired: false, transformFunction: null }, programRuleActions: { classPropertyName: "programRuleActions", publicName: "programRuleActions", isSignal: true, isRequired: false, transformFunction: null }, dataEntities: { classPropertyName: "dataEntities", publicName: "dataEntities", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: false, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { fieldUpdate: "fieldUpdate", immediateFieldUpdate: "immediateFieldUpdate", runtimeOptionChange: "runtimeOptionChange" }, usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"field()\" class=\"form-field-item\">\n <ng-dhis2-ui-form-field-item\n [field]=\"field()\"\n [isValueAssigned]=\"isValueAssigned()\"\n [fieldConfig]=\"fieldConfig\"\n [(form)]=\"form\"\n [value]=\"value()\"\n (update)=\"onValueChange()\"\n (immediateUpdate)=\"onImmediateChange($event)\"\n />\n</div>\n", styles: [".form-field-item{margin-bottom:16px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormFieldItemComponent, selector: "ng-dhis2-ui-form-field-item" }] }); }
|
|
5825
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.1.8", type: FormFieldComponent, isStandalone: false, selector: "ng-dhis2-ui-form-field", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, fieldConfig: { classPropertyName: "fieldConfig", publicName: "fieldConfig", isSignal: false, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: false, isRequired: false, transformFunction: null }, isCheckBoxButton: { classPropertyName: "isCheckBoxButton", publicName: "isCheckBoxButton", isSignal: false, isRequired: false, transformFunction: null }, fieldClass: { classPropertyName: "fieldClass", publicName: "fieldClass", isSignal: false, isRequired: false, transformFunction: null }, programRuleActions: { classPropertyName: "programRuleActions", publicName: "programRuleActions", isSignal: true, isRequired: false, transformFunction: null }, dataEntities: { classPropertyName: "dataEntities", publicName: "dataEntities", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: false, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { fieldUpdate: "fieldUpdate", immediateFieldUpdate: "immediateFieldUpdate", runtimeOptionChange: "runtimeOptionChange" }, usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"field()\" class=\"form-field-item\">\n <ng-dhis2-ui-form-field-item\n [field]=\"field()\"\n [fieldError]=\"runtimeError()\"\n [isValueAssigned]=\"isValueAssigned()\"\n [fieldConfig]=\"fieldConfig\"\n [(form)]=\"form\"\n [value]=\"value()\"\n (update)=\"onValueChange()\"\n (immediateUpdate)=\"onImmediateChange($event)\"\n />\n</div>\n", styles: [".form-field-item{margin-bottom:16px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormFieldItemComponent, selector: "ng-dhis2-ui-form-field-item" }] }); }
|
|
5713
5826
|
}
|
|
5714
5827
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FormFieldComponent, decorators: [{
|
|
5715
5828
|
type: Component,
|
|
5716
|
-
args: [{ selector: 'ng-dhis2-ui-form-field', standalone: false, template: "<div *ngIf=\"field()\" class=\"form-field-item\">\n <ng-dhis2-ui-form-field-item\n [field]=\"field()\"\n [isValueAssigned]=\"isValueAssigned()\"\n [fieldConfig]=\"fieldConfig\"\n [(form)]=\"form\"\n [value]=\"value()\"\n (update)=\"onValueChange()\"\n (immediateUpdate)=\"onImmediateChange($event)\"\n />\n</div>\n", styles: [".form-field-item{margin-bottom:16px}\n"] }]
|
|
5829
|
+
args: [{ selector: 'ng-dhis2-ui-form-field', standalone: false, template: "<div *ngIf=\"field()\" class=\"form-field-item\">\n <ng-dhis2-ui-form-field-item\n [field]=\"field()\"\n [fieldError]=\"runtimeError()\"\n [isValueAssigned]=\"isValueAssigned()\"\n [fieldConfig]=\"fieldConfig\"\n [(form)]=\"form\"\n [value]=\"value()\"\n (update)=\"onValueChange()\"\n (immediateUpdate)=\"onImmediateChange($event)\"\n />\n</div>\n", styles: [".form-field-item{margin-bottom:16px}\n"] }]
|
|
5717
5830
|
}], ctorParameters: () => [], propDecorators: { fieldConfig: [{
|
|
5718
5831
|
type: Input
|
|
5719
5832
|
}], form: [{
|
|
@@ -6051,19 +6164,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
6051
6164
|
type: Output
|
|
6052
6165
|
}] } });
|
|
6053
6166
|
|
|
6167
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6168
|
+
// Use of this source code is governed by a BSD-style
|
|
6169
|
+
// license that can be found in the LICENSE file.
|
|
6170
|
+
class BaseFormWrapperComponent {
|
|
6171
|
+
#updatedDataValues;
|
|
6172
|
+
constructor() {
|
|
6173
|
+
this.ngZone = inject(NgZone);
|
|
6174
|
+
this.name = input();
|
|
6175
|
+
this.fields = input.required();
|
|
6176
|
+
this.rules = input([]);
|
|
6177
|
+
this.dataValues = input({});
|
|
6178
|
+
this.ruleActions = signal([]);
|
|
6179
|
+
this.isFormValid = signal(true);
|
|
6180
|
+
this.#updatedDataValues = signal({});
|
|
6181
|
+
this.formSave = new EventEmitter();
|
|
6182
|
+
this.formUpdate = new EventEmitter();
|
|
6183
|
+
this.formCancel = new EventEmitter();
|
|
6184
|
+
this.formValidityUpdate = new EventEmitter();
|
|
6185
|
+
this.ruleProcessor = effect(() => {
|
|
6186
|
+
if (this.#updatedDataValues()) {
|
|
6187
|
+
this.executeRules();
|
|
6188
|
+
}
|
|
6189
|
+
});
|
|
6190
|
+
}
|
|
6191
|
+
updateDataValues(dataValues) {
|
|
6192
|
+
this.#updatedDataValues.set(dataValues);
|
|
6193
|
+
this.formUpdate.emit(this.#updatedDataValues());
|
|
6194
|
+
}
|
|
6195
|
+
updateFormValidity(isFormValid) {
|
|
6196
|
+
this.isFormValid.set(isFormValid);
|
|
6197
|
+
this.formValidityUpdate.emit(isFormValid);
|
|
6198
|
+
}
|
|
6199
|
+
executeRules() {
|
|
6200
|
+
this.ruleActions.set(new ProgramRuleEngine()
|
|
6201
|
+
.setRules(this.rules())
|
|
6202
|
+
.setDataValues(this.#updatedDataValues())
|
|
6203
|
+
.execute());
|
|
6204
|
+
}
|
|
6205
|
+
ngOnDestroy() {
|
|
6206
|
+
this.ruleProcessor.destroy();
|
|
6207
|
+
}
|
|
6208
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: BaseFormWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
6209
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.1.8", type: BaseFormWrapperComponent, isStandalone: true, inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, rules: { classPropertyName: "rules", publicName: "rules", isSignal: true, isRequired: false, transformFunction: null }, dataValues: { classPropertyName: "dataValues", publicName: "dataValues", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formSave: "formSave", formUpdate: "formUpdate", formCancel: "formCancel", formValidityUpdate: "formValidityUpdate" }, ngImport: i0 }); }
|
|
6210
|
+
}
|
|
6211
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: BaseFormWrapperComponent, decorators: [{
|
|
6212
|
+
type: Directive
|
|
6213
|
+
}], ctorParameters: () => [], propDecorators: { formSave: [{
|
|
6214
|
+
type: Output
|
|
6215
|
+
}], formUpdate: [{
|
|
6216
|
+
type: Output
|
|
6217
|
+
}], formCancel: [{
|
|
6218
|
+
type: Output
|
|
6219
|
+
}], formValidityUpdate: [{
|
|
6220
|
+
type: Output
|
|
6221
|
+
}] } });
|
|
6222
|
+
|
|
6223
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6224
|
+
// Use of this source code is governed by a BSD-style
|
|
6225
|
+
// license that can be found in the LICENSE file.
|
|
6226
|
+
|
|
6227
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6228
|
+
// Use of this source code is governed by a BSD-style
|
|
6229
|
+
// license that can be found in the LICENSE file.
|
|
6230
|
+
|
|
6231
|
+
class FlatFormComponent extends BaseFormWrapperComponent {
|
|
6232
|
+
ngOnInit() {
|
|
6233
|
+
this.formGroup = FormUtil.getFormGroup(this.fields(), this.dataValues());
|
|
6234
|
+
}
|
|
6235
|
+
onFormUpdate() {
|
|
6236
|
+
this.updateDataValues(this.formGroup.getRawValue());
|
|
6237
|
+
this.updateFormValidity(this.formGroup.valid);
|
|
6238
|
+
}
|
|
6239
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FlatFormComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
6240
|
+
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"] }] }); }
|
|
6241
|
+
}
|
|
6242
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: FlatFormComponent, decorators: [{
|
|
6243
|
+
type: Component,
|
|
6244
|
+
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" }]
|
|
6245
|
+
}] });
|
|
6246
|
+
|
|
6054
6247
|
class D2FormModule {
|
|
6055
6248
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: D2FormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
6056
6249
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.8", ngImport: i0, type: D2FormModule, declarations: [FormFieldComponent,
|
|
6057
6250
|
FormComponent,
|
|
6058
6251
|
RepeatableFormComponent,
|
|
6059
6252
|
SectionFormComponent,
|
|
6253
|
+
FlatFormComponent,
|
|
6060
6254
|
FormFieldItemComponent], imports: [CommonModule,
|
|
6061
6255
|
ReactiveFormsModule,
|
|
6062
6256
|
ReactWrapperModule,
|
|
6063
6257
|
OrganisationUnitSelectorModule], exports: [FormFieldComponent,
|
|
6064
6258
|
FormComponent,
|
|
6065
6259
|
RepeatableFormComponent,
|
|
6066
|
-
SectionFormComponent
|
|
6260
|
+
SectionFormComponent,
|
|
6261
|
+
FlatFormComponent] }); }
|
|
6067
6262
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: D2FormModule, imports: [CommonModule,
|
|
6068
6263
|
ReactiveFormsModule,
|
|
6069
6264
|
OrganisationUnitSelectorModule] }); }
|
|
@@ -6076,6 +6271,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
6076
6271
|
FormComponent,
|
|
6077
6272
|
RepeatableFormComponent,
|
|
6078
6273
|
SectionFormComponent,
|
|
6274
|
+
FlatFormComponent,
|
|
6079
6275
|
FormFieldItemComponent,
|
|
6080
6276
|
],
|
|
6081
6277
|
imports: [
|
|
@@ -6089,6 +6285,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
6089
6285
|
FormComponent,
|
|
6090
6286
|
RepeatableFormComponent,
|
|
6091
6287
|
SectionFormComponent,
|
|
6288
|
+
FlatFormComponent,
|
|
6092
6289
|
],
|
|
6093
6290
|
}]
|
|
6094
6291
|
}] });
|
|
@@ -6536,9 +6733,494 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImpor
|
|
|
6536
6733
|
// Use of this source code is governed by a BSD-style
|
|
6537
6734
|
// license that can be found in the LICENSE file.
|
|
6538
6735
|
|
|
6736
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6737
|
+
// Use of this source code is governed by a BSD-style
|
|
6738
|
+
// license that can be found in the LICENSE file.
|
|
6739
|
+
class ProgramEntryFormConfig {
|
|
6740
|
+
constructor(config) {
|
|
6741
|
+
this.displayType = 'FLAT';
|
|
6742
|
+
this.submitButtonLabel = 'Submit';
|
|
6743
|
+
this.cancelButtonLabel = 'Cancel';
|
|
6744
|
+
Object.assign(this, config);
|
|
6745
|
+
}
|
|
6746
|
+
}
|
|
6747
|
+
|
|
6748
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6749
|
+
// Use of this source code is governed by a BSD-style
|
|
6750
|
+
// license that can be found in the LICENSE file.
|
|
6751
|
+
class ProgramEntryFormFieldUtil {
|
|
6752
|
+
constructor(program, config) {
|
|
6753
|
+
this.program = program;
|
|
6754
|
+
this.config = config;
|
|
6755
|
+
}
|
|
6756
|
+
get attributes() {
|
|
6757
|
+
return (this.program.programTrackedEntityAttributes || []).map((programTrackedEntityAttribute) => {
|
|
6758
|
+
return {
|
|
6759
|
+
...programTrackedEntityAttribute.trackedEntityAttribute,
|
|
6760
|
+
sortOrder: programTrackedEntityAttribute.sortOrder,
|
|
6761
|
+
mandatory: programTrackedEntityAttribute.mandatory,
|
|
6762
|
+
allowFutureDate: programTrackedEntityAttribute.allowFutureDate,
|
|
6763
|
+
trackedEntityType: this.program.trackedEntityType?.id,
|
|
6764
|
+
metaType: 'ATTRIBUTE',
|
|
6765
|
+
stepId: null,
|
|
6766
|
+
};
|
|
6767
|
+
});
|
|
6768
|
+
}
|
|
6769
|
+
get dataElements() {
|
|
6770
|
+
return flatten((this.program.programStages || []).map((programStage) => {
|
|
6771
|
+
return (programStage.programStageDataElements || []).map((stageDataElement) => {
|
|
6772
|
+
return {
|
|
6773
|
+
...stageDataElement.dataElement,
|
|
6774
|
+
sortOrder: stageDataElement.sortOrder,
|
|
6775
|
+
mandatory: stageDataElement.compulsory,
|
|
6776
|
+
allowFutureDate: stageDataElement.allowFutureDate,
|
|
6777
|
+
stepId: programStage.id,
|
|
6778
|
+
metaType: 'DATA_ELEMENT',
|
|
6779
|
+
};
|
|
6780
|
+
});
|
|
6781
|
+
}));
|
|
6782
|
+
}
|
|
6783
|
+
#getOrgUniField() {
|
|
6784
|
+
if (this.config.hideRegistrationUnit) {
|
|
6785
|
+
return null;
|
|
6786
|
+
}
|
|
6787
|
+
return new FormField({
|
|
6788
|
+
id: 'orgUnit',
|
|
6789
|
+
key: 'orgUnit',
|
|
6790
|
+
label: this.program.orgUnitLabel || 'Registering unit',
|
|
6791
|
+
code: 'orgUnit',
|
|
6792
|
+
required: true,
|
|
6793
|
+
controlType: 'org-unit',
|
|
6794
|
+
disabled: this.config.disableRegistrationUnit,
|
|
6795
|
+
});
|
|
6796
|
+
}
|
|
6797
|
+
#getEnrollmentDateField() {
|
|
6798
|
+
if (this.config.hideEnrollmentDate) {
|
|
6799
|
+
return null;
|
|
6800
|
+
}
|
|
6801
|
+
return new FormField({
|
|
6802
|
+
id: 'enrollmentDate',
|
|
6803
|
+
label: this.program.enrollmentDateLabel || 'Enrollment date',
|
|
6804
|
+
code: 'enrollmentDate',
|
|
6805
|
+
key: 'enrollmentDate',
|
|
6806
|
+
required: true,
|
|
6807
|
+
type: 'date',
|
|
6808
|
+
controlType: 'date',
|
|
6809
|
+
disabled: this.config.disableEnrollmentDate,
|
|
6810
|
+
});
|
|
6811
|
+
}
|
|
6812
|
+
#getIncidentDateField() {
|
|
6813
|
+
if (!this.program.displayIncidentDate) {
|
|
6814
|
+
return null;
|
|
6815
|
+
}
|
|
6816
|
+
return new DateField({
|
|
6817
|
+
id: 'incidentDate',
|
|
6818
|
+
label: this.program.incidentDateLabel || 'Incident date',
|
|
6819
|
+
code: 'incidentDate',
|
|
6820
|
+
key: 'incidentDate',
|
|
6821
|
+
required: true,
|
|
6822
|
+
type: 'date',
|
|
6823
|
+
controlType: 'date',
|
|
6824
|
+
disabled: this.config.disabledIncidentDate,
|
|
6825
|
+
});
|
|
6826
|
+
}
|
|
6827
|
+
get reportFields() {
|
|
6828
|
+
return [
|
|
6829
|
+
this.#getOrgUniField(),
|
|
6830
|
+
this.#getEnrollmentDateField(),
|
|
6831
|
+
this.#getIncidentDateField(),
|
|
6832
|
+
].filter((field) => field != null);
|
|
6833
|
+
}
|
|
6834
|
+
get fields() {
|
|
6835
|
+
const fields = [...this.attributes, ...this.dataElements]
|
|
6836
|
+
.map((field) => {
|
|
6837
|
+
const options = FieldDropdown.getDropdownOptions(field);
|
|
6838
|
+
const hasOptions = options?.length > 0;
|
|
6839
|
+
return new FormField({
|
|
6840
|
+
...field,
|
|
6841
|
+
id: field.id,
|
|
6842
|
+
code: field.code,
|
|
6843
|
+
label: field.formName || field.name,
|
|
6844
|
+
key: field.code ? camelCase(field.code) : field.id,
|
|
6845
|
+
required: field.mandatory,
|
|
6846
|
+
type: FieldUtil.getFieldType(field.valueType),
|
|
6847
|
+
options,
|
|
6848
|
+
disabled: this.#getDisabledStatus(field),
|
|
6849
|
+
order: field.sortOrder,
|
|
6850
|
+
hasOptions,
|
|
6851
|
+
controlType: FieldUtil.getFieldControlType(field.valueType, hasOptions),
|
|
6852
|
+
metaType: field.metaType,
|
|
6853
|
+
stepId: field.stepId,
|
|
6854
|
+
});
|
|
6855
|
+
})
|
|
6856
|
+
.sort((a, b) => a.order ?? 0 - (b.order ?? 0));
|
|
6857
|
+
return [...this.reportFields, ...fields];
|
|
6858
|
+
}
|
|
6859
|
+
#getDisabledStatus(field) {
|
|
6860
|
+
if (field?.generated) {
|
|
6861
|
+
return true;
|
|
6862
|
+
}
|
|
6863
|
+
if (this.config.autoAssignedValues &&
|
|
6864
|
+
this.config.autoAssignedValues.length > 0) {
|
|
6865
|
+
const key = field.code ? camelCase(field.code) : field.id;
|
|
6866
|
+
const assignedValue = (this.config.autoAssignedValues || []).find((assignedValue) => assignedValue.field === key)?.value;
|
|
6867
|
+
return !isUndefined(assignedValue);
|
|
6868
|
+
}
|
|
6869
|
+
return false;
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
|
|
6873
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6874
|
+
// Use of this source code is governed by a BSD-style
|
|
6875
|
+
// license that can be found in the LICENSE file.
|
|
6876
|
+
class ProgramEntryFormSectionUtil {
|
|
6877
|
+
constructor(program, config) {
|
|
6878
|
+
this.program = program;
|
|
6879
|
+
this.config = config;
|
|
6880
|
+
}
|
|
6881
|
+
get sections() {
|
|
6882
|
+
return [];
|
|
6883
|
+
}
|
|
6884
|
+
}
|
|
6885
|
+
|
|
6886
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6887
|
+
// Use of this source code is governed by a BSD-style
|
|
6888
|
+
// license that can be found in the LICENSE file.
|
|
6889
|
+
|
|
6890
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
6891
|
+
// Use of this source code is governed by a BSD-style
|
|
6892
|
+
// license that can be found in the LICENSE file.
|
|
6893
|
+
class ProgramEntryFormMetaData {
|
|
6894
|
+
constructor() {
|
|
6895
|
+
this.d2 = window?.d2Web;
|
|
6896
|
+
}
|
|
6897
|
+
setConfig(config) {
|
|
6898
|
+
this.config = config;
|
|
6899
|
+
return this;
|
|
6900
|
+
}
|
|
6901
|
+
getProgramPromise() {
|
|
6902
|
+
const program = this.config.program;
|
|
6903
|
+
const programQuery = this.d2.programModule.program
|
|
6904
|
+
.select([
|
|
6905
|
+
'id',
|
|
6906
|
+
'code',
|
|
6907
|
+
'name',
|
|
6908
|
+
'captureCoordinates',
|
|
6909
|
+
'featureType',
|
|
6910
|
+
'enrollmentDateLabel',
|
|
6911
|
+
'incidentDateLabel',
|
|
6912
|
+
'displayIncidentDate',
|
|
6913
|
+
'onlyEnrollOnce',
|
|
6914
|
+
'orgUnitLabel',
|
|
6915
|
+
'programType',
|
|
6916
|
+
'useFirstStageDuringRegistration',
|
|
6917
|
+
'trackedEntityType',
|
|
6918
|
+
])
|
|
6919
|
+
.with(this.d2.programModule.programTrackedEntityAttribute.with(this.d2.programModule.trackedEntityAttribute.with(this.d2.optionSetModule.optionSet.with(this.d2.optionSetModule.option), 'ToOne'), 'ToOne'))
|
|
6920
|
+
.with(this.d2.programModule.programRuleVariable
|
|
6921
|
+
.with(this.d2.dataElementModule.dataElement.select([
|
|
6922
|
+
'id',
|
|
6923
|
+
'code',
|
|
6924
|
+
'name',
|
|
6925
|
+
]), 'ToOne')
|
|
6926
|
+
.with(this.d2.programModule.trackedEntityAttribute.select([
|
|
6927
|
+
'id',
|
|
6928
|
+
'code',
|
|
6929
|
+
'name',
|
|
6930
|
+
]), 'ToOne'))
|
|
6931
|
+
.byId(program);
|
|
6932
|
+
if (this.config.displayType === 'FLAT') {
|
|
6933
|
+
programQuery.with(this.d2.programModule.programSection.with(this.d2.programModule.trackedEntityAttribute.select(['id'])));
|
|
6934
|
+
}
|
|
6935
|
+
if (!this.config.excludeProgramStages) {
|
|
6936
|
+
programQuery.with(this.d2.programModule.programStage
|
|
6937
|
+
.with(this.d2.programModule.programStageSection)
|
|
6938
|
+
.with(this.d2.programModule.programStageDataElement.with(this.d2.dataElementModule.dataElement.with(this.d2.optionSetModule.optionSet.with(this.d2.optionSetModule.option), 'ToOne'), 'ToOne')));
|
|
6939
|
+
}
|
|
6940
|
+
return programQuery.get();
|
|
6941
|
+
}
|
|
6942
|
+
async #getProgramMetaData() {
|
|
6943
|
+
const program = this.config.program;
|
|
6944
|
+
if (!this.d2) {
|
|
6945
|
+
return null;
|
|
6946
|
+
}
|
|
6947
|
+
const metaDataResponse = await Promise.all([
|
|
6948
|
+
this.getProgramPromise(),
|
|
6949
|
+
this.d2.programModule.programRule
|
|
6950
|
+
.where({
|
|
6951
|
+
attribute: 'program.id',
|
|
6952
|
+
value: program,
|
|
6953
|
+
})
|
|
6954
|
+
.with(this.d2.programModule.programRuleAction
|
|
6955
|
+
.select([
|
|
6956
|
+
'id',
|
|
6957
|
+
'programRuleActionType',
|
|
6958
|
+
'data',
|
|
6959
|
+
'displayContent',
|
|
6960
|
+
'content',
|
|
6961
|
+
])
|
|
6962
|
+
.with(this.d2.dataElementModule.dataElement.select([
|
|
6963
|
+
'id',
|
|
6964
|
+
'code',
|
|
6965
|
+
'name',
|
|
6966
|
+
]), 'ToOne')
|
|
6967
|
+
.with(this.d2.programModule.trackedEntityAttribute.select([
|
|
6968
|
+
'id',
|
|
6969
|
+
'code',
|
|
6970
|
+
'name',
|
|
6971
|
+
]), 'ToOne')
|
|
6972
|
+
.with(this.d2.optionSetModule.optionGroup
|
|
6973
|
+
.select(['id'])
|
|
6974
|
+
.with(this.d2.optionSetModule.option.select([
|
|
6975
|
+
'id',
|
|
6976
|
+
'code',
|
|
6977
|
+
'displayName',
|
|
6978
|
+
]), 'ToMany'), 'ToOne')
|
|
6979
|
+
.with(this.d2.optionSetModule.option.select([
|
|
6980
|
+
'id',
|
|
6981
|
+
'code',
|
|
6982
|
+
'displayName',
|
|
6983
|
+
]), 'ToOne'))
|
|
6984
|
+
.get(),
|
|
6985
|
+
]);
|
|
6986
|
+
const [programResponse, programRuleResponse] = metaDataResponse;
|
|
6987
|
+
const metaData = programResponse.data;
|
|
6988
|
+
metaData.programRules = programRuleResponse.data;
|
|
6989
|
+
return metaData;
|
|
6990
|
+
}
|
|
6991
|
+
get formFields() {
|
|
6992
|
+
if (!this.metaData) {
|
|
6993
|
+
return [];
|
|
6994
|
+
}
|
|
6995
|
+
return new ProgramEntryFormFieldUtil(this.metaData, this.config).fields;
|
|
6996
|
+
}
|
|
6997
|
+
get sections() {
|
|
6998
|
+
if (!this.metaData || this.config.displayType !== 'SECTION') {
|
|
6999
|
+
return [];
|
|
7000
|
+
}
|
|
7001
|
+
return new ProgramEntryFormSectionUtil(this.metaData, this.config).sections;
|
|
7002
|
+
}
|
|
7003
|
+
get rules() {
|
|
7004
|
+
if (!this.metaData || !this.metaData.programRules) {
|
|
7005
|
+
return [];
|
|
7006
|
+
}
|
|
7007
|
+
return this.metaData.programRules.map((programRule) => new MetadataRule(programRule, this.metaData.programRuleVariables || []).toJson());
|
|
7008
|
+
}
|
|
7009
|
+
toJson() {
|
|
7010
|
+
return {
|
|
7011
|
+
id: this.metaData?.id,
|
|
7012
|
+
name: this.metaData?.name,
|
|
7013
|
+
description: this.metaData?.description,
|
|
7014
|
+
formFields: this.formFields,
|
|
7015
|
+
sections: this.sections,
|
|
7016
|
+
rules: this.rules,
|
|
7017
|
+
};
|
|
7018
|
+
}
|
|
7019
|
+
async get() {
|
|
7020
|
+
try {
|
|
7021
|
+
const metaData = await this.#getProgramMetaData();
|
|
7022
|
+
if (metaData) {
|
|
7023
|
+
this.metaData = metaData;
|
|
7024
|
+
return this.toJson();
|
|
7025
|
+
}
|
|
7026
|
+
return null;
|
|
7027
|
+
}
|
|
7028
|
+
catch (err) {
|
|
7029
|
+
return null;
|
|
7030
|
+
}
|
|
7031
|
+
}
|
|
7032
|
+
}
|
|
7033
|
+
|
|
7034
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
7035
|
+
// Use of this source code is governed by a BSD-style
|
|
7036
|
+
// license that can be found in the LICENSE file.
|
|
7037
|
+
class ProgramEntryFormSection {
|
|
7038
|
+
constructor(props) {
|
|
7039
|
+
this.formFields = [];
|
|
7040
|
+
this.orientation = 'HORIZONTAL';
|
|
7041
|
+
Object.assign(this, props);
|
|
7042
|
+
}
|
|
7043
|
+
}
|
|
7044
|
+
|
|
7045
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
7046
|
+
// Use of this source code is governed by a BSD-style
|
|
7047
|
+
// license that can be found in the LICENSE file.
|
|
7048
|
+
|
|
7049
|
+
// eslint-disable-next-line @angular-eslint/component-class-suffix
|
|
7050
|
+
class ProgramEntryFormModule {
|
|
7051
|
+
constructor() {
|
|
7052
|
+
this.config = input.required();
|
|
7053
|
+
this.trackedEntity = input();
|
|
7054
|
+
this.event = input();
|
|
7055
|
+
this.enrollment = input();
|
|
7056
|
+
this.orgUnit = input();
|
|
7057
|
+
this.ngZone = inject(NgZone);
|
|
7058
|
+
this.d2 = window.d2Web;
|
|
7059
|
+
this.loading = signal(false);
|
|
7060
|
+
this.metaData = signal(null);
|
|
7061
|
+
this.isFormValid = signal(true);
|
|
7062
|
+
this.isFormValid$ = toObservable(this.isFormValid);
|
|
7063
|
+
this.instance = signal(null);
|
|
7064
|
+
this.instanceSave = new EventEmitter();
|
|
7065
|
+
this.instanceSaveCompleted = new EventEmitter();
|
|
7066
|
+
this.instanceUpdate = new EventEmitter();
|
|
7067
|
+
this.formValidityUpdate = new EventEmitter();
|
|
7068
|
+
this.formCancel = new EventEmitter();
|
|
7069
|
+
this.FormLoader = () => {
|
|
7070
|
+
return React__default.createElement(CircularLoader$1, { small: true });
|
|
7071
|
+
};
|
|
7072
|
+
this.FormActionButtons = computed(() => {
|
|
7073
|
+
if (this.config().hideActionButtons) {
|
|
7074
|
+
return React__default.createElement(React__default.Fragment, null);
|
|
7075
|
+
}
|
|
7076
|
+
return () => {
|
|
7077
|
+
const [isValid, setIsValid] = useState();
|
|
7078
|
+
const [submitting, setSubmitting] = useState(false);
|
|
7079
|
+
useEffect(() => {
|
|
7080
|
+
const isValidSubscription = this.isFormValid$.subscribe((isValid) => {
|
|
7081
|
+
setIsValid(isValid);
|
|
7082
|
+
});
|
|
7083
|
+
return () => {
|
|
7084
|
+
isValidSubscription.unsubscribe();
|
|
7085
|
+
};
|
|
7086
|
+
}, []);
|
|
7087
|
+
const onSave = () => {
|
|
7088
|
+
setSubmitting(true);
|
|
7089
|
+
this.ngZone.run(async () => {
|
|
7090
|
+
const saveResponse = await this.#saveInstance();
|
|
7091
|
+
this.instanceSaveCompleted.emit(saveResponse);
|
|
7092
|
+
setSubmitting(false);
|
|
7093
|
+
});
|
|
7094
|
+
};
|
|
7095
|
+
return (React__default.createElement(ButtonStrip$1, null,
|
|
7096
|
+
!this.config().hideSubmitButton && (React__default.createElement(Button$1, { primary: true, disabled: !isValid, loading: submitting, onClick: onSave }, this.config().submitButtonLabel)),
|
|
7097
|
+
!this.config().hideCancelButton && (React__default.createElement(Button$1, { onClick: () => {
|
|
7098
|
+
this.ngZone.run(() => {
|
|
7099
|
+
this.onCancel();
|
|
7100
|
+
});
|
|
7101
|
+
} }, this.config().cancelButtonLabel))));
|
|
7102
|
+
};
|
|
7103
|
+
});
|
|
7104
|
+
}
|
|
7105
|
+
async ngOnInit() {
|
|
7106
|
+
this.loading.set(true);
|
|
7107
|
+
try {
|
|
7108
|
+
// Loading metadata
|
|
7109
|
+
const metaData = await new ProgramEntryFormMetaData()
|
|
7110
|
+
.setConfig(this.config())
|
|
7111
|
+
.get();
|
|
7112
|
+
this.metaData.set(metaData);
|
|
7113
|
+
// Load initial instance information
|
|
7114
|
+
const instance = await this.#getInstance();
|
|
7115
|
+
this.instance.set(instance);
|
|
7116
|
+
if (this.config().autoAssignedValues) {
|
|
7117
|
+
this.#updateInstanceWithAutoAssignedValues(this.config().autoAssignedValues || []);
|
|
7118
|
+
}
|
|
7119
|
+
this.loading.set(false);
|
|
7120
|
+
}
|
|
7121
|
+
catch (err) {
|
|
7122
|
+
this.loading.set(false);
|
|
7123
|
+
}
|
|
7124
|
+
}
|
|
7125
|
+
onFormUpdate(dataValues) {
|
|
7126
|
+
this.#updateInstance(dataValues);
|
|
7127
|
+
if (this.instance()) {
|
|
7128
|
+
this.instanceUpdate.emit(this.instance());
|
|
7129
|
+
}
|
|
7130
|
+
}
|
|
7131
|
+
onValidityUpdate(isFormValid) {
|
|
7132
|
+
this.isFormValid.set(isFormValid);
|
|
7133
|
+
this.formValidityUpdate.emit(isFormValid);
|
|
7134
|
+
}
|
|
7135
|
+
onCancel() {
|
|
7136
|
+
this.formCancel.emit();
|
|
7137
|
+
}
|
|
7138
|
+
#updateInstanceWithAutoAssignedValues(autoAssignedValues) {
|
|
7139
|
+
const assignedDataValues = autoAssignedValues.reduce((entities, assignedValue) => {
|
|
7140
|
+
return {
|
|
7141
|
+
...entities,
|
|
7142
|
+
[assignedValue.field]: assignedValue.value,
|
|
7143
|
+
};
|
|
7144
|
+
}, {});
|
|
7145
|
+
this.#updateInstance(assignedDataValues);
|
|
7146
|
+
}
|
|
7147
|
+
#updateInstance(dataValues) {
|
|
7148
|
+
this.instance.update((instance) => {
|
|
7149
|
+
instance?.updateDataValues(dataValues);
|
|
7150
|
+
return instance;
|
|
7151
|
+
});
|
|
7152
|
+
}
|
|
7153
|
+
async #saveInstance() {
|
|
7154
|
+
switch (this.config().formType) {
|
|
7155
|
+
case 'TRACKER':
|
|
7156
|
+
return this.instanceQuery
|
|
7157
|
+
.setData(this.instance())
|
|
7158
|
+
.save();
|
|
7159
|
+
case 'EVENT':
|
|
7160
|
+
return this.instanceQuery
|
|
7161
|
+
.setData(this.instance())
|
|
7162
|
+
.save();
|
|
7163
|
+
default:
|
|
7164
|
+
return firstValueFrom(of(null));
|
|
7165
|
+
}
|
|
7166
|
+
}
|
|
7167
|
+
async #getTrackerInstance() {
|
|
7168
|
+
this.instanceQuery = this.d2.trackerModule.trackedEntity
|
|
7169
|
+
.setProgram(this.config().program)
|
|
7170
|
+
.setOrgUnit(this.orgUnit());
|
|
7171
|
+
return this.trackedEntity()
|
|
7172
|
+
? (await this.instanceQuery
|
|
7173
|
+
.setTrackedEntity(this.trackedEntity())
|
|
7174
|
+
.get()).data || (await this.instanceQuery.create())
|
|
7175
|
+
: await this.instanceQuery.create();
|
|
7176
|
+
}
|
|
7177
|
+
async #getEventInstance() {
|
|
7178
|
+
this.instanceQuery = this.d2.eventModule.event
|
|
7179
|
+
.setProgram(this.config().program)
|
|
7180
|
+
.setProgramStage(this.config().programStage)
|
|
7181
|
+
.setEnrollment(this.enrollment())
|
|
7182
|
+
.setTrackedEntity(this.trackedEntity())
|
|
7183
|
+
.setOrgUnit(this.orgUnit());
|
|
7184
|
+
return this.event()
|
|
7185
|
+
? (await this.instanceQuery.setEvent(this.event()).get())
|
|
7186
|
+
.data || (await this.instanceQuery.create())
|
|
7187
|
+
: await this.instanceQuery.create();
|
|
7188
|
+
}
|
|
7189
|
+
#getInstance() {
|
|
7190
|
+
switch (this.config().formType) {
|
|
7191
|
+
case 'TRACKER':
|
|
7192
|
+
return this.#getTrackerInstance();
|
|
7193
|
+
case 'EVENT':
|
|
7194
|
+
return this.#getEventInstance();
|
|
7195
|
+
default:
|
|
7196
|
+
return firstValueFrom(of(null));
|
|
7197
|
+
}
|
|
7198
|
+
}
|
|
7199
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: ProgramEntryFormModule, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7200
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.8", type: ProgramEntryFormModule, isStandalone: true, selector: "ng-dhis2-ui-program-entry-form", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, trackedEntity: { classPropertyName: "trackedEntity", publicName: "trackedEntity", isSignal: true, isRequired: false, transformFunction: null }, event: { classPropertyName: "event", publicName: "event", isSignal: true, isRequired: false, transformFunction: null }, enrollment: { classPropertyName: "enrollment", publicName: "enrollment", isSignal: true, isRequired: false, transformFunction: null }, orgUnit: { classPropertyName: "orgUnit", publicName: "orgUnit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { instanceSave: "instanceSave", instanceSaveCompleted: "instanceSaveCompleted", instanceUpdate: "instanceUpdate", formValidityUpdate: "formValidityUpdate", formCancel: "formCancel" }, ngImport: i0, template: "@if (loading()) {\n<div className=\"program-entry__form-loader\">\n <ng-dhis2-ui-wrapper [component]=\"FormLoader\" />\n</div>\n} @else if(metaData()) {\n\n<div>\n <!-- Form content -->\n @switch (config().displayType) {\n\n <!-- Flat display -->\n @case ('FLAT') {\n <ng-dhis2-ui-flat-form\n [name]=\"metaData()!.name\"\n [dataValues]=\"instance()!\"\n [rules]=\"metaData()!.rules\"\n [fields]=\"metaData()!.formFields\"\n (formUpdate)=\"onFormUpdate($event)\"\n (formValidityUpdate)=\"onValidityUpdate($event)\"\n />\n }\n\n <!-- SECTION display -->\n @case ('SECTION') { Section form }\n\n <!-- CUSTOM FORM -->\n @case ('CUSTOM') { } }\n\n <!-- Action buttons -->\n\n @if(!config().hideActionButtons) {\n <ng-dhis2-ui-wrapper [component]=\"FormActionButtons()\" />\n }\n</div>\n}\n", styles: ["::ng-deep .program-entry__form-loader{padding:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: D2FormModule }, { kind: "component", type: FlatFormComponent, selector: "ng-dhis2-ui-flat-form" }, { kind: "directive", type: ReactWrapperModule, selector: "ng-dhis2-ui-wrapper", inputs: ["props", "component"] }] }); }
|
|
7201
|
+
}
|
|
7202
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: ProgramEntryFormModule, decorators: [{
|
|
7203
|
+
type: Component,
|
|
7204
|
+
args: [{ selector: 'ng-dhis2-ui-program-entry-form', imports: [CommonModule, D2FormModule, ReactWrapperModule], template: "@if (loading()) {\n<div className=\"program-entry__form-loader\">\n <ng-dhis2-ui-wrapper [component]=\"FormLoader\" />\n</div>\n} @else if(metaData()) {\n\n<div>\n <!-- Form content -->\n @switch (config().displayType) {\n\n <!-- Flat display -->\n @case ('FLAT') {\n <ng-dhis2-ui-flat-form\n [name]=\"metaData()!.name\"\n [dataValues]=\"instance()!\"\n [rules]=\"metaData()!.rules\"\n [fields]=\"metaData()!.formFields\"\n (formUpdate)=\"onFormUpdate($event)\"\n (formValidityUpdate)=\"onValidityUpdate($event)\"\n />\n }\n\n <!-- SECTION display -->\n @case ('SECTION') { Section form }\n\n <!-- CUSTOM FORM -->\n @case ('CUSTOM') { } }\n\n <!-- Action buttons -->\n\n @if(!config().hideActionButtons) {\n <ng-dhis2-ui-wrapper [component]=\"FormActionButtons()\" />\n }\n</div>\n}\n", styles: ["::ng-deep .program-entry__form-loader{padding:8px}\n"] }]
|
|
7205
|
+
}], propDecorators: { instanceSave: [{
|
|
7206
|
+
type: Output
|
|
7207
|
+
}], instanceSaveCompleted: [{
|
|
7208
|
+
type: Output
|
|
7209
|
+
}], instanceUpdate: [{
|
|
7210
|
+
type: Output
|
|
7211
|
+
}], formValidityUpdate: [{
|
|
7212
|
+
type: Output
|
|
7213
|
+
}], formCancel: [{
|
|
7214
|
+
type: Output
|
|
7215
|
+
}] } });
|
|
7216
|
+
|
|
7217
|
+
// Copyright 2025 UDSM DHIS2 Lab. All rights reserved.
|
|
7218
|
+
// Use of this source code is governed by a BSD-style
|
|
7219
|
+
// license that can be found in the LICENSE file.
|
|
7220
|
+
|
|
6539
7221
|
/**
|
|
6540
7222
|
* Generated bundle index. Do not edit.
|
|
6541
7223
|
*/
|
|
6542
7224
|
|
|
6543
|
-
export { Boolean$1 as Boolean, BreadcrumbComponent, BreadcrumbModule, ButtonComponent, ButtonModule, CheckBox, D2FormModule, DataTableUIComponent, DataTableUIModule, DateField, DateRangeValue, Dropdown, EventFormComponent, EventFormModule, FieldConfig, FieldControlTypeUtil, FieldDropdown, FieldType, FieldUtil, FormComponent, FormConfig, FormField, FormFieldComponent, FormFieldGroup, FormFieldTypeUtil, FormMetaData, FormMetadataSection, FormUtil, FormValue, FormValueUtil, HeaderBarComponent, HeaderBarModule, LineListModule, LineListTableComponent, MetadataRule, MetadataRuleAction, OrganisationUnitSelectionConfig, OrganisationUnitSelectorComponent, OrganisationUnitSelectorModalComponent, OrganisationUnitSelectorModule, PeriodSelectorComponent, PeriodSelectorModalComponent, PeriodSelectorModule, ReactWrapperModule, RepeatableFormComponent, SectionFormComponent, SelectionFiltersComponent, SelectionFiltersUiModule, TrackerFormComponent, TrackerFormModule, TranslationUtil };
|
|
7225
|
+
export { Boolean$1 as Boolean, BreadcrumbComponent, BreadcrumbModule, ButtonComponent, ButtonModule, CheckBox, D2FormModule, DataTableUIComponent, DataTableUIModule, DateField, DateRangeValue, Dropdown, EventFormComponent, EventFormModule, FieldConfig, FieldControlTypeUtil, FieldDropdown, FieldType, FieldUtil, FlatFormComponent, FormComponent, FormConfig, FormField, FormFieldComponent, FormFieldGroup, FormFieldTypeUtil, FormMetaData, FormMetadataSection, FormUtil, FormValue, FormValueUtil, HeaderBarComponent, HeaderBarModule, LineListModule, LineListTableComponent, MetadataRule, MetadataRuleAction, OrganisationUnitSelectionConfig, OrganisationUnitSelectorComponent, OrganisationUnitSelectorModalComponent, OrganisationUnitSelectorModule, PeriodSelectorComponent, PeriodSelectorModalComponent, PeriodSelectorModule, ProgramEntryFormConfig, ProgramEntryFormMetaData, ProgramEntryFormModule, ProgramEntryFormSection, ReactWrapperModule, RepeatableFormComponent, SectionFormComponent, SelectionFiltersComponent, SelectionFiltersUiModule, TrackerFormComponent, TrackerFormModule, TranslationUtil };
|
|
6544
7226
|
//# sourceMappingURL=iapps-ng-dhis2-ui.mjs.map
|