@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.
Files changed (27) hide show
  1. package/fesm2022/iapps-ng-dhis2-ui.mjs +815 -133
  2. package/fesm2022/iapps-ng-dhis2-ui.mjs.map +1 -1
  3. package/index.d.ts +1 -0
  4. package/lib/modules/form/components/base-form-field.component.d.ts +3 -1
  5. package/lib/modules/form/containers/flat-form/flat-form.component.d.ts +11 -0
  6. package/lib/modules/form/containers/form-field/form-field.component.d.ts +1 -0
  7. package/lib/modules/form/form.module.d.ts +7 -6
  8. package/lib/modules/form/hooks/field-validation.hook.d.ts +3 -1
  9. package/lib/modules/form/index.d.ts +1 -0
  10. package/lib/modules/form/interfaces/form-field.interface.d.ts +1 -0
  11. package/lib/modules/form/models/form-field.model.d.ts +1 -0
  12. package/lib/modules/form/models/form-metadata-section.model.d.ts +1 -0
  13. package/lib/modules/form/shared/components/base-form-wrapper.component.d.ts +26 -0
  14. package/lib/modules/form/shared/components/index.d.ts +1 -0
  15. package/lib/modules/form/shared/index.d.ts +1 -0
  16. package/lib/modules/form/utils/field-type.util.d.ts +1 -1
  17. package/lib/modules/form/utils/field.util.d.ts +1 -1
  18. package/lib/modules/program-entry-form/index.d.ts +2 -0
  19. package/lib/modules/program-entry-form/models/index.d.ts +3 -0
  20. package/lib/modules/program-entry-form/models/program-entry-form-metadata.d.ts +28 -0
  21. package/lib/modules/program-entry-form/models/program-entry-form-section.model.d.ts +16 -0
  22. package/lib/modules/program-entry-form/models/program-entry-form.config.d.ts +47 -0
  23. package/lib/modules/program-entry-form/program-entry-form.component.d.ts +35 -0
  24. package/lib/modules/program-entry-form/utils/index.d.ts +2 -0
  25. package/lib/modules/program-entry-form/utils/program-entry-form-field.util.d.ts +63 -0
  26. package/lib/modules/program-entry-form/utils/program-entry-form-section.util.d.ts +8 -0
  27. 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
- else if (error['max']) {
4095
+ if (error['max']) {
4084
4096
  return `${field.label || 'Value'} should not be greater than ${error['max'].max}!`;
4085
4097
  }
4086
- else if (error['pattern']) {
4098
+ if (error['pattern']) {
4087
4099
  if (field.type === 'email') {
4088
4100
  return `The email address provided is not valid`;
4089
4101
  }
4090
- else if (field.type === 'tel') {
4102
+ if (field.type === 'tel') {
4091
4103
  return 'Phone number provided is not valid';
4092
4104
  }
4093
- else {
4094
- return `${field.label || 'Value'} should have appropriate format`;
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
- }, [hasError]);
4101
- return { hasError, validationError };
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
- ? [Validators.pattern('\\+255[6-7][1-9][0-9]{7}$')]
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(this.form().get(this.field().id)?.value ||
5376
- this.form().get(this.field().key)?.value);
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 { hasError, validationError } = useFieldValidation({
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
- switch (this.field().controlType) {
5393
- case 'textarea':
5394
- 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) => {
5395
- this.ngZone.run(() => {
5396
- (this.form().get(this.field().id) ||
5397
- this.form().get(this.field().key))?.setValue(event.value);
5398
- this.immediateUpdate.emit({
5399
- form: this.form(),
5400
- value: event.value,
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
- setValue(event.value);
5404
- setTouched(true);
5405
- }, onBlur: () => {
5406
- this.ngZone.run(() => {
5407
- this.update.emit({ form: this.form(), value });
5408
- });
5409
- } }));
5410
- case 'org-unit':
5411
- return (React__default.createElement(OrgUnitFormField, { label: this.label(), key: this.field().id, required: this.field().required, onSelectOrgUnit: (selectedOrgUnit) => {
5412
- this.ngZone.run(() => {
5413
- (this.form().get(this.field().id) ||
5414
- this.form().get(this.field().key))?.setValue(selectedOrgUnit);
5415
- this.update.emit({
5416
- form: this.form(),
5417
- value: selectedOrgUnit,
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
- setValue(selectedOrgUnit);
5421
- setTouched(true);
5422
- }, selected: value }));
5423
- case 'transfer':
5424
- return (React__default.createElement(Transfer, { filterable: true, filterPlaceholder: "Search", selected: selected, leftHeader: React__default.createElement("div", { style: {
5425
- fontSize: 14,
5426
- padding: '8px 4px',
5427
- } }, this.field().availableOptionsLabel), rightHeader: React__default.createElement("div", { style: {
5428
- fontSize: 14,
5429
- padding: '8px 4px',
5430
- } }, this.field().selectedOptionsLabel), options: this.field().options, onChange: (event) => {
5431
- onChange({ selected: event.selected });
5432
- this.ngZone.run(() => {
5433
- (this.form().get(this.field().id) ||
5434
- this.form().get(this.field().key))?.setValue(event.selected);
5435
- });
5436
- setValue(event.selected);
5437
- setTouched(true);
5438
- this.update.emit({ form: this.form(), value });
5439
- } }));
5440
- case 'checkbox':
5441
- return (React__default.createElement(Checkbox, { checked: Boolean(value), error: hasError, label: this.label(), name: this.field().id, disabled: disabled, onChange: (event) => {
5442
- this.ngZone.run(() => {
5443
- (this.form().get(this.field().id) ||
5444
- this.form().get(this.field().key))?.setValue(event.checked);
5445
- });
5446
- setValue(event.checked);
5447
- setTouched(true);
5448
- }, onBlur: () => {
5449
- this.ngZone.run(() => {
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
- case 'dropdown':
5454
- 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) => {
5455
- this.ngZone.run(() => {
5456
- (this.form().get(this.field().id) ||
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
- setValue(event.selected);
5464
- setTouched(true);
5465
- } }, (this.field().options || []).map((option) => (React__default.createElement(SingleSelectOption, { key: crypto.randomUUID() || option.key, label: option.label, value: option.value })))));
5466
- case 'multi-dropdown':
5467
- 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) => {
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
- setValue(selectedValue);
5478
- setTouched(true);
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(fileId);
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: fileId,
5543
+ value: event.selected,
5489
5544
  });
5490
5545
  });
5491
- setValue(fileId);
5546
+ setValue(event.selected);
5492
5547
  setTouched(true);
5493
- } })));
5494
- default:
5495
- 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) => {
5496
- this.ngZone.run(() => {
5497
- (this.form().get(this.field().id) ||
5498
- this.form().get(this.field().key))?.setValue(event.value);
5499
- this.immediateUpdate.emit({
5500
- form: this.form(),
5501
- value: event.value,
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
- setValue(event.value);
5505
- setTouched(true);
5506
- }, onBlur: () => {
5507
- this.ngZone.run(() => {
5508
- this.update.emit({ form: this.form(), value });
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
- .filter((ruleAction) => ruleAction.field === this.field().id)
5586
- .forEach((ruleAction) => {
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
- this.isValueAssigned.set(true);
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