Skip to content
This repository has been archived by the owner on Jun 20, 2022. It is now read-only.

Commit

Permalink
Merge pull request #268 from ImisDevelopers/feature/232-exposure-cont…
Browse files Browse the repository at this point in the history
…acts

Fundamentals of Exposure Contact Management
  • Loading branch information
wobkenh authored May 11, 2020
2 parents e28ee9a + a483ea6 commit 2dffc29
Show file tree
Hide file tree
Showing 25 changed files with 1,344 additions and 92 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
.idea
.gradle
.DS_Store
**/.project
**/.settings
/.classpath
# CMake
cmake-build-*/

Expand Down
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"register-service-worker": "^1.6.2",
"vue": "^2.6.11",
"vue-router": "^3.1.5",
"vue-typed-mixins": "^0.2.0",
"vuex": "^3.1.2",
"vuex-smart-module": "^0.3.4"
},
Expand Down
102 changes: 100 additions & 2 deletions client/src/api/SwaggerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,32 @@ export interface Doctor {
zip?: string;
}

export interface ExposureContactContactView {
firstName?: string;
id?: string;
inQuarantine?: boolean;
infected?: boolean;
lastName?: string;
}

export interface ExposureContactFromServer {
comment?: string;
contact?: ExposureContactContactView;
context?: string;
dateOfContact?: string;
id?: number;
source?: ExposureContactContactView;
}

export interface ExposureContactToServer {
comment?: string;
contact?: string;
context?: string;
dateOfContact?: string;
id?: number;
source?: string;
}

export interface GrantedAuthority {
authority?: string;
}
Expand Down Expand Up @@ -511,7 +537,7 @@ type ApiConfig<SecurityDataType> = {
};

class HttpClient<SecurityDataType> {
public baseUrl: string = "//localhost:8642/";
public baseUrl: string = "//localhost/";
private securityData: SecurityDataType = null as any;
private securityWorker: ApiConfig<SecurityDataType>["securityWorker"] = (() => {}) as any;

Expand Down Expand Up @@ -589,7 +615,7 @@ class HttpClient<SecurityDataType> {
/**
* @title Api Documentation
* @version 1.0
* @baseUrl //localhost:8642/
* @baseUrl //localhost/
* Api Documentation
*/
export class Api<SecurityDataType = any> extends HttpClient<SecurityDataType> {
Expand Down Expand Up @@ -705,6 +731,78 @@ export class Api<SecurityDataType = any> extends HttpClient<SecurityDataType> {
addScheduledEventUsingPost: (dto: RequestLabTestDTO, params?: RequestParams) =>
this.request<PatientEvent, any>(`/api/doctor/create_appointment`, "POST", params, dto, true),

/**
* @tags exposure-contact-controller
* @name createExposureContactUsingPOST
* @summary createExposureContact
* @request POST:/api/exposure-contacts
* @secure
*/
createExposureContactUsingPost: (dto: ExposureContactToServer, params?: RequestParams) =>
this.request<ExposureContactFromServer, any>(`/api/exposure-contacts`, "POST", params, dto, true),

/**
* @tags exposure-contact-controller
* @name updateExposureContactUsingPUT
* @summary updateExposureContact
* @request PUT:/api/exposure-contacts
* @secure
*/
updateExposureContactUsingPut: (contact: ExposureContactToServer, params?: RequestParams) =>
this.request<ExposureContactFromServer, any>(`/api/exposure-contacts`, "PUT", params, contact, true),

/**
* @tags exposure-contact-controller
* @name getExposureSourceContactsForPatientUsingGET
* @summary getExposureSourceContactsForPatient
* @request GET:/api/exposure-contacts/by-contact/{id}
* @secure
*/
getExposureSourceContactsForPatientUsingGet: (id: string, params?: RequestParams) =>
this.request<ExposureContactFromServer[], any>(
`/api/exposure-contacts/by-contact/${id}`,
"GET",
params,
null,
true,
),

/**
* @tags exposure-contact-controller
* @name getExposureContactsForPatientUsingGET
* @summary getExposureContactsForPatient
* @request GET:/api/exposure-contacts/by-source/{id}
* @secure
*/
getExposureContactsForPatientUsingGet: (id: string, params?: RequestParams) =>
this.request<ExposureContactFromServer[], any>(
`/api/exposure-contacts/by-source/${id}`,
"GET",
params,
null,
true,
),

/**
* @tags exposure-contact-controller
* @name getExposureContactUsingGET
* @summary getExposureContact
* @request GET:/api/exposure-contacts/{id}
* @secure
*/
getExposureContactUsingGet: (id: number, params?: RequestParams) =>
this.request<ExposureContactFromServer, any>(`/api/exposure-contacts/${id}`, "GET", params, null, true),

/**
* @tags exposure-contact-controller
* @name removeExposureContactUsingDELETE
* @summary removeExposureContact
* @request DELETE:/api/exposure-contacts/{id}
* @secure
*/
removeExposureContactUsingDelete: (id: number, params?: RequestParams) =>
this.request<any, any>(`/api/exposure-contacts/${id}`, "DELETE", params, null, true),

/**
* @tags institution-controller
* @name createInstitutionUsingPOST
Expand Down
43 changes: 25 additions & 18 deletions client/src/components/DateInput.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
<template>
<a-form-item :label="label">
<a-date-picker
:disabled="disabled"
:format="dateFormat"
:open="dateOfBirthPickerOpen"
@focus="datePickerFocused"
@openChange="openChanged"
placeholder="TT.MM.JJJJ (z.B. 28.02.1986)"
style="width: 100%"
v-decorator="decorator"
/>
</a-form-item>
<a-date-picker
v-bind="$attrs"
v-on="$listeners"
:value="value"
:format="format"
:open="open || dateOfBirthPickerOpen"
@focus="datePickerFocused"
@openChange="openChanged"
:placeholder="placeholder"
/>
</template>

<script lang="ts">
import Vue from 'vue'
import mixins from 'vue-typed-mixins'
import { FormControlMixin } from '@/util/forms'
/**
* Input that supports 1d and 2d Barcodes
Expand All @@ -27,17 +26,25 @@ import Vue from 'vue'
export interface State {
dateOfBirthPickerOpen: boolean;
wasJustFocused: boolean;
dateFormat: string;
}
export default Vue.extend({
name: 'LaboratoryInput',
props: ['decorator', 'label', 'disabled'],
export default mixins(FormControlMixin).extend({
name: 'DateInput',
mixins: [FormControlMixin],
model: {
prop: 'value',
event: 'change',
},
props: {
value: { default: undefined },
open: { default: false },
placeholder: { default: 'TT.MM.JJJJ (z.B. 28.02.1986)' },
format: { default: 'DD.MM.YYYY' },
},
data(): State {
return {
dateOfBirthPickerOpen: false,
wasJustFocused: false,
dateFormat: 'DD.MM.YYYY',
}
},
methods: {
Expand Down
153 changes: 153 additions & 0 deletions client/src/components/EditExposureContact.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<template>
<div class="edit-exposure-contact">
<a-form-item style="display: none;"
:selfUpdate="true">
<a-input type="hidden"
v-decorator="[ formInputKey('id') ]"/>
</a-form-item>
<a-row class="patients-flex">
<!-- Originating and Contact Names -->
<a-form-item
:style="`display: ${$props.showOriginatorPatient ? 'unset' : 'none'}`"
:selfUpdate="true"
label="Ursprungspatient"
class="patient-input">
<patient-input
v-bind="inputProps.source"
:disabled="$props.disableOriginatorPatient"
:filterOption="filterSources"
v-decorator="[ formInputKey('source'), {
rules: [
{ required: true, message: 'Bitte Ursprungspatienten angeben' },
],
}]"/>
</a-form-item>
<a-icon
v-if="$props.showOriginatorPatient && $props.showContactPatient"
type="swap"/>
<a-form-item
:style="`display: ${$props.showContactPatient ? 'unset' : 'none'}`"
:selfUpdate="true"
label="Kontaktperson"
class="patient-input">
<patient-input
v-bind="inputProps.contact"
:disabled="$props.disableContactPatient"
:filterOption="filterContacts"
v-decorator="[ formInputKey('contact'), {
rules: [
{ required: true, message: 'Bitte Kontaktperson angeben' },
],
}]"/>
</a-form-item>
</a-row>
<a-row>
<!-- When and How -->
<a-col :md="11" :sm="24">
<a-form-item label="Datum des Kontakts"
:selfUpdate="true">
<date-input
v-bind="inputProps.dateOfContact"
:disabledDate="date => date.isAfter(moment())"
v-decorator="[ formInputKey('dateOfContact'), {
rules: [
{ required: true, message: 'Bitte ein gültiges Datum angeben' },
],
}]"/>
</a-form-item>
</a-col>
<a-col :md="2" :sm="0"></a-col>
<a-col :md="11" :sm="24">
<a-form-item label="Umgebung / Kontext"
:selfUpdate="true">
<a-auto-complete
v-bind="inputProps.context"
:dataSource="contexts"
:filterOption="false"
v-decorator="[ formInputKey('context'), {
rules: [
{ required: true, message: 'Bitte den Umstand des Kontakts angeben' }
]
}]"/>
</a-form-item>
</a-col>
</a-row>
<a-row>
<!-- Comment Space -->
<a-form-item label="Sonstiges / Kommentar"
:selfUpdate="true">
<a-textarea
v-bind="inputProps.comment"
v-decorator="[ formInputKey('comment'), {
rules: [],
}]"/>
</a-form-item>
</a-row>
</div>
</template>

<script lang="ts">
import Vue from 'vue'
import mixins from 'vue-typed-mixins'
import Api from '@/api'
import moment from 'moment'
import DateInput from '@/components/DateInput.vue'
import PatientInput from '@/components/PatientInput.vue'
import { FormGroupMixin } from '@/util/forms.ts'
const exposureContexts = [
'Haushaltskontakt',
'Berufskontakt',
'Kontakt in Gemeinschaftseinrichtung',
]
export default mixins(FormGroupMixin).extend({
name: 'EditExposureFormGroup',
components: {
DateInput,
PatientInput,
},
inputKeys: ['id', 'source', 'contact', 'dateOfContact', 'context', 'comment'],
props: {
showOriginatorPatient: { default: true },
showContactPatient: { default: true },
disableOriginatorPatient: { default: false },
disableContactPatient: { default: false },
},
data() {
return {
contexts: exposureContexts,
}
},
methods: {
moment,
filterContacts(inputVal: string, option: any): boolean {
return option.key !== (this as any).getSingleValue('source')
},
filterSources(inputVal: string, option: any): boolean {
return option.key !== (this as any).getSingleValue('contact')
},
},
} as any)
</script>

<style lang="scss">
.edit-exposure-contact {
.patients-flex {
display: flex;
flex-flow: row wrap;
align-items: center;
align-content: center;
justify-content: center;
}
.patients-flex > * {
flex: 1 1;
}
.patients-flex > .patient-input {
min-width: 47%;
}
}
</style>
Loading

0 comments on commit 2dffc29

Please sign in to comment.