Commit 670c48fb authored by jackie / Andrea Ida Malkah Klaura's avatar jackie / Andrea Ida Malkah Klaura
Browse files

FEAT: add conflict resolve modal

parent e2d23fb2
......@@ -34,16 +34,32 @@
variant="danger"
:show="conflictMode"
>
<b-row>
<b-col cols="12">
<div align="center">
<h4>Conflict Resolution</h4>
</div>
</b-col>
<b-col>
... coming soon ...
</b-col>
</b-row>
<div
v-if="conflictMode"
align="center"
>
<h4>Conflict Resolution</h4>
<p>for new schedule</p>
<p>
from <b>{{ resolveData.schedule.dstart }}, {{ resolveData.schedule.tstart }}</b>
to <b>{{ resolveData.schedule.tend }}</b>.
</p>
<p v-if="resolveData.schedule.rrule !== 1">
This is a recurring event: <b>{{ rruleRender(resolveData.schedule.rrule) }}</b>,
until: <b>{{ resolveData.schedule.until }}</b>.
</p>
<p v-if="conflictCount > 0">
Conflicts to resolve: {{ conflictCount }}
</p>
<p v-else>
<b-button
variant="success"
@click="resolveSubmit"
>
0 conflicts left! Submit this solution.
</b-button>
</p>
</div>
</b-alert>
<full-calendar
......@@ -62,6 +78,9 @@
<app-modalEmissionManagerCreate
ref="appModalEmissionManagerCreate"
/>
<app-modalEmissionManagerResolve
ref="appModalEmissionManagerResolve"
/>
</b-container>
</template>
......@@ -70,13 +89,18 @@ import axios from 'axios'
import { FullCalendar } from 'vue-full-calendar'
import 'fullcalendar/dist/fullcalendar.css'
import modalEmissionManagerCreate from './EmissionManagerModalCreate.vue'
import modalEmissionManagerResolve from './EmissionManagerModalResolve.vue'
import rrules from '../mixins/rrules'
export default {
components: {
FullCalendar,
'app-modalEmissionManagerCreate': modalEmissionManagerCreate,
'app-modalEmissionManagerResolve': modalEmissionManagerResolve,
},
mixins: [ rrules ],
data () {
return {
currentShow: 0,
......@@ -93,6 +117,11 @@ export default {
// this flag signifies if we are in conflict resolution mode
conflictMode: false,
// when conflict mode is activated, this should hold the steering response
// from schedule creation, with all the conflicts and solutions
resolveData: null,
conflictCount: 0,
conflictSolutions: [],
// this is the whole configuration for our schedule calendar, including
// simple event handlers that do not need the whole components scope
......@@ -145,8 +174,16 @@ export default {
}
},
eventSelected (event, jsEvent, view) {
this.$log.debug('eventSelected', event, jsEvent, view)
eventSelected (event) {
if (this.conflictMode) {
if (event.hash === undefined) {
return
} else if (this.conflictSolutions[event.hash] === undefined) {
this.$refs.appModalEmissionManagerResolve.openNotNeeded()
} else {
this.$refs.appModalEmissionManagerResolve.open(event)
}
}
},
eventDrop (event) {
......@@ -176,11 +213,8 @@ export default {
start = view.start.format()
end = view.end.format()
}
// if we are in conflict resolution mode we do not load all timeslots
// but only the conflicting ones
if (this.conflictMode) {
this.loadConflictSlots(start, end)
} else {
// we only load new timeslots, if we are not in conflict mode
if (!this.conflictMode) {
this.loadTimeslots(start, end)
}
}
......@@ -188,7 +222,51 @@ export default {
resolve (data) {
this.$log.debug('resolve', data)
this.resolveData = data
this.conflictMode = true
this.conflictCount = 0
this.conflictSolutions = data.solutions
this.calendarSlots = []
try {
for (let i in data.projected) {
let newSlot = {
// we need a numeric ID for the event for later selection by the user.
// with converting the hash to a number (in this case a float), we
// do not risk using a number that is already used by a timeslot id
// of a conflicting timeslot
id: Number(data.projected[i].hash),
// the hash is needed to compare against solutions and conflicts
hash: data.projected[i].hash,
start: data.projected[i].start,
end: data.projected[i].end,
title: 'new',
collisions: [],
solutionChoices: [],
className: 'noconflict',
editable: false,
}
if (data.projected[i].collisions.length > 0) {
newSlot.className = 'conflict'
newSlot.solutionChoices = data.projected[i].solution_choices
for (let col of data.projected[i].collisions) {
let conflictingSlot = {
id: col.id,
start: col.start,
end: col.end,
title: col.show_name,
className: 'otherShow',
editable: false,
}
this.calendarSlots.push(conflictingSlot)
this.conflictCount++
newSlot.collisions.push(col)
}
}
this.calendarSlots.push(newSlot)
}
} catch (err) {
this.$log.error(err)
}
},
loadCalendarSlots () {
......@@ -260,4 +338,10 @@ export default {
a.currentShow {
background-color: #17a2b8;
}
.conflict {
background-color: #b00;
}
.noconflict {
background-color: #17a2b8;
}
</style>
......@@ -81,9 +81,10 @@
<script>
import axios from 'axios'
import prettyDate from '../mixins/prettyDate'
import rrules from '../mixins/rrules'
export default {
mixins: [ prettyDate ],
mixins: [ prettyDate, rrules ],
data () {
return {
......@@ -97,21 +98,6 @@ export default {
until: null,
rrule: 1
},
rruleOptions: [
{ value: 1, text: 'einmalig' },
{ value: 2, text: 'täglich' },
{ value: 3, text: 'werktäglich' },
{ value: 4, text: 'wöchentlich' },
{ value: 5, text: 'zweiwöchentlich' },
{ value: 6, text: 'vierwöchentlich' },
{ value: 7, text: 'gerade Kalenderwoche' },
{ value: 8, text: 'ungerade Kalenderwoche' },
{ value: 9, text: 'Jede 1. Woche im Monat' },
{ value: 10, text: 'Jede 2. Woche im Monat' },
{ value: 11, text: 'Jede 3. Woche im Monat' },
{ value: 12, text: 'Jede 4. Woche im Monat' },
{ value: 13, text: 'Jede 5. Woche im Monat' },
],
}
},
......
<template>
<div>
<b-modal
ref="modalEmissionManagerResolve"
title="Resolve a timeslot conflict"
size="lg"
@ok="resolve"
>
<p>
Resolving a conflict for a new schedule of the show:
<b v-if="$parent.loaded.shows">
<b>{{ $parent.shows[$parent.currentShow].name }}</b>
</b>
</p>
<p v-if="loaded">
The new projected slot starts at
<b-badge variant="danger">
{{ toResolve.start.format('YYYY-DD-MM HH:mm') }}
</b-badge>
and ends at
<b-badge variant="danger">
{{ toResolve.end.format('YYYY-DD-MM HH:mm') }}
</b-badge>
.
</p>
<p>
It conflicts with the following timeslots:
</p>
<ul v-if="loaded">
<li
v-for="col in toResolve.collisions"
:key="col.id"
>
<i>{{ col.show_name }}</i> from
<b-badge variant="success">
{{ col.start.slice(0,16) }}
</b-badge>
to
<b-badge variant="success">
{{ col.end.slice(0,16) }}
</b-badge>
</li>
</ul>
<p>
What should we do?
</p>
<div align="center">
<b-button-group v-if="loaded">
<b-button
v-if="toResolve.solutionChoices.indexOf('ours') >= 0"
variant="danger"
size="sm"
>
Create new,<br>
delete existing.
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('theirs') >= 0"
variant="success"
size="sm"
>
Discard new,<br>
keep existing.
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('theirs-start') >= 0"
variant="info"
size="sm"
>
theirs-start<br>
TODO: describe
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('theirs-end') >= 0"
variant="info"
size="sm"
>
theirs-end<br>
TODO: describe
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('theirs-both') >= 0"
variant="info"
size="sm"
>
theirs-both<br>
TODO: describe
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('ours-start') >= 0"
variant="info"
size="sm"
>
ours-start<br>
TODO: describe
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('ours-end') >= 0"
variant="info"
size="sm"
>
ours-end<br>
TODO: describe
</b-button>
<b-button
v-if="toResolve.solutionChoices.indexOf('ours-both') >= 0"
variant="info"
size="sm"
>
ours-both<br>
TODO: describe
</b-button>
</b-button-group>
</div>
</b-modal>
<b-modal
ref="modalEmissionManagerResolveNotNeeded"
title="No conflict"
size="sm"
>
<div align="center">
<p>This timeslot has no conflict.</p>
<p>All fine.</p>
</div>
</b-modal>
</div>
</template>
<script>
export default {
data () {
return {
loaded: false,
toResolve: null,
}
},
methods: {
resolve () {
},
// initialise properties and open the modal
open (event) {
this.$log.debug(event)
this.toResolve = event
this.loaded = true
this.$refs.modalEmissionManagerResolve.show()
},
// opens the modal signaling that there is no conflict to resolve
openNotNeeded () {
this.$refs.modalEmissionManagerResolveNotNeeded.show()
},
}
}
</script>
<style scoped>
.row {
margin-bottom: 1em;
}
</style>
export default {
computed: {
rruleOptions () {
return [
{ value: 1, text: 'einmalig' },
{ value: 2, text: 'täglich' },
{ value: 3, text: 'werktäglich' },
{ value: 4, text: 'wöchentlich' },
{ value: 5, text: 'zweiwöchentlich' },
{ value: 6, text: 'vierwöchentlich' },
{ value: 7, text: 'gerade Kalenderwoche' },
{ value: 8, text: 'ungerade Kalenderwoche' },
{ value: 9, text: 'Jede 1. Woche im Monat' },
{ value: 10, text: 'Jede 2. Woche im Monat' },
{ value: 11, text: 'Jede 3. Woche im Monat' },
{ value: 12, text: 'Jede 4. Woche im Monat' },
{ value: 13, text: 'Jede 5. Woche im Monat' },
]
},
},
methods: {
rruleRender (rrule) {
let rule = this.rruleOptions.find(r => r.value === rrule)
return rule.text
}
}
}
Supports Markdown
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