EmissionManager.vue 7 KB
Newer Older
1
<template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  <b-container>
    <b-row v-if="loaded.shows">
      <b-col>
        <h3>{{ shows[currentShow].name }}</h3>
      </b-col>
      <b-col align="right">
        <b-dropdown
          id="ddshows"
          text="Sendereihe auswählen"
          variant="outline-info"
        >
          <b-dropdown-item
            v-for="(show, index) in shows"
            :key="show.id"
            @click="switchShow(index)"
          >
            {{ show.name }}
          </b-dropdown-item>
        </b-dropdown>
      </b-col>
    </b-row>
    <b-row v-else>
      <b-col cols="12">
        <div align="center">
          ... loading show data ...
        </div>
      </b-col>
    </b-row>
30

31
32
    <hr>

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    <b-alert
      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>
    </b-alert>

49
50
51
52
53
54
55
    <full-calendar
      ref="calendar"
      editable="false"
      default-view="agendaWeek"
      :events="calendarSlots"
      :config="calendarConfig"
      @view-render="renderView"
56
57
58
59
60
61
62
63
      @event-selected="eventSelected"
      @event-drop="eventDrop"
      @event-resize="eventResize"
      @event-created="eventCreated"
    />

    <app-modalEmissionManagerCreate
      ref="appModalEmissionManagerCreate"
64
65
    />
  </b-container>
66
67
68
69
</template>

<script>
import axios from 'axios'
70
import { FullCalendar } from 'vue-full-calendar'
71
import 'fullcalendar/dist/fullcalendar.css'
72
import modalEmissionManagerCreate from './EmissionManagerModalCreate.vue'
73
74
75
76

export default {
  components: {
    FullCalendar,
77
    'app-modalEmissionManagerCreate': modalEmissionManagerCreate,
78
  },
79

80
81
  data () {
    return {
82
      currentShow: 0,
83
84
85
      shows: [],
      timeslots: [],
      calendarSlots: [],
86

87
88
89
90
91
92
93
94
95
96
      // flags for loading data
      loaded: {
        shows: false,
        timeslots: false,
        calendarSlots: false,
      },

      // this flag signifies if we are in conflict resolution mode
      conflictMode: false,

97
      // this is the whole configuration for our schedule calendar, including
98
      // simple event handlers that do not need the whole components scope
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
      calendarConfig: {
        height: 600,
        firstDay: 1,
        header: {
          left: 'title',
          center: '',
          right: 'today prev,next'
        },
        views: {
          agendaWeek: {
            columnHeaderFormat: 'ddd D.M.',
            timeFormat: 'k:mm',
            slotLabelFormat: 'k:mm',
            allDaySlot: false,
          },
        },
115
116
117
118
119
        // here we add a simple tooltip to every event, so that the full title
        // of a show can be viewed
        eventRender: function(event, element) {
          element.attr('title', event.title);
        },
120
121
122
123
      },
    }
  },

124
125
126
127
128
129
130
  created () {
    if (this.$route.query.show) {
      this.currentShow = this.$route.query.show
    } else {
      this.currentShow = 0
    }
    this.loadShows()
131
132
133
  },

  methods: {
134
135
136
    switchShow (index) {
      this.currentShow = index
      this.loadCalendarSlots()
137
138
139
140
141
142
143
144
145
146
147
    },

    getShowTitleById (id) {
      let i = this.shows.findIndex(show => show.id === id)
      if (i >= 0) {
        return this.shows[i].name
      } else {
        return 'Error: no show found for this timeslot'
      }
    },

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    eventSelected (event, jsEvent, view) {
      this.$log.debug('eventSelected', event, jsEvent, view)
    },

    eventDrop (event) {
      this.$log.debug('eventDrop', event)
    },

    eventResize (event) {
      this.$log.debug('eventResize', event)
    },

    eventCreated (event) {
      this.$refs.appModalEmissionManagerCreate.open(event.start, event.end)
    },

164
165
166
167
    // this is called when the user changes the calendar view, so we just
    // refetch the timeslots with the updated visible date range
    renderView (view) {
      if (this.loaded.shows) {
168
169
170
171
172
173
174
175
176
177
178
        let start = null
        let end = null
        // in case it gets called from a modal, we use the current view
        // otherwise we use the new dates from the view received by the renderView event
        if (view === null) {
          start = this.$refs.calendar.fireMethod('getView').start.format()
          end = this.$refs.calendar.fireMethod('getView').end.format()
        } else {
          start = view.start.format()
          end = view.end.format()
        }
179
180
181
182
183
184
185
        // 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 {
          this.loadTimeslots(start, end)
        }
186
187
188
      }
    },

189
190
191
192
193
    resolve (data) {
      this.$log.debug('resolve', data)
      this.conflictMode = true
    },

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    loadCalendarSlots () {
      this.loaded.calendarSlots = false
      this.calendarSlots = []
      for (let i in this.timeslots) {
        let highlighting = 'otherShow'
        if (this.timeslots[i].show === this.shows[this.currentShow].id) {
          highlighting = 'currentShow'
        }
        this.calendarSlots.push({
          start: this.timeslots[i].start,
          end: this.timeslots[i].end,
          title: this.getShowTitleById(this.timeslots[i].show),
          className: highlighting
        })
      }
      this.loaded.calendarSlots = true
    },

212
    loadTimeslots (start, end) {
213
      this.$log.debug('loadTimeslots: currentShow = '+this.currentShow)
214
215
216
217
      this.loaded.timeslots = false
      let uri = process.env.VUE_APP_API_STEERING + 'timeslots?start=' + start + '&end=' + end
      axios.get(uri, {
        withCredentials: true,
218
        headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
219
      }).then(response => {
220
        this.timeslots = response.data
221
        this.loaded.timeslots = true
222
        this.loadCalendarSlots()
223
224
225
226
227
228
229
230
231
232
233
234
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not load timeslots. See console for details.')
      })
    },

    loadShows () {
      this.loaded.shows = false
      let uri = process.env.VUE_APP_API_STEERING + 'shows'
      axios.get(uri, {
        withCredentials: true,
235
        headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
      }).then(response => {
        this.shows = response.data
        this.loaded.shows = true
        let start = this.$refs.calendar.fireMethod('getView').start.format()
        let end = this.$refs.calendar.fireMethod('getView').end.format()
        this.loadTimeslots(start, end)
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not load shows. See console for details.')
      })
    },

    updateSchedules () {
      this.$log.debug(this.$refs.calendar.fireMethod('getView').start.format())
    }
  },
}
</script>

<style>
.otherShow {
  background-color: #eee;
}
a.currentShow {
  background-color: #17a2b8;
}
</style>