Commit e2abee3f authored by Sascha Herzinger's avatar Sascha Herzinger
Browse files

implemented task manager

parent 3d9396d2
......@@ -60,6 +60,7 @@
watch: {
'selectedIDs': {
handler: function (newSelectedIDs, oldSelectedIDs) {
// avoid emitting signals and thus triggering watchers if selected ids didn't change
if (JSON.stringify(newSelectedIDs) !== JSON.stringify(oldSelectedIDs)) {
this.$emit('update', newSelectedIDs)
}
......
<template>
<div class="fjs-loader"></div>
</template>
<script>
export default {
name: 'loader'
}
</script>
<style lang="sass" scoped>
$size: 20px !default
$thickness: 3px !default
$base-color: #fff !default
$wheel-color: #c30 !default
$speed: 800ms !default
.fjs-loader
margin: 5% auto
height: $size
width: $size
border: $thickness solid $base-color
border:
right-color: $wheel-color
top-color: $wheel-color
radius: 100%
animation: spin $speed infinite linear
@keyframes spin
from
transform: rotate(0deg)
to
transform: rotate(359deg)
</style>
<template>
<div class="fjs-task-state-container" v-if="pendingTasks.length || failedTasks.length">
<div class="fjs-task-state-element" v-for="task in pendingTasks">
<loader class="fjs-loader"></loader>
<span class="fjs-task-info">{{ task.taskName }}</span>
<span class="fjs-cancel-task-btn" @click="cancelTask(task.taskID)">&#215;</span>
</div>
<div class="fjs-task-state-element" v-for="task in failedTasks">
<span>{{ task.taskName }}</span>
</div>
</div>
</template>
<script>
import store from '../store/store'
import Loader from './Loader.vue'
export default {
name: 'task-view',
components: {
Loader
},
data () {
return {
}
},
computed: {
tasks () {
return store.getters.tasks
},
pendingTasks () {
return Object.keys(this.tasks)
.filter(taskID => this.tasks[taskID].taskState === 'PENDING')
.map(taskID => this.tasks[taskID])
},
failedTasks () {
return Object.keys(this.tasks)
.filter(taskID => this.tasks[taskID].taskState === 'FAILURE')
.map(taskID => this.tasks[taskID])
}
},
methods: {
cancelTask (taskID) {
store.getters.requestManager.cancelAnalysis({taskID})
}
}
}
</script>
<style lang="sass" scoped>
.fjs-task-state-container
display: flex
flex-direction: column
z-index: 1
position: fixed
bottom: 0
right: 0
color: #fff
background-color: #000
opacity: 0.8
padding: 20px
border-radius: 15px 0 0 0
.fjs-task-state-element
display: flex
align-items: center
.fjs-task-info
margin: 0 0 0 5px
.fjs-cancel-task-btn
cursor: pointer
margin: 0 0 0 20px
color: #f00
font-size: 30px
font-weight: bold
</style>
<template>
<div :class="`fjs-vm-root fjs-vm-root-${this._uid}`">
<div class="fjs-data-box-container">
<data-box class="fjs-data-box"
header="X and Y variables"
......@@ -124,7 +123,7 @@
</table>
</div>
</div>
<task-view></task-view>
</div>
</template>
......@@ -133,11 +132,11 @@
import DataBox from '../DataBox.vue'
import Icon from '../Icon.vue'
import store from '../../store/store'
import types from '../../store/mutation-types'
import requestHandling from '../methods/request-handling'
import * as d3 from 'd3'
import svgtooltip from '../directives/v-svgtooltip'
import { TweenLite } from 'gsap'
import TaskView from '../TaskView.vue'
export default {
name: 'correlation-analysis',
data () {
......@@ -357,7 +356,7 @@
return
}
}
store.commit(types.SET_FILTER, {filter: 'ids', value: this.selectedPoints.map(d => d.id)})
store.dispatch('setFilter', {filter: 'ids', value: this.selectedPoints.map(d => d.id)})
})
},
histograms () {
......@@ -414,6 +413,7 @@
watch: {
'args': {
handler: function (newArgs, oldArgs) {
// if our data selection change we will want to re-initialize the current view
const init = newArgs.x !== oldArgs.x ||
newArgs.y !== oldArgs.y ||
JSON.stringify(newArgs.annotations) !== JSON.stringify(oldArgs.annotations)
......@@ -489,7 +489,8 @@
},
components: {
DataBox,
Icon
Icon,
TaskView
},
mixins: [
requestHandling,
......
......@@ -8,11 +8,13 @@ export default {
}
const rv1 = await store.getters.requestManager.createAnalysis({task_name, args})
const taskID = rv1.data.task_id
store.dispatch('setTask', {taskID, taskName: task_name, taskState: 'PENDING'})
let counter = 0
while (counter < 1000) {
await timeout(++counter * 200)
const rv2 = await store.getters.requestManager.getAnalysisStatus({taskID})
const taskInfo = rv2.data
store.dispatch('setTask', {taskID, taskName: task_name, taskState: taskInfo.state})
if (taskInfo.state === 'SUCCESS') {
return taskInfo.result
} else if (taskInfo.state === 'FAILURE') {
......
......@@ -51,6 +51,7 @@ export default class {
}
cancelAnalysis ({taskID}) {
store.dispatch('unsetTask', {taskID})
return this._axios.delete(`/analytics/${taskID}`)
}
}
......@@ -9,7 +9,8 @@ export default {
},
updateData: context => {
context.getters.requestManager.getAllDataStates().then(response => {
context.commit(types.SET_DATA, response.data.data_states)
const data = response.data.data_states
context.commit(types.SET_DATA, data)
}).catch(error => {
console.error(error) // TODO: Notify user about this
}).then(() => { // finally
......@@ -20,5 +21,11 @@ export default {
},
setFilter: (context, {filter, value}) => {
context.commit(types.SET_FILTER, {filter, value})
},
setTask: (context, {taskID, taskName, taskState}) => {
context.commit(types.SET_TASK, {taskID, taskName, taskState})
},
unsetTask: (context, {taskID}) => {
context.commit(types.UNSET_TASK, {taskID})
}
}
export default {
data: state => state.data,
tasks: state => state.tasks,
subsets: state => state.subsets,
requestManager: state => state.requestManager,
filter: state => name => state.filters[name]
......
......@@ -2,5 +2,7 @@ export default {
SET_DATA: 'SET_DATA',
SET_REQUEST_MANAGER: 'SET_REQUEST_MANAGER',
SET_SUBSETS: 'SET_SUBSETS',
SET_FILTER: 'SET_FILTER'
SET_FILTER: 'SET_FILTER',
SET_TASK: 'SET_TASK',
UNSET_TASK: 'UNSET_TASK'
}
......@@ -2,7 +2,10 @@ import types from './mutation-types'
export default {
[types.SET_DATA] (state, data) {
state.data = data
// avoid triggering possible watchers if data didn't change
if (JSON.stringify(state.data) !== JSON.stringify(data)) {
state.data = data
}
},
[types.SET_REQUEST_MANAGER] (state, manager) {
state.requestManager = manager
......@@ -12,5 +15,17 @@ export default {
},
[types.SET_FILTER] (state, {filter, value}) {
state.filters[filter] = value
},
[types.SET_TASK] (state, {taskID, taskName, taskState}) {
// assure to trigger possible external watchers by replacing the entire tasks object
const tasks = JSON.parse(JSON.stringify(state.tasks))
tasks[taskID] = {taskID, taskName, taskState}
state.tasks = tasks
},
[types.UNSET_TASK] (state, {taskID}) {
// assure to trigger possible external watchers by replacing the entire tasks object
const tasks = JSON.parse(JSON.stringify(state.tasks))
delete tasks[taskID]
state.tasks = tasks
}
}
......@@ -8,6 +8,7 @@ Vue.use(Vuex)
const state = {
data: [],
tasks: {},
requestManager: null,
subsets: [],
filters: {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment