Group sessions now show current data in a scenario format.
Remote users are now informed when session is closed.
This commit is contained in:
parent
6f7e5596c3
commit
6f4da05ddc
@ -147,7 +147,19 @@ data class Scenario(
|
|||||||
@OneToOne(cascade = [CascadeType.ALL])
|
@OneToOne(cascade = [CascadeType.ALL])
|
||||||
val knowledge: RatingComponent
|
val knowledge: RatingComponent
|
||||||
|
|
||||||
)
|
) {
|
||||||
|
fun ratingsAllValid(): Boolean {
|
||||||
|
val limitation = 1..5
|
||||||
|
return monitoring.rating in limitation &&
|
||||||
|
controlProcedural.rating in limitation &&
|
||||||
|
control.rating in limitation &&
|
||||||
|
conservatism.rating in limitation &&
|
||||||
|
teamworkCommunications.rating in limitation &&
|
||||||
|
teamworkLeadership.rating in limitation &&
|
||||||
|
teamworkWorkload.rating in limitation &&
|
||||||
|
knowledge.rating in limitation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
data class Person(
|
data class Person(
|
||||||
|
@ -15,7 +15,7 @@ object GroupSessionManager {
|
|||||||
var tutors: List<Long>? = 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: MutableMap<String, GroupObservation> = mutableMapOf()
|
||||||
|
|
||||||
fun startNewSession(site: Site, tutors: Set<Tutor>, trainingType: TrainingType, scenarioTitles: List<String>): Int {
|
fun startNewSession(site: Site, tutors: Set<Tutor>, trainingType: TrainingType, scenarioTitles: List<String>): Int {
|
||||||
logger.info("Starting new Group Session")
|
logger.info("Starting new Group Session")
|
||||||
@ -29,11 +29,19 @@ object GroupSessionManager {
|
|||||||
this.tutors = tutors.map { it.id }
|
this.tutors = tutors.map { it.id }
|
||||||
this.trainingType = trainingType
|
this.trainingType = trainingType
|
||||||
this.scenarioTitles = scenarioTitles
|
this.scenarioTitles = scenarioTitles
|
||||||
observations = mutableListOf()
|
observations = mutableMapOf()
|
||||||
logger.debug("Group session initialized")
|
logger.debug("Group session initialized")
|
||||||
return sessionId
|
return sessionId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun invalidate() {
|
||||||
|
this.site = null
|
||||||
|
this.tutors = null
|
||||||
|
this.trainingType = null
|
||||||
|
this.scenarioTitles = null
|
||||||
|
this.observations = mutableMapOf()
|
||||||
|
}
|
||||||
|
|
||||||
fun isValid(sessionId: Int): Boolean {
|
fun isValid(sessionId: Int): Boolean {
|
||||||
return isValid() && sessionId == this.sessionId
|
return isValid() && sessionId == this.sessionId
|
||||||
}
|
}
|
||||||
@ -42,7 +50,30 @@ object GroupSessionManager {
|
|||||||
return site != null && tutors != null && trainingType != null && scenarioTitles != null
|
return site != null && tutors != null && trainingType != null && scenarioTitles != null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addObservation(observation: Observation) {
|
fun asScenarioView(): MutableMap<String, MutableList<Scenario>> {
|
||||||
observations.add(observation)
|
val output: MutableMap<String, MutableList<Scenario>> = mutableMapOf()
|
||||||
|
scenarioTitles?.forEach { title ->
|
||||||
|
output[title] = mutableListOf()
|
||||||
|
}
|
||||||
|
observations.forEach { k, v ->
|
||||||
|
v.scenarios.forEach {
|
||||||
|
output[it.title]?.add(it.copy(title = k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dataComplete(): Boolean {
|
||||||
|
observations.values.forEach {
|
||||||
|
it.scenarios.forEach { x ->
|
||||||
|
if (!x.ratingsAllValid())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateObservationData(input: GroupObservation) {
|
||||||
|
observations[input.person] = input
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,7 +40,7 @@ class CustomWebSecurityConfigurerAdapter : WebSecurityConfigurerAdapter() {
|
|||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
override fun configure(http: HttpSecurity) {
|
override fun configure(http: HttpSecurity) {
|
||||||
http.csrf().disable().authorizeRequests()
|
http.csrf().disable().authorizeRequests()
|
||||||
.antMatchers(HttpMethod.POST, "/api/site", "/api/tutor", "/api/observation", "/api/grpob/start").authenticated()
|
.antMatchers(HttpMethod.POST, "/api/site", "/api/tutor", "/api/observation", "/api/grpob/start", "/api/grpob/complete").authenticated()
|
||||||
.anyRequest().permitAll()
|
.anyRequest().permitAll()
|
||||||
.and()
|
.and()
|
||||||
.httpBasic()
|
.httpBasic()
|
||||||
|
@ -73,7 +73,7 @@ class GroupSessionController {
|
|||||||
fun reconnectToGroupObservation(): Map<String, Any> {
|
fun reconnectToGroupObservation(): Map<String, Any> {
|
||||||
if (GroupSessionManager.isValid()) {
|
if (GroupSessionManager.isValid()) {
|
||||||
logger.info("Previous group observation requested, current id ${GroupSessionManager.sessionId}")
|
logger.info("Previous group observation requested, current id ${GroupSessionManager.sessionId}")
|
||||||
return getConnectionDetails().plus(mapOf("id" to GroupSessionManager.sessionId.toString(), "observations" to GroupSessionManager.observations))
|
return getConnectionDetails().plus(mapOf("id" to GroupSessionManager.sessionId.toString(), "scenarios" to GroupSessionManager.asScenarioView()))
|
||||||
}
|
}
|
||||||
logger.info("Tried to recover a session but no session is active")
|
logger.info("Tried to recover a session but no session is active")
|
||||||
return mapOf("error" to "No session currently active")
|
return mapOf("error" to "No session currently active")
|
||||||
@ -119,29 +119,41 @@ class GroupSessionController {
|
|||||||
*/
|
*/
|
||||||
@PostMapping("/submit")
|
@PostMapping("/submit")
|
||||||
fun addGroupObservation(@Valid @RequestBody observationData: GroupObservation) {
|
fun addGroupObservation(@Valid @RequestBody observationData: GroupObservation) {
|
||||||
|
GroupSessionManager.updateObservationData(observationData)
|
||||||
|
websocketMessenger.convertAndSend("/ws/scenarios", mapOf("scenarios" to GroupSessionManager.asScenarioView()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/complete")
|
||||||
|
fun pushObservationsToDatabase(): Map<String, String> {
|
||||||
|
if (GroupSessionManager.isValid() && GroupSessionManager.dataComplete()) {
|
||||||
val tutors = tutorRepository.findAllById(GroupSessionManager.tutors!!).toSet()
|
val tutors = tutorRepository.findAllById(GroupSessionManager.tutors!!).toSet()
|
||||||
if (GroupSessionManager.isValid()) {
|
GroupSessionManager.observations.values.forEach { x ->
|
||||||
var observation = Observation(
|
saveObservation(Observation(
|
||||||
site = GroupSessionManager.site!!,
|
site = GroupSessionManager.site!!,
|
||||||
date = LocalDate.now(),
|
date = LocalDate.now(),
|
||||||
type = GroupSessionManager.trainingType!!,
|
type = GroupSessionManager.trainingType!!,
|
||||||
observed = observationData.scenarios.joinToString { it.title },
|
observed = x.scenarios.joinToString { it.title },
|
||||||
monitoring = observationData.scenarios.map { it.monitoring.rating }.average(),
|
monitoring = x.scenarios.map { it.monitoring.rating }.average(),
|
||||||
conservatism = observationData.scenarios.map { it.conservatism.rating }.average(),
|
conservatism = x.scenarios.map { it.conservatism.rating }.average(),
|
||||||
controlProcedural = observationData.scenarios.map { it.controlProcedural.rating }.average(),
|
controlProcedural = x.scenarios.map { it.controlProcedural.rating }.average(),
|
||||||
control = observationData.scenarios.map { it.control.rating }.average(),
|
control = x.scenarios.map { it.control.rating }.average(),
|
||||||
teamworkCommunications = observationData.scenarios.map { it.teamworkCommunications.rating }.average(),
|
teamworkCommunications = x.scenarios.map { it.teamworkCommunications.rating }.average(),
|
||||||
teamworkLeadership = observationData.scenarios.map { it.teamworkLeadership.rating }.average(),
|
teamworkLeadership = x.scenarios.map { it.teamworkLeadership.rating }.average(),
|
||||||
teamworkWorkload = observationData.scenarios.map { it.teamworkWorkload.rating }.average(),
|
teamworkWorkload = x.scenarios.map { it.teamworkWorkload.rating }.average(),
|
||||||
knowledge = observationData.scenarios.map { it.knowledge.rating }.average(),
|
knowledge = x.scenarios.map { it.knowledge.rating }.average(),
|
||||||
scenarios = observationData.scenarios,
|
scenarios = x.scenarios,
|
||||||
tutors = tutors,
|
tutors = tutors,
|
||||||
person = personRepository.findFirstByNameLike(observationData.person.toUpperCase()) ?: personRepository.save(Person(name = observationData.person.toUpperCase()))
|
person = personRepository.findFirstByNameLike(x.person.toUpperCase())
|
||||||
)
|
?: personRepository.save(Person(name = x.person.toUpperCase()))
|
||||||
observation = saveObservation(observation)
|
))
|
||||||
GroupSessionManager.addObservation(observation)
|
|
||||||
websocketMessenger.convertAndSend("/ws/observations", mapOf("observations" to GroupSessionManager.observations))
|
|
||||||
}
|
}
|
||||||
|
GroupSessionManager.invalidate()
|
||||||
|
websocketMessenger.convertAndSend("/ws/status", mapOf("status" to "complete"))
|
||||||
|
return mapOf("success" to "The submission was successfully completed.")
|
||||||
|
} else if (!GroupSessionManager.dataComplete()) {
|
||||||
|
return mapOf("error" to "Data is incomplete")
|
||||||
|
}
|
||||||
|
return mapOf("error" to "Session was not valid")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,17 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<b-container>
|
<b-container fluid>
|
||||||
<b-row v-if="active">
|
<b-row v-if="active">
|
||||||
<b-col cols="3">
|
<b-col cols="12" md="3">
|
||||||
<vue-qrcode v-model="qrdata" :options="{ width: 250 }"></vue-qrcode>
|
<vue-qrcode v-model="qrdata" :options="{ width: 250 }"></vue-qrcode>
|
||||||
<p>Scan the code or navigate to
|
<p>Scan the code or navigate to
|
||||||
<br>
|
<br>
|
||||||
{{ qrdata }}
|
{{ qrdata }}
|
||||||
</p>
|
</p>
|
||||||
</b-col>
|
</b-col>
|
||||||
|
<b-col cols="12" md="9">
|
||||||
|
<b-card-group v-for="(item, index) in data" v-bind:key="index">
|
||||||
|
<b-card border-variant="secondary" header-border-variant="secondary" :header="index">
|
||||||
|
<b-card-text>
|
||||||
|
<b-table :fields="tableFields" :items="item"></b-table>
|
||||||
|
</b-card-text>
|
||||||
|
</b-card>
|
||||||
|
</b-card-group>
|
||||||
|
</b-col>
|
||||||
<b-col>
|
<b-col>
|
||||||
<b-list-group v-for="(item, index) in data" v-bind:key="index">
|
<b-button size="lg" variant="primary" v-on:click="showCompletionModal()">Finish Session</b-button>
|
||||||
<b-list-group-item>{{ item.person.name }}</b-list-group-item>
|
</b-col>
|
||||||
</b-list-group>
|
</b-row>
|
||||||
|
<b-row v-else-if="complete">
|
||||||
|
<b-col>
|
||||||
|
<b-row>
|
||||||
|
<b-col>
|
||||||
|
<h2>Session Complete</h2>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row>
|
||||||
|
<b-col>
|
||||||
|
<p>Observation data for this session is now saved in the database.</p>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row>
|
||||||
|
<b-col>
|
||||||
|
<b-button
|
||||||
|
size="lg"
|
||||||
|
variant="primary"
|
||||||
|
v-on:click="window.location.reload()"
|
||||||
|
>Start a New Session</b-button>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<b-row v-else>
|
<b-row v-else>
|
||||||
@ -99,7 +129,7 @@
|
|||||||
<b-modal
|
<b-modal
|
||||||
id="submissionModal"
|
id="submissionModal"
|
||||||
ref="submissionModal"
|
ref="submissionModal"
|
||||||
title="Enter password to confirm submission"
|
title="Enter password to confirm session start"
|
||||||
@ok="handleOk"
|
@ok="handleOk"
|
||||||
@shown="clearPassword"
|
@shown="clearPassword"
|
||||||
>
|
>
|
||||||
@ -107,6 +137,17 @@
|
|||||||
<b-form-input type="password" placeholder="Enter password" v-model="submitPassword"></b-form-input>
|
<b-form-input type="password" placeholder="Enter password" v-model="submitPassword"></b-form-input>
|
||||||
</form>
|
</form>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
|
<b-modal
|
||||||
|
id="completionModal"
|
||||||
|
ref="completionModal"
|
||||||
|
title="Enter password to confirm submission"
|
||||||
|
@ok="handleSubmitComplete"
|
||||||
|
@shown="clearPassword"
|
||||||
|
>
|
||||||
|
<form @submit.stop.prevent="handleSubmit">
|
||||||
|
<b-form-input type="password" placeholder="Enter password" v-model="submitPassword"></b-form-input>
|
||||||
|
</form>
|
||||||
|
</b-modal>
|
||||||
</b-container>
|
</b-container>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -122,6 +163,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
active: false,
|
active: false,
|
||||||
stompclient: null,
|
stompclient: null,
|
||||||
|
complete: false,
|
||||||
qrdata: "N/A",
|
qrdata: "N/A",
|
||||||
data: [{ person: { name: "No data yet received." } }],
|
data: [{ person: { name: "No data yet received." } }],
|
||||||
site: null,
|
site: null,
|
||||||
@ -130,7 +172,21 @@ export default {
|
|||||||
tutorOptions: [],
|
tutorOptions: [],
|
||||||
scenarioTitles: [{ data: "" }, { data: "" }, { data: "" }],
|
scenarioTitles: [{ data: "" }, { data: "" }, { data: "" }],
|
||||||
type: null,
|
type: null,
|
||||||
submitPassword: null
|
submitPassword: null,
|
||||||
|
tableFields: [
|
||||||
|
{ key: "title", label: "Name" },
|
||||||
|
{ key: "monitoring.rating", label: "Monitoring" },
|
||||||
|
{ key: "controlProcedural.rating", label: "Control Procedural" },
|
||||||
|
{ key: "control.rating", label: "Control" },
|
||||||
|
{ key: "conservatism.rating", label: "Conservatism" },
|
||||||
|
{
|
||||||
|
key: "teamworkCommunications.rating",
|
||||||
|
label: "Teamwork Communications"
|
||||||
|
},
|
||||||
|
{ key: "teamworkLeadership.rating", label: "Teamwork Leadership" },
|
||||||
|
{ key: "teamworkWorkload.rating", label: "Teamwork Workload" },
|
||||||
|
{ key: "knowledge.rating", label: "Knowledge" }
|
||||||
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -183,27 +239,7 @@ export default {
|
|||||||
console.log(response);
|
console.log(response);
|
||||||
if ("error" in response.data) {
|
if ("error" in response.data) {
|
||||||
} else {
|
} else {
|
||||||
let rdata = response.data;
|
self.setupSession(response.data);
|
||||||
self.qrdata = `http://${rdata.ip}:${rdata.port}/#/groupsession/${
|
|
||||||
rdata.id
|
|
||||||
}`;
|
|
||||||
self.active = true;
|
|
||||||
self.stompclient = webstomp.over(
|
|
||||||
new SockJS("http://127.0.0.1:8080/websocket", {
|
|
||||||
heartbeat: true
|
|
||||||
})
|
|
||||||
);
|
|
||||||
self.stompclient.connect([], function() {
|
|
||||||
self.stompclient.subscribe("/ws/observations", function(
|
|
||||||
incomingData
|
|
||||||
) {
|
|
||||||
self.data = JSON.parse(incomingData.body).observations;
|
|
||||||
console.log("data #")
|
|
||||||
console.log(self.data)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
self.$refs.submissionModal.hide();
|
|
||||||
self.clearPassword();
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
@ -219,28 +255,7 @@ export default {
|
|||||||
console.log(response);
|
console.log(response);
|
||||||
if ("error" in response.data) {
|
if ("error" in response.data) {
|
||||||
} else {
|
} else {
|
||||||
let rdata = response.data;
|
self.setupSession(response.data);
|
||||||
self.data = rdata.observations;
|
|
||||||
self.qrdata = `http://${rdata.ip}:${rdata.port}/#/groupsession/${
|
|
||||||
rdata.id
|
|
||||||
}`;
|
|
||||||
console.log(self.active);
|
|
||||||
self.active = true;
|
|
||||||
console.log(self.active);
|
|
||||||
self.stompclient = webstomp.over(
|
|
||||||
new SockJS("http://127.0.0.1:8080/websocket", {
|
|
||||||
heartbeat: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
self.stompclient.connect([], function() {
|
|
||||||
self.stompclient.subscribe("/ws/observations", function(
|
|
||||||
incomingData
|
|
||||||
) {
|
|
||||||
self.data = JSON.parse(incomingData.body).observations;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
self.$refs.submissionModal.hide();
|
|
||||||
self.clearPassword();
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
@ -250,6 +265,27 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
setupSession: function(rdata) {
|
||||||
|
console.log("rdata");
|
||||||
|
console.log(rdata);
|
||||||
|
var self = this;
|
||||||
|
self.qrdata = `http://${rdata.ip}:${rdata.port}/#/groupsession/${
|
||||||
|
rdata.id
|
||||||
|
}`;
|
||||||
|
self.active = true;
|
||||||
|
self.stompclient = webstomp.over(
|
||||||
|
new SockJS("http://127.0.0.1:8080/websocket", {
|
||||||
|
heartbeat: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
self.stompclient.connect([], function() {
|
||||||
|
self.stompclient.subscribe("/ws/scenarios", function(incomingData) {
|
||||||
|
self.data = JSON.parse(incomingData.body).scenarios;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
self.$refs.submissionModal.hide();
|
||||||
|
self.clearPassword();
|
||||||
|
},
|
||||||
getTutors: function() {
|
getTutors: function() {
|
||||||
if (this.site != null) {
|
if (this.site != null) {
|
||||||
Vue.axios
|
Vue.axios
|
||||||
@ -277,6 +313,9 @@ export default {
|
|||||||
showModal() {
|
showModal() {
|
||||||
this.$refs.submissionModal.show();
|
this.$refs.submissionModal.show();
|
||||||
},
|
},
|
||||||
|
showCompletionModal() {
|
||||||
|
this.$refs.completionModal.show();
|
||||||
|
},
|
||||||
clearPassword() {
|
clearPassword() {
|
||||||
this.submitPassword = null;
|
this.submitPassword = null;
|
||||||
},
|
},
|
||||||
@ -286,6 +325,31 @@ export default {
|
|||||||
if (this.submitPassword !== null) {
|
if (this.submitPassword !== null) {
|
||||||
this.startSession();
|
this.startSession();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
handleSubmitComplete(evt) {
|
||||||
|
// Prevent modal from closing
|
||||||
|
var self = this;
|
||||||
|
evt.preventDefault();
|
||||||
|
if (this.submitPassword !== null) {
|
||||||
|
let axiosConfig = {
|
||||||
|
auth: {
|
||||||
|
username: "admin",
|
||||||
|
password: this.submitPassword
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Vue.axios
|
||||||
|
.post("/grpob/complete", {}, axiosConfig)
|
||||||
|
.then(function(response) {
|
||||||
|
console.log(response.data);
|
||||||
|
if ("success" in response.data) {
|
||||||
|
self.complete = true;
|
||||||
|
self.active = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
</b-container>
|
</b-container>
|
||||||
<b-container v-else-if="complete">
|
<b-container v-else-if="complete">
|
||||||
<h2>Submission Complete</h2>
|
<h2>Submission Complete</h2>
|
||||||
<p>Thank you. Your observation data has been submitted.</p>
|
<p>Thank you.</p>
|
||||||
<p>Your observation summary will shortly appear on the session display.</p>
|
<p>This observation session is now closed and your data submitted to the database.</p>
|
||||||
</b-container>
|
</b-container>
|
||||||
<b-container v-else-if="!valid">
|
<b-container v-else-if="!valid">
|
||||||
<p>Getting session data from server</p>
|
<p>Getting session data from server</p>
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<p>No scenarios defined for this session, please setup a new group session</p>
|
<p>No scenarios defined for this session, please setup a new group session</p>
|
||||||
</b-container>
|
</b-container>
|
||||||
<b-container v-else fluid>
|
<b-container v-else fluid>
|
||||||
<b-form @submit="onSubmit" id="submission-form" novalidate>
|
<b-form>
|
||||||
<b-row align-h="center">
|
<b-row align-h="center">
|
||||||
<b-col>
|
<b-col>
|
||||||
<b-form-group label="Participant">
|
<b-form-group label="Participant">
|
||||||
@ -35,12 +35,7 @@
|
|||||||
<b-col>
|
<b-col>
|
||||||
<b-row>
|
<b-row>
|
||||||
<b-col>
|
<b-col>
|
||||||
<b-form-input
|
<b-form-input v-model="item.title" type="text" readonly></b-form-input>
|
||||||
v-model="item.title"
|
|
||||||
type="text"
|
|
||||||
placeholder="Enter scenario description."
|
|
||||||
readonly
|
|
||||||
></b-form-input>
|
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<b-row>
|
<b-row>
|
||||||
@ -50,7 +45,7 @@
|
|||||||
<h5>Monitoring</h5>
|
<h5>Monitoring</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.monitoring.rating"
|
:score-value="item.monitoring.rating"
|
||||||
v-on:newselection="item.monitoring.rating = $event;"
|
v-on:newselection="item.monitoring.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -81,7 +76,7 @@
|
|||||||
<h5>Control Procedural</h5>
|
<h5>Control Procedural</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.controlProcedural.rating"
|
:score-value="item.controlProcedural.rating"
|
||||||
v-on:newselection="item.controlProcedural.rating = $event;"
|
v-on:newselection="item.controlProcedural.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -112,7 +107,7 @@
|
|||||||
<h5>Control</h5>
|
<h5>Control</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.control.rating"
|
:score-value="item.control.rating"
|
||||||
v-on:newselection="item.control.rating = $event;"
|
v-on:newselection="item.control.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -143,7 +138,7 @@
|
|||||||
<h5>Conservatism</h5>
|
<h5>Conservatism</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.conservatism.rating"
|
:score-value="item.conservatism.rating"
|
||||||
v-on:newselection="item.conservatism.rating = $event;"
|
v-on:newselection="item.conservatism.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -174,7 +169,7 @@
|
|||||||
<h5>Teamwork Communications</h5>
|
<h5>Teamwork Communications</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.teamworkCommunications.rating"
|
:score-value="item.teamworkCommunications.rating"
|
||||||
v-on:newselection="item.teamworkCommunications.rating = $event;"
|
v-on:newselection="item.teamworkCommunications.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -205,7 +200,7 @@
|
|||||||
<h5>Teamwork Leadership</h5>
|
<h5>Teamwork Leadership</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.teamworkLeadership.rating"
|
:score-value="item.teamworkLeadership.rating"
|
||||||
v-on:newselection="item.teamworkLeadership.rating = $event;"
|
v-on:newselection="item.teamworkLeadership.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -236,7 +231,7 @@
|
|||||||
<h5>Teamwork Workload</h5>
|
<h5>Teamwork Workload</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.teamworkWorkload.rating"
|
:score-value="item.teamworkWorkload.rating"
|
||||||
v-on:newselection="item.teamworkWorkload.rating = $event;"
|
v-on:newselection="item.teamworkWorkload.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -267,7 +262,7 @@
|
|||||||
<h5>Knowledge</h5>
|
<h5>Knowledge</h5>
|
||||||
<score-selector
|
<score-selector
|
||||||
:score-value="item.knowledge.rating"
|
:score-value="item.knowledge.rating"
|
||||||
v-on:newselection="item.knowledge.rating = $event;"
|
v-on:newselection="item.knowledge.rating = $event; actuallySubmit()"
|
||||||
></score-selector>
|
></score-selector>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -296,20 +291,16 @@
|
|||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<br>
|
<br>
|
||||||
<b-button type="submit" variant="primary" v-on:click="onSubmit()">Submit</b-button>
|
<b-button variant="primary" v-on:click="actuallySubmit()">Update</b-button>
|
||||||
</b-form>
|
</b-form>
|
||||||
</b-container>
|
</b-container>
|
||||||
<b-modal id="submissionModal" ref="submissionModal" title="Confirm Submission" @ok="actuallySubmit()">
|
|
||||||
<form @submit.stop.prevent="handleSubmit">
|
|
||||||
<p>Once submitted, data cannot be changed.</p>
|
|
||||||
<p>Are you sure you wish to submit?</p>
|
|
||||||
</form>
|
|
||||||
</b-modal>
|
|
||||||
</b-container>
|
</b-container>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import ScoreSelector from "../components/ScoreSelector.vue";
|
import ScoreSelector from "../components/ScoreSelector.vue";
|
||||||
|
import webstomp from "webstomp-client";
|
||||||
|
import SockJS from "sockjs-client";
|
||||||
export default {
|
export default {
|
||||||
name: "groupsessioninput",
|
name: "groupsessioninput",
|
||||||
title: "Group Session - Input",
|
title: "Group Session - Input",
|
||||||
@ -321,7 +312,8 @@ export default {
|
|||||||
participant: null,
|
participant: null,
|
||||||
valid: false,
|
valid: false,
|
||||||
complete: false,
|
complete: false,
|
||||||
error: null
|
error: null,
|
||||||
|
stompclient: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -335,6 +327,7 @@ export default {
|
|||||||
self.addAnotherObservation(x);
|
self.addAnotherObservation(x);
|
||||||
});
|
});
|
||||||
self.valid = true;
|
self.valid = true;
|
||||||
|
self.setupSession()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
@ -352,80 +345,79 @@ export default {
|
|||||||
this.scenarios.push({
|
this.scenarios.push({
|
||||||
title: newTitle,
|
title: newTitle,
|
||||||
monitoring: {
|
monitoring: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
controlProcedural: {
|
controlProcedural: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
control: {
|
control: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
conservatism: {
|
conservatism: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
teamworkCommunications: {
|
teamworkCommunications: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
teamworkLeadership: {
|
teamworkLeadership: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
teamworkWorkload: {
|
teamworkWorkload: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
},
|
},
|
||||||
knowledge: {
|
knowledge: {
|
||||||
rating: null,
|
rating: 0,
|
||||||
strengths: "",
|
strengths: "",
|
||||||
improvements: ""
|
improvements: ""
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSubmit: function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
var form = document.getElementById("submission-form");
|
|
||||||
if (form.checkValidity()) {
|
|
||||||
this.showModal();
|
|
||||||
}
|
|
||||||
form.classList.add("was-validated");
|
|
||||||
},
|
|
||||||
showModal() {
|
|
||||||
this.$refs.submissionModal.show();
|
|
||||||
},
|
|
||||||
actuallySubmit() {
|
actuallySubmit() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var payload = {
|
var payload = {
|
||||||
person: self.participant,
|
person: self.participant,
|
||||||
scenarios: self.scenarios
|
scenarios: self.scenarios
|
||||||
}
|
};
|
||||||
var form = document.getElementById("submission-form");
|
|
||||||
if (form.checkValidity()) {
|
|
||||||
console.log(payload)
|
|
||||||
Vue.axios
|
Vue.axios
|
||||||
.post("/grpob/submit", payload)
|
.post("/grpob/submit", payload)
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
self.complete = true;
|
|
||||||
console.log(response);
|
console.log(response);
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
self.error = error;
|
self.error = error;
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
setupSession: function() {
|
||||||
|
var self = this;
|
||||||
|
self.stompclient = webstomp.over(
|
||||||
|
new SockJS(`http://${window.location.host}/websocket`, {
|
||||||
|
heartbeat: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
self.stompclient.connect([], function() {
|
||||||
|
self.stompclient.subscribe("/ws/status", function(incomingData) {
|
||||||
|
var data = JSON.parse(incomingData.body);
|
||||||
|
if (data.status === "complete") {
|
||||||
|
self.complete = true;
|
||||||
|
self.stompclient.disconnect()
|
||||||
}
|
}
|
||||||
form.classList.add("was-validated");
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user