Group session data can now be submitted and shows in session log

This commit is contained in:
neviyn 2019-02-25 14:59:35 +00:00
parent db00996beb
commit 6f7e5596c3
6 changed files with 83 additions and 68 deletions

View File

@ -33,8 +33,8 @@ data class GroupObservationInit(
) )
data class GroupObservation( data class GroupObservation(
val scenarios: List<Scenario>, val person: String,
val person: String val scenarios: List<Scenario>
) )
data class ObservationsRequest( data class ObservationsRequest(

View File

@ -2,8 +2,6 @@ package uk.co.neviyn.observationdatabase
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.ThreadLocalRandom
@ -12,12 +10,9 @@ object GroupSessionManager {
private val logger: Logger = LoggerFactory.getLogger(javaClass)!! private val logger: Logger = LoggerFactory.getLogger(javaClass)!!
@Autowired
lateinit var websocketMessenger: SimpMessagingTemplate
var sessionId = ThreadLocalRandom.current().nextInt(1000, 9999) var sessionId = ThreadLocalRandom.current().nextInt(1000, 9999)
var site: Site? = null var site: Site? = null
var tutors: Set<Tutor>? = null var tutors: List<Long>? = null
var trainingType: TrainingType? = null var trainingType: TrainingType? = null
var scenarioTitles: List<String>? = null var scenarioTitles: List<String>? = null
var observations: MutableList<Observation> = mutableListOf() var observations: MutableList<Observation> = mutableListOf()
@ -31,7 +26,7 @@ object GroupSessionManager {
} }
logger.debug("New ID is $sessionId") logger.debug("New ID is $sessionId")
this.site = site this.site = site
this.tutors = tutors this.tutors = tutors.map { it.id }
this.trainingType = trainingType this.trainingType = trainingType
this.scenarioTitles = scenarioTitles this.scenarioTitles = scenarioTitles
observations = mutableListOf() observations = mutableListOf()
@ -49,14 +44,5 @@ object GroupSessionManager {
fun addObservation(observation: Observation) { fun addObservation(observation: Observation) {
observations.add(observation) observations.add(observation)
sendObservationsToSocket()
}
private fun sendObservationsToSocket() {
if (::websocketMessenger.isInitialized) {
websocketMessenger.convertAndSend("/ws/observations", mapOf("observations" to observations))
} else {
logger.warn("WebSocket messenger is not initialized. Not sending data to socket.")
}
} }
} }

View File

@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.env.Environment import org.springframework.core.env.Environment
import org.springframework.core.env.get import org.springframework.core.env.get
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.web.bind.annotation.CrossOrigin import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable
@ -17,6 +18,7 @@ import uk.co.neviyn.observationdatabase.GroupObservation
import uk.co.neviyn.observationdatabase.GroupObservationInit import uk.co.neviyn.observationdatabase.GroupObservationInit
import uk.co.neviyn.observationdatabase.GroupSessionManager import uk.co.neviyn.observationdatabase.GroupSessionManager
import uk.co.neviyn.observationdatabase.Observation import uk.co.neviyn.observationdatabase.Observation
import uk.co.neviyn.observationdatabase.ObservationRepository
import uk.co.neviyn.observationdatabase.Person import uk.co.neviyn.observationdatabase.Person
import uk.co.neviyn.observationdatabase.PersonRepository import uk.co.neviyn.observationdatabase.PersonRepository
import uk.co.neviyn.observationdatabase.SiteRepository import uk.co.neviyn.observationdatabase.SiteRepository
@ -39,9 +41,11 @@ class GroupSessionController {
@Autowired @Autowired
lateinit var tutorRepository: TutorRepository lateinit var tutorRepository: TutorRepository
@Autowired @Autowired
lateinit var observationsController: ObservationsController lateinit var observationRepository: ObservationRepository
@Autowired @Autowired
lateinit var personRepository: PersonRepository lateinit var personRepository: PersonRepository
@Autowired
lateinit var websocketMessenger: SimpMessagingTemplate
/** /**
* Start a new Group Observation session * Start a new Group Observation session
@ -95,11 +99,27 @@ class GroupSessionController {
return GroupSessionManager.isValid() return GroupSessionManager.isValid()
} }
/**
* Save an Observation to the database
*/
fun saveObservation(observation: Observation): Observation {
logger.debug("Saving new Observation to database")
val committedObservation = observationRepository.save(observation)
logger.debug("Adding Observation data to Tutor records")
committedObservation.tutors.forEach {
it.observations.add(committedObservation)
tutorRepository.save(it)
}
logger.debug("Observation addition completed")
return committedObservation
}
/** /**
* Submit an observation to be added to the session state and actual database * Submit an observation to be added to the session state and actual database
*/ */
@PostMapping("/submit") @PostMapping("/submit")
fun addGroupObservation(observationData: GroupObservation) { fun addGroupObservation(@Valid @RequestBody observationData: GroupObservation) {
val tutors = tutorRepository.findAllById(GroupSessionManager.tutors!!).toSet()
if (GroupSessionManager.isValid()) { if (GroupSessionManager.isValid()) {
var observation = Observation( var observation = Observation(
site = GroupSessionManager.site!!, site = GroupSessionManager.site!!,
@ -115,11 +135,12 @@ class GroupSessionController {
teamworkWorkload = observationData.scenarios.map { it.teamworkWorkload.rating }.average(), teamworkWorkload = observationData.scenarios.map { it.teamworkWorkload.rating }.average(),
knowledge = observationData.scenarios.map { it.knowledge.rating }.average(), knowledge = observationData.scenarios.map { it.knowledge.rating }.average(),
scenarios = observationData.scenarios, scenarios = observationData.scenarios,
tutors = GroupSessionManager.tutors!!, tutors = tutors,
person = personRepository.findFirstByNameLike(observationData.person.toUpperCase()) ?: personRepository.save(Person(name = observationData.person.toUpperCase())) person = personRepository.findFirstByNameLike(observationData.person.toUpperCase()) ?: personRepository.save(Person(name = observationData.person.toUpperCase()))
) )
observation = observationsController.saveObservation(observation) observation = saveObservation(observation)
GroupSessionManager.addObservation(observation) GroupSessionManager.addObservation(observation)
websocketMessenger.convertAndSend("/ws/observations", mapOf("observations" to GroupSessionManager.observations))
} }
} }

View File

@ -8,6 +8,11 @@
{{ qrdata }} {{ qrdata }}
</p> </p>
</b-col> </b-col>
<b-col>
<b-list-group v-for="(item, index) in data" v-bind:key="index">
<b-list-group-item>{{ item.person.name }}</b-list-group-item>
</b-list-group>
</b-col>
</b-row> </b-row>
<b-row v-else> <b-row v-else>
<b-col> <b-col>
@ -118,7 +123,7 @@ export default {
active: false, active: false,
stompclient: null, stompclient: null,
qrdata: "N/A", qrdata: "N/A",
data: [], data: [{person:{name:"No data yet received."}}],
site: null, site: null,
tutors: null, tutors: null,
siteOptions: [], siteOptions: [],
@ -176,7 +181,7 @@ export default {
) )
.then(function(response) { .then(function(response) {
console.log(response); console.log(response);
if ('error' in response.data) { if ("error" in response.data) {
} else { } else {
let rdata = response.data; let rdata = response.data;
self.qrdata = `http://${rdata.ip}:${rdata.port}/#/groupsession/${ self.qrdata = `http://${rdata.ip}:${rdata.port}/#/groupsession/${
@ -185,19 +190,18 @@ export default {
self.active = true; self.active = true;
self.stompclient = webstomp.over( self.stompclient = webstomp.over(
new SockJS("http://127.0.0.1:8080/websocket", { new SockJS("http://127.0.0.1:8080/websocket", {
heartbeat: false heartbeat: true
}) })
); );
self.stompclient.connect( self.stompclient.connect([], function() {
[],
function() {
self.stompclient.subscribe("/ws/observations", function( self.stompclient.subscribe("/ws/observations", function(
incomingData incomingData
) { ) {
self.data = incomingData.content.observations; self.data = JSON.parse(incomingData.body).observations;
console.log("data #")
console.log(self.data)
});
}); });
}
);
self.$refs.submissionModal.hide(); self.$refs.submissionModal.hide();
self.clearPassword(); self.clearPassword();
} }
@ -213,7 +217,7 @@ export default {
.get("/grpob/recover") .get("/grpob/recover")
.then(function(response) { .then(function(response) {
console.log(response); console.log(response);
if ('error' in response.data) { if ("error" in response.data) {
} else { } else {
let rdata = response.data; let rdata = response.data;
self.data = rdata.observations; self.data = rdata.observations;
@ -228,16 +232,13 @@ export default {
heartbeat: false heartbeat: false
}) })
); );
self.stompclient.connect( self.stompclient.connect([], function() {
[],
function() {
self.stompclient.subscribe("/ws/observations", function( self.stompclient.subscribe("/ws/observations", function(
incomingData incomingData
) { ) {
self.data = incomingData.content.observations; self.data = JSON.parse(incomingData.body).observations;
});
}); });
}
);
self.$refs.submissionModal.hide(); self.$refs.submissionModal.hide();
self.clearPassword(); self.clearPassword();
} }

View File

@ -44,7 +44,7 @@
</b-col> </b-col>
</b-row> </b-row>
<b-row> <b-row>
<b-col cols="12" md="6" class="border"> <b-col cols="12" md="6" xl="3" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Monitoring</h5> <h5>Monitoring</h5>
@ -75,7 +75,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
<b-col cols="12" md="6" class="border"> <b-col cols="12" md="6" xl="3" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Control Procedural</h5> <h5>Control Procedural</h5>
@ -106,9 +106,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
</b-row> <b-col cols="12" md="6" xl="3" class="border">
<b-row>
<b-col cols="12" md="6" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Control</h5> <h5>Control</h5>
@ -139,7 +137,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
<b-col cols="12" md="6" class="border"> <b-col cols="12" md="6" xl="3" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Conservatism</h5> <h5>Conservatism</h5>
@ -170,9 +168,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
</b-row> <b-col cols="12" md="6" xl="3" class="border">
<b-row>
<b-col cols="12" md="6" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Teamwork Communications</h5> <h5>Teamwork Communications</h5>
@ -203,7 +199,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
<b-col cols="12" md="6" class="border"> <b-col cols="12" md="6" xl="3" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Teamwork Leadership</h5> <h5>Teamwork Leadership</h5>
@ -234,9 +230,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
</b-row> <b-col cols="12" md="6" xl="3" class="border">
<b-row>
<b-col cols="12" md="6" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Teamwork Workload</h5> <h5>Teamwork Workload</h5>
@ -267,7 +261,7 @@
</b-col> </b-col>
</b-row> </b-row>
</b-col> </b-col>
<b-col cols="12" md="6" class="border"> <b-col cols="12" md="6" xl="3" class="border">
<b-row> <b-row>
<b-col> <b-col>
<h5>Knowledge</h5> <h5>Knowledge</h5>
@ -305,7 +299,7 @@
<b-button type="submit" variant="primary" v-on:click="onSubmit()">Submit</b-button> <b-button type="submit" variant="primary" v-on:click="onSubmit()">Submit</b-button>
</b-form> </b-form>
</b-container> </b-container>
<b-modal id="submissionModal" ref="submissionModal" title="Confirm Submission" @ok="handleOk"> <b-modal id="submissionModal" ref="submissionModal" title="Confirm Submission" @ok="actuallySubmit()">
<form @submit.stop.prevent="handleSubmit"> <form @submit.stop.prevent="handleSubmit">
<p>Once submitted, data cannot be changed.</p> <p>Once submitted, data cannot be changed.</p>
<p>Are you sure you wish to submit?</p> <p>Are you sure you wish to submit?</p>
@ -411,15 +405,17 @@ export default {
showModal() { showModal() {
this.$refs.submissionModal.show(); this.$refs.submissionModal.show();
}, },
handleSubmit() { actuallySubmit() {
var self = this;
var payload = {
person: self.participant,
scenarios: self.scenarios
}
var form = document.getElementById("submission-form"); var form = document.getElementById("submission-form");
if (form.checkValidity()) { if (form.checkValidity()) {
var self = this; console.log(payload)
Vue.axios Vue.axios
.post("/grpob/submit", { .post("/grpob/submit", payload)
person: self.participant,
scenarios: JSON.parse(JSON.stringify(self.scenarios))
})
.then(function(response) { .then(function(response) {
self.complete = true; self.complete = true;
console.log(response); console.log(response);
@ -434,3 +430,14 @@ export default {
} }
}; };
</script> </script>
<style scoped>
.strength {
background-color: honeydew;
}
.afi {
background-color: mistyrose;
}
.bottom-buffer {
margin-bottom: 10px;
}
</style>

View File

@ -22,7 +22,7 @@
</b-row> </b-row>
<b-row class="my-3" align-h="center"> <b-row class="my-3" align-h="center">
<b-col lg="6" sm="12"> <b-col lg="6" sm="12">
<b-button disabled variant="outline-secondary" class="scale-in-center" size="lg" to="/groupsession" block><v-icon name="users"/> Start a Group Session <b-badge variant="info">Coming Soon!</b-badge></b-button> <b-button class="scale-in-center" size="lg" to="/groupsession" block><v-icon name="users"/> Start a Group Session</b-button>
</b-col> </b-col>
</b-row> </b-row>
</b-container> </b-container>