Skip to content

Commit

Permalink
(feat) : Adapt data sources to new schema specification and add `remo…
Browse files Browse the repository at this point in the history
…te-select` Question
  • Loading branch information
donaldkibet committed Jan 23, 2025
1 parent dfc3fc7 commit ec3b217
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,22 @@ export class RemoteSelectComponent implements OnInit, ControlValueAccessor {

private loadOptions() {
this.remoteOptions$ = concat(
of([]), // default items
this.dataSource.searchOptions(
'',
this.dataSource?.dataSourceOptions ?? {}
) ?? of([]), // default items
this.remoteOptionInput$.pipe(
distinctUntilChanged(),
tap(() => {
this.loading = true;
}),
switchMap((term) =>
this.dataSource.searchOptions(term).pipe(
catchError(() => of([])), // empty list on error
tap(() => (this.loading = false))
)
this.dataSource
.searchOptions(term, this.dataSource?.dataSourceOptions ?? {})
.pipe(
catchError(() => of([])), // empty list on error
tap(() => (this.loading = false))
)
)
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { MinLengthValidationModel } from '../question-models/min-length-validati
import { WorkspaceLauncherQuestion } from '../question-models';
import { DecimalValidationModel } from '../question-models/decimal-validation.model';
import { DisallowDecimalsValidationModel } from '../question-models/disallow-decimals-validation.model';
import { RemoteSelectQuestion } from '../question-models/remote-select-question';
@Injectable()
export class QuestionFactory {
dataSources: any = {};
Expand Down Expand Up @@ -745,6 +746,38 @@ export class QuestionFactory {
return question;
}

toRemoteSelectQuestion(schemaQuestion: any): RemoteSelectQuestion {
const dataSource = this.getDataSourceConfig(schemaQuestion);
const question = new RemoteSelectQuestion({
dataSource: dataSource.name,
dataSourceOptions: dataSource.options,
type: '',
key: ''
});
question.questionIndex = this.quetionIndex;
question.label = schemaQuestion.label;
question.prefix = schemaQuestion.prefix;
question.key = schemaQuestion.id;
question.renderingType = 'remote-select';
question.validators = this.addValidators(schemaQuestion);
question.extras = schemaQuestion;
return question;
}

private getDataSourceConfig(
schemaQuestion: any
): { name: string; options: any } {
const dataSourceName = schemaQuestion.questionOptions?.dataSource;
const dataSourceOptions = schemaQuestion.questionOptions?.dataSourceOptions;
// See https://github.com/openmrs/openmrs-contrib-json-schemas/blob/main/form.schema.json
const openMrs3DataSource = schemaQuestion.questionOptions?.datasource;

return {
name: dataSourceName ?? openMrs3DataSource?.name ?? '',
options: dataSourceOptions ?? openMrs3DataSource?.config ?? {}
};
}

toDecimalQuestion(schemaQuestion: any): TextInputQuestion {
const question = new TextInputQuestion({
placeholder: '',
Expand Down Expand Up @@ -938,6 +971,8 @@ export class QuestionFactory {
return this.toFileUploadQuestion(schema);
case 'workspace-launcher':
return this.toWorkspaceLauncher(schema);
case 'remote-select':
return this.toRemoteSelectQuestion(schema);
default:
console.warn('New Schema Question Type found.........' + renderType);
return this.toTextQuestion(schema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { SelectOption } from './select-option';
import { Observable } from 'rxjs';

export interface DataSource {
dataSourceOptions?: any;
dataSourceOptions?: Record<string, unknown>;
dataFromSourceChanged?: Observable<SelectOption[]>;
resolveSelectedValue(value): Observable<SelectOption>;
searchOptions(searchText): Observable<SelectOption[]>;
searchOptions(
searchText,
dataSourceOptions?: Record<string, unknown>
): Observable<SelectOption[]>;
fileUpload(data): Observable<any>;
fetchFile(url: string, fileType?: string): Observable<any>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { BaseOptions } from '../interfaces/base-options';

export interface RemoteSelectQuestionOptions extends BaseOptions {
dataSource: string;
dataSourceOptions?: Record<string, unknown>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class QuestionBase implements BaseOptions {
historicalDataValue?: any;
extras?: any;
dataSource?: string;
dataSourceOptions?: any;
dataSourceOptions?: Record<string, unknown>;

controlType?: AfeControlType;
validators?: Array<ValidationModel>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { QuestionBase } from './question-base';
import { AfeControlType } from '../../abstract-controls-extension/afe-control-type';
import { RemoteSelectQuestionOptions } from './interfaces/remote-select-question-options';

export class RemoteSelectQuestion extends QuestionBase {
rendering: string;
options: any[];

constructor(options: RemoteSelectQuestionOptions) {
super(options);
this.renderingType = 'select';
this.controlType = AfeControlType.AfeFormControl;
this.dataSource = options.dataSource || '';
this.dataSourceOptions = options.dataSourceOptions || {};
}
}
50 changes: 45 additions & 5 deletions src/app/adult-1.6.json
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,23 @@
"rendering": "ui-select-extended"
}
},
{
"id": "admitToLocation",
"type": "obs",
"required": true,
"label": "Admit to location",
"questionOptions": {
"rendering": "remote-select",
"required": true,
"concept": "CIEL:169403",
"datasource": {
"name": "location_datasource",
"config": {
"tag": "Admission Location"
}
}
}
},
{
"type": "encounterLocation",
"label": "Facility name (site/satellite clinic required):",
Expand Down Expand Up @@ -3362,7 +3379,9 @@
"type": "obs",
"hide": {
"field": "tb_current",
"value": ["b8aa06ca-93c6-40ea-b144-c74f841926f4"]
"value": [
"b8aa06ca-93c6-40ea-b144-c74f841926f4"
]
},
"id": "__ptxCzFD2s"
}
Expand Down Expand Up @@ -6991,7 +7010,9 @@
"type": "obs",
"hide": {
"field": "q26f",
"value": ["b8aa06ca-93c6-40ea-b144-c74f841926f4"]
"value": [
"b8aa06ca-93c6-40ea-b144-c74f841926f4"
]
},
"id": "__Jywyp94Lw"
}
Expand Down Expand Up @@ -8012,7 +8033,16 @@
"questionOptions": {
"concept": "318a5e8b-218c-4f66-9106-cd581dec1f95",
"rendering": "date",
"weeksList": [2, 4, 6, 8, 12, 16, 24, 36]
"weeksList": [
2,
4,
6,
8,
12,
16,
24,
36
]
},
"validators": [
{
Expand Down Expand Up @@ -8042,7 +8072,17 @@
"questionOptions": {
"concept": "a8a666ba-1350-11df-a1f1-0026b9348838",
"rendering": "date",
"weeksList": [2, 4, 6, 8, 12, 16, 20, 24, 36]
"weeksList": [
2,
4,
6,
8,
12,
16,
20,
24,
36
]
},
"validators": [
{
Expand Down Expand Up @@ -8178,4 +8218,4 @@
]
}
]
}
}
42 changes: 41 additions & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ export class AppComponent implements OnInit {
searchOptions: this.sampleSearch,
resolveSelectedValue: this.sampleResolve
});
this.dataSources.registerDataSource('location_datasource', {
searchOptions: this.sampleLocationSearch,
resolveSelectedValue: this.sampleResolve
});
this.dataSources.registerDataSource('provider', {
searchOptions: this.sampleSearch,
resolveSelectedValue: this.sampleResolve
Expand Down Expand Up @@ -350,7 +354,43 @@ export class AppComponent implements OnInit {
});
}

public sampleSearch(): Observable<any> {
public sampleLocationSearch(
searchText: string
): Observable<Array<Record<string, string>>> {
const locations = [
{
value: 'ba685651-ed3b-4e63-9b35-78893060758a',
label: 'Inpatient Ward'
},
{
value: '184ac7d9-225a-41f8-bac7-c87b1327e1b0',
label: 'Ward 1'
},
{
value: '5a7f3c53-6bb4-448b-a966-5e65b397b9f3',
label: 'Ward 2'
},
{
value: '2272b8cd-b690-4878-a50c-40d22235b3f3',
label: 'Ward 3'
},
{
value: 'db0253bb-8e2e-4b2c-b60c-6c88110e3c2e',
label: 'Duplix'
}
];
if (searchText) {
return of(
locations.filter((location) =>
location.label.toLowerCase().includes(searchText.toLowerCase())
)
);
}

return of(locations);
}

public sampleSearch(searchText: string): Observable<any> {
const items: Array<any> = [
{ value: '0', label: 'Aech' },
{ value: '5b6e58ea-1359-11df-a1f1-0026b9348838', label: 'Art3mis' },
Expand Down
25 changes: 17 additions & 8 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import {
provideHttpClient,
withInterceptorsFromDi
} from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormEntryModule } from '@openmrs/ngx-formentry';
import { AppComponent } from './app.component';
import { NgxTranslateModule } from './translate/translate.module';

@NgModule({ declarations: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent], imports: [BrowserModule,
BrowserAnimationsModule,
FormEntryModule,
ReactiveFormsModule,
NgxTranslateModule], providers: [provideHttpClient(withInterceptorsFromDi())] })
@NgModule({
declarations: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormEntryModule,
ReactiveFormsModule,
NgxTranslateModule
],
providers: [provideHttpClient(withInterceptorsFromDi())]
})
export class AppModule {}
Loading

0 comments on commit ec3b217

Please sign in to comment.