Skip to content

Commit

Permalink
Introduce Capturing of drugs as observations
Browse files Browse the repository at this point in the history
  • Loading branch information
kajambiya committed Sep 27, 2023
1 parent ee43c40 commit 6c0dcb1
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export interface OHRIFormQuestionOptions {
};
isDateTime?: { labelTrue: boolean; labelFalse: boolean };
usePreviousValueDisabled?: boolean;
datasource?: { id: string; config?: Record<string, any> };
datasource?: { name: string; config?: Record<string, any> };
isSearchable?: boolean;
}

Expand Down
21 changes: 14 additions & 7 deletions src/components/inputs/ui-select-extended/ui-select-extended.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import { PreviousValueReview } from '../../previous-value-review/previous-value-
import debounce from 'lodash-es/debounce';
import { useTranslation } from 'react-i18next';
import { getRegisteredDataSource } from '../../../registry/registry';
import { useDataSourceConfig } from '../../../hooks/useDataSourceConfig';

export const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handler, onChange }) => {
const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handler, onChange }) => {
const { t } = useTranslation();
const [field, meta] = useField(question.id);
const { setFieldValue, encounterContext, fields } = React.useContext(OHRIFormContext);
Expand All @@ -29,8 +30,13 @@ export const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handl
const isProcessingSelection = useRef(false);
const [dataSource, setDataSource] = useState(null);

const config = useDataSourceConfig(question);

useEffect(() => {
getRegisteredDataSource(question.questionOptions?.datasource?.id).then(ds => setDataSource(ds));
const datasourceName = question.questionOptions?.datasource?.name;
getRegisteredDataSource(datasourceName ? datasourceName : question.questionOptions.rendering).then(ds =>
setDataSource(ds),
);
}, [question.questionOptions?.datasource]);

useEffect(() => {
Expand All @@ -48,7 +54,7 @@ export const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handl

const debouncedSearch = debounce((searchterm, dataSource) => {
setIsLoading(true);
dataSource.fetchData(searchterm, question.questionOptions?.datasource?.config).then(dataItems => {
dataSource.fetchData(searchterm, config).then(dataItems => {
setItems(dataItems.map(dataSource.toUuidAndDisplay));
setIsLoading(false);
});
Expand All @@ -58,15 +64,14 @@ export const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handl
// If not searchable, preload the items
if (dataSource && !isTrue(question.questionOptions.isSearchable)) {
setIsLoading(true);
dataSource.fetchData(null, question.questionOptions?.datasource?.config).then(dataItems => {
dataSource.fetchData(null, config).then(dataItems => {
setItems(dataItems.map(dataSource.toUuidAndDisplay));
setIsLoading(false);
});
}
}, [dataSource]);

useEffect(() => {
// get the data source
if (dataSource && isTrue(question.questionOptions.isSearchable) && !isEmpty(searchTerm)) {
debouncedSearch(searchTerm, dataSource);
}
Expand Down Expand Up @@ -139,8 +144,8 @@ export const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handl
isProcessingSelection.current = false;
return;
}
setInputValue('');
setFieldValue(question.id, '');
setInputValue(value);
//setFieldValue(question.id, '');
if (question.questionOptions['isSearchable']) {
setSearchTerm(value);
}
Expand All @@ -162,3 +167,5 @@ export const UISelectExtended: React.FC<OHRIFormFieldProps> = ({ question, handl
)
);
};

export default UISelectExtended;
18 changes: 18 additions & 0 deletions src/datasources/concept-data-source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { openmrsFetch } from '@openmrs/esm-framework';
import { BaseOpenMRSDataSource } from './data-source';

export class ConceptDataSource extends BaseOpenMRSDataSource {
constructor() {
super('/ws/rest/v1/concept?name=&searchType=fuzzy&v=custom:(uuid,display)');
}

fetchData(searchTerm: string, config?: Record<string, any>): Promise<any[]> {
if (config?.class) {
let urlParts = this.url.split('name=');
this.url = `${urlParts[0]}&name=&class=${config.class}&${urlParts[1]}`;
}
return openmrsFetch(searchTerm ? `${this.url}&q=${searchTerm}` : this.url).then(({ data }) => {
return data.results;
});
}
}
5 changes: 2 additions & 3 deletions src/datasources/location-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { openmrsFetch } from '@openmrs/esm-framework';
import { BaseOpenMRSDataSource } from './data-source';

export class LocationDataSource extends BaseOpenMRSDataSource {
constructor(){
super("/ws/rest/v1/location?v=custom:(uuid,display)");
constructor() {
super('/ws/rest/v1/location?v=custom:(uuid,display)');
}

fetchData(searchTerm: string, config?: Record<string, any>): Promise<any[]> {
Expand All @@ -15,5 +15,4 @@ export class LocationDataSource extends BaseOpenMRSDataSource {
return data.results;
});
}

}
22 changes: 22 additions & 0 deletions src/hooks/useDataSourceConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useEffect, useState } from 'react';
import { getControlTemplate } from '../registry/inbuilt-components/control-templates';
import { OHRIFormField } from '../api/types';
import { useTranslation } from 'react-i18next';

export function useDataSourceConfig(field: OHRIFormField) {
const [config, setConfig] = useState({});
const { t } = useTranslation();

useEffect(() => {
if (field.questionOptions.datasource?.name) {
setConfig(field.questionOptions.datasource.config);
} else {
const template = getControlTemplate(field.questionOptions.rendering);
setConfig(template.datasource.config);
}
}, [field]);

return {
config,
};
}
18 changes: 18 additions & 0 deletions src/registry/inbuilt-components/control-templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import UISelectExtended from '../../components/inputs/ui-select-extended/ui-select-extended';

export const controlTemplates = [
{
name: 'drug',
baseControlComponent: UISelectExtended,
datasource: {
name: 'drug_datasource',
config: {
class: '8d490dfc-c2cc-11de-8d13-0010c6dffd0f',
},
},
},
];

export const getControlTemplate = (name: string) => {
return controlTemplates.find(template => template.name === name);
};
8 changes: 7 additions & 1 deletion src/registry/inbuilt-components/inbuiltControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import OHRIDropdown from '../../components/inputs/select/ohri-dropdown.component
import OHRITextArea from '../../components/inputs/text-area/ohri-text-area.component';
import OHRIText from '../../components/inputs/text/ohri-text.component';
import OHRIToggle from '../../components/inputs/toggle/ohri-toggle.component';
import { UISelectExtended } from '../../components/inputs/ui-select-extended/ui-select-extended';
import UISelectExtended from '../../components/inputs/ui-select-extended/ui-select-extended';
import { OHRIRepeat } from '../../components/repeat/ohri-repeat.component';
import { RegistryItem } from '../registry';
import { controlTemplates } from './control-templates';

/**
* @internal
Expand Down Expand Up @@ -108,4 +109,9 @@ export const inbuiltControls: Array<RegistryItem<React.ComponentType<OHRIFormFie
component: UISelectExtended,
type: 'ui-select-extended',
},
...controlTemplates.map(template => ({
name: `${template.name}Control`,
component: UISelectExtended,//template.baseControlComponent,
type: template.name.toLowerCase(),
})),
];
11 changes: 10 additions & 1 deletion src/registry/inbuilt-components/inbuiltDataSources.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DataSource } from '../../api/types';
import { ConceptDataSource } from '../../datasources/concept-data-source';
import { LocationDataSource } from '../../datasources/location-data-source';
import { RegistryItem } from '../registry';

Expand All @@ -7,7 +8,15 @@ import { RegistryItem } from '../registry';
*/
export const inbuiltDataSources: Array<RegistryItem<DataSource<any>>> = [
{
name: 'concept_location',
name: 'location_datasource',
component: new LocationDataSource(),
},
{
name: 'drug_datasource',
component: new ConceptDataSource(),
},
];

export const validateInbuiltDatasource = (name: string) => {
return inbuiltDataSources.some(datasource => datasource.name === name);
};
17 changes: 13 additions & 4 deletions src/registry/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { inbuiltControls } from './inbuilt-components/inbuiltControls';
import { inbuiltFieldSubmissionHandlers } from './inbuilt-components/inbuiltFieldSubmissionHandlers';
import { inbuiltValidators } from './inbuilt-components/inbuiltValidators';
import { inbuiltDataSources } from './inbuilt-components/inbuiltDataSources';
import { getControlTemplate } from './inbuilt-components/control-templates';

/**
* @internal
Expand Down Expand Up @@ -157,10 +158,18 @@ export async function getRegisteredDataSource(name: string): Promise<DataSource<
}
let ds = inbuiltDataSources.find(dataSource => dataSource.name === name)?.component;
if (!ds) {
const dataSourceImport = await getFormsStore()
.dataSources.find(ds => ds.name === name)
?.load?.();
ds = dataSourceImport.default;
const template = getControlTemplate(name);
if (template) {
ds = inbuiltDataSources.find(dataSource => dataSource.name === template.datasource.name)?.component;
} else {
const dataSourceImport = await getFormsStore()
.dataSources.find(ds => ds.name === name)
?.load?.();
if (!dataSourceImport) {
throw new Error('Datasource not found');
}
ds = dataSourceImport.default;
}
}
registryCache.dataSources[name] = ds;
return ds;
Expand Down

0 comments on commit 6c0dcb1

Please sign in to comment.