Skip to content

Commit

Permalink
feat: refactored query filter components, api, ...
Browse files Browse the repository at this point in the history
  • Loading branch information
tada5hi committed Oct 31, 2024
1 parent 69809d3 commit b8a95bb
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 185 deletions.
83 changes: 52 additions & 31 deletions packages/core/src/components/core/query/QueryPatientFilters.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<script lang="ts">
import type { PropType } from 'vue';
import {
defineComponent, ref,
} from 'vue';
import { VCFormRangeMultiSlider } from '@vuecs/form-controls';
import { defineComponent, ref } from 'vue';
import { QueryFilterURLKey } from '../../../constants';
import { injectHTTPClient } from '../../../core';
import type { PatientFilter } from '../../../domains';
import { useQueryFilterStore } from '../../../stores';
import QueryFilterBox from './QueryFilterBox.vue';
Expand All @@ -15,8 +13,12 @@ export default defineComponent({
VCFormRangeMultiSlider,
},
props: {
available: {
type: Object as PropType<PatientFilter>,
queryId: {
type: String,
required: true,
},
useCase: {
type: String,
required: true,
},
busy: {
Expand All @@ -27,6 +29,20 @@ export default defineComponent({
emits: ['submit'],
async setup(props, { emit }) {
const store = useQueryFilterStore();
const httpClient = injectHTTPClient();
const available = ref<PatientFilter>({});
const availableInitialized = ref<boolean>(false);
const load = async () => {
try {
available.value = await httpClient.query.getPatientFilter(props.useCase, props.queryId);
} catch (e) {
available.value = [];
} finally {
availableInitialized.value = true;
}
};
const gender = ref<string[]>([]);
const vitalStatus = ref<string[]>([]);
Expand All @@ -37,40 +53,40 @@ export default defineComponent({
});
const resetGender = () => {
gender.value = props.available.gender ?
props.available.gender.map((el) => el.code) :
gender.value = available.value.gender ?
available.value.gender.map((el) => el.code) :
[];
store.set(QueryFilterURLKey.GENDER, []);
};
const resetVitalStatus = () => {
vitalStatus.value = props.available.vitalStatus ?
props.available.vitalStatus.map((el) => el.code) :
vitalStatus.value = available.value.vitalStatus ?
available.value.vitalStatus.map((el) => el.code) :
[];
store.set(QueryFilterURLKey.VITAL_STATUS, []);
};
const resetSite = () => {
site.value = props.available.site ?
props.available.site.map((el) => el.code) :
site.value = available.value.site ?
available.value.site.map((el) => el.code) :
[];
store.set(QueryFilterURLKey.SITE, []);
};
const resetAgeMin = () => {
age.value.min = props.available.ageRange ?
props.available.ageRange.min :
age.value.min = available.value.ageRange ?
available.value.ageRange.min :
0;
store.set(QueryFilterURLKey.AGE_MIN, []);
};
const resetAgeMax = () => {
age.value.max = props.available.ageRange ?
props.available.ageRange.max :
age.value.max = available.value.ageRange ?
available.value.ageRange.max :
100;
store.set(QueryFilterURLKey.AGE_MAX, []);
Expand Down Expand Up @@ -135,25 +151,27 @@ export default defineComponent({
}
};
init();
Promise.resolve()
.then(() => load())
.then(() => init());
const handleAgeRangeChanged = (ctx: { min: number, max: number}) => {
age.value.min = Math.round(ctx.min);
age.value.max = Math.round(ctx.max);
if (props.available.ageRange) {
if (available.value.ageRange) {
if (
props.available.ageRange.min &&
props.available.ageRange.min === age.value.min
available.value.ageRange.min &&
available.value.ageRange.min === age.value.min
) {
store.set(QueryFilterURLKey.AGE_MIN, []);
} else {
store.set(QueryFilterURLKey.AGE_MIN, [`${age.value.min}`]);
}
if (
props.available.ageRange.max &&
props.available.ageRange.max === age.value.max
available.value.ageRange.max &&
available.value.ageRange.max === age.value.max
) {
store.set(QueryFilterURLKey.AGE_MAX, []);
} else {
Expand All @@ -165,9 +183,9 @@ export default defineComponent({
const handleGenderChanged = () => {
const data : string[] = [];
if (
props.available &&
props.available.gender &&
props.available.gender.length !== gender.value.length
available.value &&
available.value.gender &&
available.value.gender.length !== gender.value.length
) {
data.push(...gender.value);
}
Expand All @@ -178,9 +196,9 @@ export default defineComponent({
const handleVitalStatusChanged = () => {
const data : string[] = [];
if (
props.available &&
props.available.vitalStatus &&
props.available.vitalStatus.length !== vitalStatus.value.length
available.value &&
available.value.vitalStatus &&
available.value.vitalStatus.length !== vitalStatus.value.length
) {
data.push(...vitalStatus.value);
}
Expand All @@ -191,9 +209,9 @@ export default defineComponent({
const handleSiteChanged = () => {
const data : string[] = [];
if (
props.available &&
props.available.site &&
props.available.site.length !== site.value.length
available.value &&
available.value.site &&
available.value.site.length !== site.value.length
) {
data.push(...site.value);
}
Expand All @@ -208,6 +226,9 @@ export default defineComponent({
};
return {
available,
availableInitialized,
age,
gender,
vitalStatus,
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/domains/coding/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ export function serializeCoding(coding: Coding) {
parts.push(coding.code);
if (coding.system) {
parts.push(coding.system);

if (coding.version) {
parts.push(coding.version);
}
}

return parts.join('|');
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/domains/query/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BaseAPI } from '../api';
import type { PatientFilter } from '../patient';
import type { QueryBase } from './types';

export class QueryAPI extends BaseAPI {
Expand All @@ -9,4 +10,12 @@ export class QueryAPI extends BaseAPI {
const response = await this.client.get(`${useCase}/queries/${id}`);
return response.data;
}

async getPatientFilter(
useCase: string,
id: string,
) : Promise<PatientFilter> {
const response = await this.client.get(`${useCase}/queries/${id}/filters/patient`);
return response.data;
}
}
2 changes: 0 additions & 2 deletions packages/core/src/domains/query/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import type { MinMaxRange } from '../utility';
*/
export type QueryBase<
CRITERIA extends ObjectLiteral = ObjectLiteral,
FILTERS extends ObjectLiteral = ObjectLiteral,
> = {
id: string,
submittedAt: string,
querier: string,
mode: Coding,
criteria?: CRITERIA | null,
filters: FILTERS
/**
* Validity period (seconds) for the query.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,60 @@
<!--
- Copyright (c) 2024.
- Author Peter Placzek (tada5hi)
- For the full copyright and license information,
- view the LICENSE file that was distributed with this source code.
-->

<script lang="ts">
import type { PropType } from 'vue';
import {
computed, defineComponent, onUnmounted, ref,
} from 'vue';
import {
type Coding, DQueryFilterBox, QueryEventBusEventName, injectQueryEventBus, useQueryFilterStore,
} from '@dnpm-dip/core';
import { QueryFilterURLKey } from '../../constants';
import { QueryFilterURLKey } from '../../../constants';
import { injectHTTPClient } from '../../../core/http-client';
export default defineComponent({
components: {
DQueryFilterBox,
},
props: {
available: {
type: Object as PropType<Coding[]>,
},
busy: {
type: Boolean,
default: false,
},
queryId: {
type: String,
required: true,
},
},
emits: ['commited'],
async setup(props, { emit }) {
const store = useQueryFilterStore();
const eventBus = injectQueryEventBus();
const httpClient = injectHTTPClient();
const items = ref<string[]>([]);
const itemsAvailable = ref<Coding[]>([]);
const itemsAvailableInitialized = ref<boolean>(false);
const itemsAvailable = computed(() => {
if (!props.available) {
return [];
const load = async () => {
try {
const response = await httpClient.query.getDiagnosisFilter(props.queryId);
if (
response &&
response.code
) {
itemsAvailable.value = response.code
.sort((a, b) => a.code.localeCompare(b.code));
}
} catch (e) {
itemsAvailable.value = [];
} finally {
itemsAvailableInitialized.value = true;
}
return [...props.available]
.sort((a, b) => a.code.localeCompare(b.code));
});
};
const offset = ref(0);
const limit = ref(10);
Expand All @@ -59,7 +78,7 @@ export default defineComponent({
.slice(startIndex, endIndex);
});
const load = (pagination: any) => {
const loadPage = (pagination: any) => {
limit.value = pagination.limit;
offset.value = pagination.offset;
};
Expand Down Expand Up @@ -131,7 +150,9 @@ export default defineComponent({
setFilter();
};
init();
Promise.resolve()
.then(() => load())
.then(() => init());
const submit = () => {
store.commit();
Expand All @@ -145,6 +166,7 @@ export default defineComponent({
return {
items,
itemsAvailableInitialized,
handleChanged,
selectAll,
Expand All @@ -155,8 +177,7 @@ export default defineComponent({
total,
limit,
offset,
load,
loadPage,
};
},
});
Expand All @@ -178,6 +199,7 @@ export default defineComponent({
<div class="d-flex flex-row">
<div>
<button
:disabled="!itemsAvailableInitialized"
type="button"
class="btn btn-xs btn-dark"
@click.prevent="selectAll"
Expand All @@ -187,6 +209,7 @@ export default defineComponent({
</div>
<div class="ms-auto">
<button
:disabled="!itemsAvailableInitialized"
type="button"
class="btn btn-xs btn-dark"
@click.prevent="unselectAll"
Expand Down Expand Up @@ -218,14 +241,15 @@ export default defineComponent({
:total="total"
:offset="offset"
:limit="limit"
@load="load"
@load="loadPage"
/>
</div>
</div>

<div class="row">
<div class="form-group">
<button
:disabled="!itemsAvailableInitialized"
type="button"
class="btn btn-xs btn-primary btn-block"
@click.prevent="submit"
Expand Down
Loading

0 comments on commit b8a95bb

Please sign in to comment.