Group sessions can now be properly started

This commit is contained in:
neviyn 2019-02-19 16:05:19 +00:00
parent cd6aba097d
commit 2676307170
5 changed files with 185 additions and 38 deletions

View File

@ -40,7 +40,7 @@ class CustomWebSecurityConfigurerAdapter : WebSecurityConfigurerAdapter() {
@Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/site", "/api/tutor", "/api/observation").authenticated()
.antMatchers(HttpMethod.POST, "/api/site", "/api/tutor", "/api/observation", "/api/grpob/start").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic()

View File

@ -15,6 +15,6 @@ class WebSocketConfig : WebSocketMessageBrokerConfigurer {
}
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/websocket").withSockJS()
registry.addEndpoint("/websocket").setAllowedOrigins("http://localhost:8080", "http://127.0.0.1:8080").withSockJS()
}
}

View File

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import uk.co.neviyn.observationdatabase.GroupObservation
@ -22,6 +23,7 @@ import uk.co.neviyn.observationdatabase.SiteRepository
import uk.co.neviyn.observationdatabase.TutorRepository
import java.net.Inet4Address
import java.net.NetworkInterface
import javax.validation.Valid
@RestController
@RequestMapping("/api/grpob")
@ -45,7 +47,7 @@ class GroupSessionController {
* Start a new Group Observation session
*/
@PostMapping("/start")
fun startGroupObservation(initData: GroupObservationInit): Map<String, String> {
fun startGroupObservation(@Valid @RequestBody initData: GroupObservationInit): Map<String, String> {
val site = siteRepository.findById(initData.site)
val tutors = tutorRepository.findAllById(initData.tutors).toSet()
if (!site.isPresent) {
@ -65,8 +67,12 @@ class GroupSessionController {
*/
@GetMapping("/recover")
fun reconnectToGroupObservation(): Map<String, Any> {
logger.debug("Previous group observation requested")
return getConnectionDetails().plus(mapOf("id" to GroupSessionManager.sessionId.toString(), "observations" to GroupSessionManager.observations))
if (GroupSessionManager.isValid()) {
logger.info("Previous group observation requested, current id ${GroupSessionManager.sessionId}")
return getConnectionDetails().plus(mapOf("id" to GroupSessionManager.sessionId.toString(), "observations" to GroupSessionManager.observations))
}
logger.info("Tried to recover a session but no session is active")
return mapOf("error" to "No session currently active")
}
/**

View File

@ -11,7 +11,7 @@
</b-row>
<b-row v-else>
<b-col>
<b-form id="submission-form" novalidate>
<b-form id="submission-form" novalidate @submit="onSubmit">
<b-row align-h="center">
<b-col>
<b-form-group label="Site">
@ -43,17 +43,65 @@
</b-form-group>
</b-col>
</b-row>
<b-row
v-for="(item, index) in scenarioTitles"
v-bind:key="index"
class="border bottom-buffer"
fluid
>
<b-col>
<b-form-input
v-model="item.data"
type="text"
placeholder="Enter scenario description."
></b-form-input>
</b-col>
<b-col cols="1">
<b-button v-on:click="scenarioTitles.splice(index, 1)" variant="danger">
<b>Delete</b>
</b-button>
</b-col>
</b-row>
<b-row align-h="center">
<b-col>
<b-button
v-on:click="scenarioTitles.push({data:''})"
size="lg"
variant="primary"
>Add Another Scenario</b-button>
</b-col>
</b-row>
<b-row>
<b-col>
<br>
</b-col>
</b-row>
<b-row align-h="center">
<b-col>
<b-button type="submit" size="lg" variant="primary">Start</b-button>
</b-col>
<b-col>
<b-button size="lg" variant="secondary">Connect to Previous Session</b-button>
<b-button
size="lg"
variant="secondary"
v-on:click="connectToPrevious()"
>Connect to Previous Session</b-button>
</b-col>
</b-row>
</b-form>
</b-col>
</b-row>
<b-modal
id="submissionModal"
ref="submissionModal"
title="Enter password to confirm submission"
@ok="handleOk"
@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>
</template>
<script>
@ -75,7 +123,7 @@ export default {
tutors: null,
siteOptions: [],
tutorOptions: [],
scenarioTitles: null,
scenarioTitles: [{ data: "" }, { data: "" }, { data: "" }],
type: null,
submitPassword: null
};
@ -88,15 +136,6 @@ export default {
},
mounted() {
console.log("loading");
var self = this;
this.stompclient.connect(
[],
function() {
self.stompclient.subscribe("/ws/observations", function(incomingData) {
self.data = incomingData.content.observations;
});
}
);
Vue.axios
.get("/site")
.then(response => {
@ -104,39 +143,112 @@ export default {
})
.catch(error => {
if (error.response.status === 404) {
this.$router.push("/dberror");
//this.$router.push("/dberror");
return;
}
});
},
methods: {
startSession: function() {
var self = this;
let axiosConfig = {
auth: {
username: "admin",
password: this.submitPassword
}
};
console.log({
site: self.site,
tutors: self.tutors,
scenarioTitles: self.scenarioTitles.map(x => x.data),
type: self.type
});
Vue.axios
.post(
"/grpob/start",
{
site: this.site,
tutors: this.tutors,
scenarioTitles: this.whom,
type: this.type
site: self.site,
tutors: self.tutors,
scenarioTitles: self.scenarioTitles.map(x => x.data),
type: self.type
},
axiosConfig
)
.then(function(response) {
console.log(response);
this.qrdata =
"http://" + response.ip + ":" + response.port + "/#/" + response.id;
if ('error' in response.data) {
} else {
let rdata = 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: false
})
);
self.stompclient.connect(
[],
function() {
self.stompclient.subscribe("/ws/observations", function(
incomingData
) {
self.data = incomingData.content.observations;
});
}
);
self.$refs.submissionModal.hide();
self.clearPassword();
}
})
.catch(function(error) {
self.active = false;
console.log(error);
});
},
connectToPrevious: function() {
var self = this;
Vue.axios
.get("/grpob/recover")
.then(function(response) {
console.log(response);
if ('error' in response.data) {
} else {
let rdata = 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 = incomingData.content.observations;
});
}
);
self.$refs.submissionModal.hide();
self.clearPassword();
}
})
.catch(function(error) {
if (error.response.status === 404) {
this.$router.push("/dberror");
return;
}
});
},
getTutors: function() {
if (this.site != null) {
Vue.axios
@ -151,6 +263,28 @@ export default {
}
});
}
},
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();
},
clearPassword() {
this.submitPassword = null;
},
handleOk(evt) {
// Prevent modal from closing
evt.preventDefault();
if (this.submitPassword !== null) {
this.startSession();
}
}
},
beforeDestroy() {

View File

@ -1,6 +1,12 @@
<template>
<b-container fluid>
<b-container
<b-container v-if="!valid">
<p>Getting session data from server</p>
</b-container>
<b-container v-else-if="scenarios.length === 0">
<p>No scenarios defined for this session, please setup a new group session</p>
</b-container>
<b-container v-else
v-for="(item, index) in scenarios"
v-bind:key="index"
class="border bottom-buffer"
@ -288,28 +294,31 @@ export default {
scenarios: [],
totals: [0, 0, 0, 0, 0, 0, 0, 0],
warningBound: 2.5,
submitPassword: null
submitPassword: null,
valid: false
};
},
mounted() {
/*
let self = this;
if (this.id != null) {
Vue.axios
.get("/grpob/valid/" + this.id)
.then(response => {
response.titles.forEach(function(x) {
this.addAnotherObservation(x);
});
.get(`/grpob/valid/${this.id}`)
.then(function (response) {
if(response.data.titles != null) {
response.data.titles.forEach(function(x) {
self.addAnotherObservation(x);
})
self.valid = true
};
})
.catch(error => {
.catch(function(error) {
if (error.response.status === 404) {
this.$router.push("/dberror");
self.$router.push("/dberror");
return;
}
console.log(error)
});
}
*/
this.addAnotherObservation("Sample Entry");
},
methods: {
addAnotherObservation: function(newTitle) {
@ -436,5 +445,3 @@ export default {
}
};
</script>
};
</script>