Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • softwarepraktikum/vis_webtool
1 result
Show changes
Commits on Source (3)
Showing
with 1396 additions and 61 deletions
No preview for this file type
No preview for this file type
No preview for this file type
...@@ -46,6 +46,7 @@ INSTALLED_APPS = [ ...@@ -46,6 +46,7 @@ INSTALLED_APPS = [
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
......
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
...@@ -19,5 +19,6 @@ urlpatterns = [ ...@@ -19,5 +19,6 @@ urlpatterns = [
path('delete/<index>', api_delete_patient_view, name="delete"), path('delete/<index>', api_delete_patient_view, name="delete"),
path('create', api_post_patient_view, name="create"), path('create', api_post_patient_view, name="create"),
path('stats', visual), path('stats', visual),
path('test', queryTest),
] ]
This diff is collapsed.
...@@ -15,6 +15,15 @@ ...@@ -15,6 +15,15 @@
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn v-if="accessToken==null" icon to="/login/">
<v-icon>mdi-account</v-icon>
</v-btn>
<v-btn v-if="accessToken!=null" icon to="/logout/">
<v-icon>mdi-account-minus</v-icon>
</v-btn>
<v-btn icon @click="toggle_dark_mode">
<v-icon>mdi-theme-light-dark</v-icon>
</v-btn>
</v-app-bar> </v-app-bar>
<v-navigation-drawer <v-navigation-drawer
v-model="drawer" v-model="drawer"
...@@ -70,6 +79,12 @@ import getAPI from './axios-api' ...@@ -70,6 +79,12 @@ import getAPI from './axios-api'
this.$router.push({ name: 'login' }) this.$router.push({ name: 'login' })
}) })
}, },
methods: {
toggle_dark_mode: function() {
this.$vuetify.theme.dark = !this.$vuetify.theme.dark;
localStorage.setItem("dark_theme", this.$vuetify.theme.dark.toString());
}
},
mounted() { mounted() {
getAPI.get('/api/patients/', { headers: { Authorization: `Bearer ${this.$store.state.accessToken}` } }) getAPI.get('/api/patients/', { headers: { Authorization: `Bearer ${this.$store.state.accessToken}` } })
.then(response => { .then(response => {
...@@ -78,6 +93,23 @@ import getAPI from './axios-api' ...@@ -78,6 +93,23 @@ import getAPI from './axios-api'
.catch(err => { .catch(err => {
console.log(err) console.log(err)
}) })
const theme = localStorage.getItem("dark_theme");
if (theme) {
if (theme === "true") {
this.$vuetify.theme.dark = true;
} else {
this.$vuetify.theme.dark = false;
}
} else if (
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches
) {
this.$vuetify.theme.dark = true;
localStorage.setItem(
"dark_theme",
this.$vuetify.theme.dark.toString()
);
}
}, },
components: { components: {
ResponsiveNavigation ResponsiveNavigation
......
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
height ="70" height ="70"
> >
</v-sheet> </v-sheet>
<v-card-actions class="justify-center">
<v-btn color="primary" v-if="accessToken==null" to="/login/" >
Login First
</v-btn>
</v-card-actions>
<v-card> <v-card>
<v-card-title> <v-card-title>
<v-text-field <v-text-field
...@@ -75,7 +80,7 @@ ...@@ -75,7 +80,7 @@
<script> <script>
import { mapState, mapActions } from "vuex"; import { mapState} from "vuex";
import getAPI from '../axios-api' import getAPI from '../axios-api'
export default { export default {
...@@ -88,7 +93,6 @@ export default { ...@@ -88,7 +93,6 @@ export default {
}, },
computed:{ computed:{
patients() { patients() {
return this.$store.state.patients return this.$store.state.patients
...@@ -122,9 +126,10 @@ export default { ...@@ -122,9 +126,10 @@ export default {
} }
}); });
}, },
...mapState(['accessToken']),
}, },
methods: { methods: {
createPatient() { createPatient() {
this.$router.push({path: `/create/`}) this.$router.push({path: `/create/`})
}, },
......
<template>
<div>
<div class="container">
<div class="Chart">
<h2 style="text-align:center;">Überblick:</h2>
</div>
</div>
<v-flex xs6>
<v-select
:items="geschlecht"
label="Geschlecht"
@change="sendGender"
></v-select>
</v-flex>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Es sind im Moment {{ APIData.amount }} Patienten gespeichert:<br><br>Alter der
Patienten:<br>(Durchschnitt: {{ APIData.averageage }})</h1>
</div>
</div>
<v-card-text>
<v-sparkline
:value="[APIData.old, APIData.mid, APIData.young]"
:labels="[
'vor 1940 (' + Math.round((APIData.old/((APIData.old+APIData.mid+APIData.young)/100))) + '%)' ,
'zw. 1940-1970 (' + Math.round((APIData.mid/((APIData.old+APIData.mid+APIData.young)/100))) + '%)',
'nach 1970 (' + Math.round((APIData.young/((APIData.old+APIData.mid+APIData.young)/100))) + '%)'
]"
:gradient="gradient1"
:smooth="radius || false"
:padding="padding"
:line-width="widthBar"
:stroke-linecap="lineCap"
:gradient-direction="gradientDirection"
:fill="fill"
:type="'bar'"
:auto-line-width="autoLineWidth"
auto-draw
>
</v-sparkline>
</v-card-text>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Verteilung Männer/Frauen:</h1>
</div>
</div>
<v-card-text>
<v-sparkline
:value="[APIData.M, APIData.W]"
:labels="[
'Männer (' + Math.round((APIData.M/((APIData.M+APIData.W)/100))) + '%)',
'Frauen (' + Math.round((APIData.W/((APIData.W+APIData.M)/100))) + '%)',
]"
:gradient="gradient1"
:smooth="radius || false"
:padding="padding"
:line-width="widthBar"
:stroke-linecap="lineCap"
:gradient-direction="gradientDirection"
:fill="fill"
:type="'bar'"
:auto-line-width="autoLineWidth"
auto-draw
>
</v-sparkline>
</v-card-text>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Art des Aufenthalts:</h1>
</div>
</div>
<v-card-text>
<v-sparkline
:value="[APIData.stationaer, APIData.ambulant, APIData.teilstationaer]"
:labels="labels1"
:gradient="gradient1"
:smooth="radius || false"
:padding="padding"
:line-width="widthBar"
:stroke-linecap="lineCap"
:gradient-direction="gradientDirection"
:fill="fill"
:type="'bar'"
:auto-line-width="autoLineWidth"
auto-draw
>
</v-sparkline>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Verteilung der Untersuchungen über die<br><br></br>Monate:</h1>
</div>
</div>
<v-sparkline
:value="[APIData.jan, APIData.feb, APIData.maer, APIData.apr, APIData.mai, APIData.jun, APIData.jul, APIData.aug, APIData.sep, APIData.okt, APIData.nov, APIData.dez]"
:labels="labels"
:gradient="gradient"
:smooth="radius || false"
:padding="padding"
:line-width="width"
:stroke-linecap="lineCap"
:gradient-direction="gradientDirection"
:fill="fill"
:type="type"
:auto-line-width="autoLineWidth"
auto-draw
>
</v-sparkline>
</v-card-text>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Alter der Patientendaten</h1>
</div>
</div>
<v-row justify="space-around">
<v-avatar
color="indigo"
size="200"
>
<span class="white--text headline"><br>25% der Daten sind älter als:<br>{{ APIData.twentyfife }}</span>
</v-avatar>
<v-avatar
color="teal"
size="400"
>
<span class="white--text headline">50% der Daten sind älter als:<br>{{ APIData.fifty }}</span>
</v-avatar>
<v-avatar
color="orange"
size="600"
>
<span class="white--text headline">75% der Daten sind älter als:<br>{{ APIData.seventyfive }}</span>
</v-avatar>
</v-row>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Untersuchung die durchgeführt wurden:</h1>
</div>
</div>
<v-card-text>
<v-sparkline
:value="[APIData.fanzahl1, APIData.fanzahl2, APIData.fanzahl3, APIData.amount-APIData.fanzahl1-APIData.fanzahl2-APIData.fanzahl3-APIData.fanzahl4 ]"
:labels="[
APIData.fname1 + '('+ Math.round((APIData.fanzahl1/((APIData.fanzahl1+APIData.fanzahl2+APIData.fanzahl3+APIData.fanzahl4+(APIData.amount-APIData.fanzahl1-APIData.fanzahl2-APIData.fanzahl3))/100))) + '%)',
APIData.fname2 + '('+ Math.round((APIData.fanzahl2/((APIData.fanzahl1+APIData.fanzahl2+APIData.fanzahl3+APIData.fanzahl4+(APIData.amount-APIData.fanzahl1-APIData.fanzahl2-APIData.fanzahl3))/100))) + '%)',
APIData.fname3 + '('+ Math.round((APIData.fanzahl3/((APIData.fanzahl1+APIData.fanzahl2+APIData.fanzahl3+APIData.fanzahl4+(APIData.amount-APIData.fanzahl1-APIData.fanzahl2-APIData.fanzahl3))/100))) + '%)',
'andere'+ '('+ Math.round(((APIData.amount-APIData.fanzahl1-APIData.fanzahl2-APIData.fanzahl3)/((APIData.fanzahl1+APIData.fanzahl2+APIData.fanzahl3+APIData.fanzahl4+(APIData.amount-APIData.fanzahl1-APIData.fanzahl2-APIData.fanzahl3))/100))) + '%)'
]"
:gradient="gradient1"
:smooth="radius || false"
:padding="padding"
:line-width="widthBar"
:stroke-linecap="lineCap"
:gradient-direction="gradientDirection"
:fill="fill"
:type="'bar'"
:auto-line-width="autoLineWidth"
auto-draw
>
</v-sparkline>
</v-card-text>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">Krankheiten auf Grundlage der Anamnese:</h1>
</div>
</div>
<v-card-text>
<v-sparkline
:value="[APIData.Achalasie, APIData.Reflux, APIData.Ösophagusstenose, APIData.Zoeliakie, APIData.Polypektomie, APIData.Adipositas]"
:labels="[
'(1)',
'(2)',
'(3)',
'(4)',
'(5)',
'(6)'
]"
:gradient="gradient1"
:smooth="radius || false"
:padding="padding"
:line-width="widthBar"
:stroke-linecap="lineCap"
:gradient-direction="gradientDirection"
:fill="fill"
:type="'bar'"
:auto-line-width="autoLineWidth"
auto-draw
>
</v-sparkline>
</v-card-text>
<div class="container">
<div class="Chart">
<h1 style="text-align:center;">(1)Achalasie ({{ APIData.Achalasie }})<br>(2)Reflux ({{ APIData.Reflux }})<br>(3)Ösophagusstenose
({{ APIData.Ösophagusstenose }})<br>(4)Zoeliakie ({{ APIData.Zoeliakie }})<br>(5)Polypektomie
({{ APIData.Polypektomie }})<br>(6)Adipositas ({{ APIData.Adipositas }})</h1>
</div>
</div>
<div class="container">
<div class="Chart">
<h3 style="text-align:center;">Daten in jupyter Notebook selber bearbeiten<br>(beachte Voraussetzung in
Handbuch):<br><a href="./jupyter_notebook.ipynb" target="_blank">jupyter_notebook</a></h3>
</div>
</div>
</div>
</template>
<script>
const gradients = [
['#222'],
['#42b3f4'],
['red', 'orange', 'yellow'],
['purple', 'violet'],
['#00c6ff', '#F0F', '#FF0'],
['#f72047', '#ffd200', '#1feaea'],
['violet', 'black']
]
import getAPI from '../axios-api'
export default {
name: 'StatsTest',
data() {
return {
geschlecht: ['W', 'M', ''],
APIData: [],
width: 2,
widthBar: 10,
radius: 10,
padding: 20,
lineCap: 'round',
gradient: gradients[5],
gradient1: gradients[6],
gradient2: gradients[0],
gradientDirection: 'top',
fill: false,
autoLineWidth: false,
labels: [
'Jan',
'Feb',
'Mär',
'Apr',
'Mai',
'Jun',
'Jul',
'Aug',
'Sep',
'Okt',
'Nov',
'Dez'
],
labels1: [
' ',
'Stationaer',
'Ambulant',
'Teilstationär',
'Poststationär',
' '
],
}
},
created() {
getAPI.get('/api/test',)
.then(response => {
console.log('Post API has recieved data')
this.APIData = response.data
})
.catch(err => {
console.log(err)
})
},
computed: {
myStyles() {
return {
height: `${this.height}px`,
position: 'relative'
}
}
},
methods: {
async sendGender(val) {
try {
const formData = new FormData()
formData.append('geschlecht', val)
await getAPI.post('api/test', formData)
.then()
} catch (error) {
console.log(error)
}
vm.$forceUpdate()
},
},
props: {
msg: String
}
}
</script>
<style scoped>
.chart-wrapper {
width: 100%;
height: 700px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
h1 {
font-family: 'Helvetica', Arial;
color: #464646;
text-transform: uppercase;
border-bottom: 1px solid #f1f1f1;
padding-bottom: 15px;
font-size: 28px;
margin-top: 0;
}
.Chart {
padding: 20px;
box-shadow: 0px 0px 20px 2px rgba(0, 0, 0, .4);
border-radius: 20px;
margin: 50px 0;
}
h2 {
font-family: 'Helvetica', Arial;
color: #464646;
text-transform: uppercase;
border-bottom: 1px solid #f1f1f1;
padding-bottom: 15px;
font-size: 50px;
margin-top: 0;
}
h2 {
font-family: 'Helvetica', Arial;
color: #464646;
text-transform: uppercase;
border-bottom: 1px solid #f1f1f1;
padding-bottom: 15px;
font-size: 30px;
margin-top: 0;
}
</style>
...@@ -36,6 +36,13 @@ const routes = [ ...@@ -36,6 +36,13 @@ const routes = [
return import('../components/Stats.vue') return import('../components/Stats.vue')
} }
}, },
{
path: '/statstest/',
name: 'StatsTest',
component: function () {
return import('../components/StatsTest.vue')
}
},
{ {
path: '/upload/', path: '/upload/',
name: 'Upload', name: 'Upload',
......
...@@ -8,12 +8,18 @@ ...@@ -8,12 +8,18 @@
<p v-if="incorrectAuth">Incorrect username or password entered - please try again</p> <p v-if="incorrectAuth">Incorrect username or password entered - please try again</p>
<form v-on:submit.prevent="login"> <form v-on:submit.prevent="login">
<div class="form-group"> <div class="form-group">
<input type="text" name="username" id="user" v-model="username" class="form-control" placeholder="Username"> <v-text-field v-model="username" label="Username"/>
<v-text-field
v-model="password"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:rules="[rules.required]"
:type="show1 ? 'text' : 'password'"
name="input-10-1"
label="Password"
@click:append="show1 = !show1"
></v-text-field>
</div> </div>
<div class="form-group"> <v-btn type="submit" class="btn btn-lg btn-primary btn-block">Login</v-btn>
<input type="password" name="password" id="pass" v-model="password" class="form-control" placeholder="Password">
</div>
<button type="submit" class="btn btn-lg btn-primary btn-block">Login</button>
</form> </form>
</div> </div>
...@@ -23,13 +29,20 @@ ...@@ -23,13 +29,20 @@
</template> </template>
<script> <script>
export default { export default {
name: 'login', name: 'login',
data () { data () {
return { return {
username: '', username: '',
password: '', password: '',
incorrectAuth: false incorrectAuth: false,
show1: false,
rules: {
required: value => !!value || 'Required.',
},
} }
}, },
methods: { methods: {
...@@ -46,7 +59,8 @@ ...@@ -46,7 +59,8 @@
this.incorrectAuth = true this.incorrectAuth = true
}) })
} }
} },
} }
</script> </script>
......