ShowManager.vue 24.4 KB
Newer Older
1
<template>
2
  <b-container>
3
4
5
6
7
8
9
10
11
12
13
    <b-row>
      <b-col align="right">
        <b-dropdown id="ddshows" text="Sendereihe auswählen" variant="info">
          <b-dropdown-item v-for="(show, index) in this.shows" :key="show.id" v-on:click="switchShow(index)">{{ show.name }}</b-dropdown-item>
        </b-dropdown>
      </b-col>
    </b-row>
    <hr />

    <b-jumbotron>
      <template slot="header">
14
15
        <span v-if="loaded.shows">
          {{ shows[currentShow].name }}
16
          <img src="../assets/16x16/emblem-system.png" alt="edit name of show" v-on:click="$refs.appModalShow.showName()" />
17
        </span>
18
19
20
        <span v-else>Shows are being loaded</span>
      </template>
      <template slot="lead">
21
        <span v-if="loaded.shows">{{ shows[currentShow].short_description }}</span>
22
        <img src="../assets/16x16/emblem-system.png" alt="edit short description" v-on:click="$refs.appModalShow.showShortDescription()" />
23
      </template>
24
      <p v-if="loaded.shows">
25
        <b>Description:</b> <img src="../assets/16x16/emblem-system.png" alt="edit description" v-on:click="$refs.appModalShow.showDescription()" />
26
        <div v-if="loaded.shows">
27
28
29
30
31
          <!-- TODO: see if we can make a nice but secure html rendering of the description
            This should be already secure, as long as you do not write directly to the DOM.
            Only if you do this and render HTML, take care to have it save (no script tags etc.).
            This current regex replace is only to have it looking nicely, in case there are html tags. -->
          {{ shows[currentShow].description.replace(/<[^>]*>/g, '') }}
32
33
34
35
36
          <!-- TODO: add image and logo here? -->
        </div>
      </p>
    </b-jumbotron>

37
    <div v-if="!loaded.shows">
38
39
40
      <b-row>
        <b-col align="center">
          <img src="../assets/radio.gif" alt="loading data" />
41
42
        </b-col>
      </b-row>
43
44
    </div>
    <div v-else>
45
      <!-- include the modals to edit show and timeslot entries from the modal compontents -->
46
47
      <app-modalShow ref="appModalShow" :show="shows[currentShow]"></app-modalShow>
      <app-modalNotes ref="appModalNotes" :show="shows[currentShow]" :showAggregate="current"></app-modalNotes>
48

49
      <!-- here we show our table of timeslots -->
50
      <p>
51
        The next <b>{{ numSlots }}</b> timeslots between <b>{{ prettyDate(dateSlotsStart) }}</b> and <b>{{ prettyDate(dateSlotsEnd) }}</b>:
52
53
54
55
56
57
      </p>
      <div v-if="loaded.timeslots">
        <b-table striped hover outlined :items="notesTableArray"></b-table>
      </div>
      <div v-else style="text-align: center;"><img src="../assets/radio.gif" alt="loading data" /><br /></div>

58
59
      <hr />

60
61
      <h2>Allgemeine Einstellungen zur Sendereihe:</h2>
      <b-row>
62

63
64
65
66
67
68
69
70
        <b-col lg="6">
          <p>
            <b-badge variant="light">E-Mail:</b-badge>
            <span v-if="shows[currentShow].email === null"><small><i>(none set)</i></small></span>
            <span v-else>{{ shows[currentShow].email }}</span>
            <img src="../assets/16x16/emblem-system.png" alt="edit contact e-mail" v-on:click="$refs.appModalShow.showEmail()" />
          </p>
        </b-col>
71

72
73
74
75
76
77
78
79
        <b-col lg="6">
          <p>
            <b-badge variant="light">Website:</b-badge>
            <span v-if="shows[currentShow].website === null"><small><i>(none set)</i></small></span>
            <span v-else><a :href="shows[currentShow].website">{{ shows[currentShow].website }}</a></span>
            <img src="../assets/16x16/emblem-system.png" alt="edit website" v-on:click="$refs.appModalShow.showWebsite()" />
          </p>
        </b-col>
80

81
82
83
84
85
86
87
        <b-col lg="6">
          <p>
            <b-badge variant="light">Show type:</b-badge>
            <!-- TODO: discuss: should this be visible to show owners or only to administrators? -->
            <span v-if="loaded.type">
              <span v-if="current.type.length === 0"><small><i>(none set)</i></small></span>
              <span v-else>{{ current.type[0].type }}</span>
88
              <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showType()" />
89
90
91
92
            </span>
            <span v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /></span>
          </p>
        </b-col>
93

94
95
96
97
        <b-col lg="6">
          <p>
            <b-badge variant="light">Funding category (eg. for RTR):</b-badge>
            <!-- TODO: discuss: should this be visible to show owners or only to administrators? -->
98
99
100
            <span v-if="loaded.fundingcategory">
              <span v-if="current.fundingcategory.length === 0"><small><i>(none set)</i></small></span>
              <span v-else>{{ current.fundingcategory[0].fundingcategory }}</span>
101
              <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showFundingCategory()" />
102
103
104
105
            </span>
            <span v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /></span>
          </p>
        </b-col>
106

107
108
109
110
111
112
        <b-col lg="6">
          <p>
            <!-- TODO: discuss: should this be visible to show owners or only to administrators? -->
            <!-- TODO: fetch name for predecessor_id from steering api -->
            <b-badge variant="light">Predecessor:</b-badge>
            <span v-if="shows[currentShow].predecessor_id === null"><small><i>This show has no predecessor show.</i></small></span>
113
114
            <span v-else>{{ predecessorName }}</span>
            <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showPredecessor()" />
115
116
          </p>
        </b-col>
117

118
119
120
121
122
123
124
125
        <b-col lg="6">
          <p>
            <b-badge variant="light">CBA Series ID:</b-badge>
            <span v-if="shows[currentShow].cba_series_id === null"><small><i>(none set)</i></small></span>
            <span v-else>{{ shows[currentShow].cba_series_id }}</span>
            <img src="../assets/16x16/emblem-system.png" alt="edit CBA series ID" v-on:click="$refs.appModalShow.showCBAid()" />
          </p>
        </b-col>
126

127
128
129
130
131
132
133
134
        <b-col lg="6">
          <p>
            <b-badge variant="light">Fallback List/Pool:</b-badge>
            <span v-if="shows[currentShow].fallback_id === ''"><small><i>(none set)</i></small></span>
            <span v-else>ID: {{ shows[currentShow].fallback_id }}</span>
            <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="notYetImplemented" />
          </p>
        </b-col>
135

136
      </b-row>
137

138
      <b-row>
139

140
        <b-col lg="2">
141
          <b-badge style="width:80%;">Categories:</b-badge> <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showCategories()" />
142
143
144
145
146
147
148
149
150
151
152
153
154
155
        </b-col>
        <b-col lg="4">
          <div v-if="loaded.categories">
            <p v-if="shows[currentShow].category.length === 0">
              <small><i>(none set)</i></small>
            </p>
            <p v-else>
              <ul>
                <li v-for="cat in current.categories">{{ cat.category }}</li>
              </ul>
            </p>
          </div>
          <div v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /><br /></div>
        </b-col>
156

157
        <b-col lg="2">
158
          <b-badge style="width:80%;">Topics:</b-badge> <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showTopics()" />
159
160
161
162
163
164
165
166
167
168
169
170
171
172
        </b-col>
        <b-col lg="4">
          <div v-if="loaded.topics">
            <p v-if="shows[currentShow].topic.length === 0">
              <small><i>(none set)</i></small>
            </p>
            <p v-else>
              <ul>
                <li v-for="topic in current.topics">{{ topic.topic }}</li>
              </ul>
            </p>
          </div>
          <div v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /><br /></div>
        </b-col>
173

174
        <b-col lg="2">
175
          <b-badge style="width:80%;">Musicfocus:</b-badge> <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showMusicFocus()" />
176
177
178
179
180
181
182
183
184
185
186
187
188
189
        </b-col>
        <b-col lg="4">
          <div v-if="loaded.musicfocus">
            <p v-if="shows[currentShow].musicfocus.length === 0">
              <small><i>(none set)</i></small>
            </p>
            <p v-else>
              <ul>
                <li v-for="focus in current.musicfocus">{{ focus.focus }}</li>
              </ul>
            </p>
          </div>
          <div v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /><br /></div>
        </b-col>
190

191
        <b-col lg="2">
192
          <b-badge style="width:80%;">Languages:</b-badge> <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showLanguages()" />
193
194
195
196
197
198
199
200
201
202
203
204
205
206
        </b-col>
        <b-col lg="4">
          <div v-if="loaded.languages">
            <p v-if="shows[currentShow].language.length === 0">
              <small><i>(none set)</i></small>
            </p>
            <p v-else>
              <ul>
                <li v-for="lang in current.languages">{{ lang.name }}</li>
              </ul>
            </p>
          </div>
          <div v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /><br /></div>
        </b-col>
207

208
        <b-col lg="2">
209
          <b-badge style="width:80%;">Hosts:</b-badge> <img src="../assets/16x16/emblem-system.png" alt="edit" v-on:click="$refs.appModalShow.showHosts()" />
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
        </b-col>
        <b-col lg="4">
          <div v-if="loaded.hosts">
            <p v-if="shows[currentShow].hosts.length === 0">
              <small><i>(none set)</i></small>
            </p>
            <p v-else>
              <!-- TODO: make link on name; when user clicks, open modal to edit host -->
              <ul>
                <li v-for="host in current.hosts">{{ host.name }}</li>
              </ul>
            </p>
          </div>
          <div v-else><img src="../assets/radio.gif" height="24px" alt="loading data" /><br /></div>
        </b-col>

      </b-row>
227
    </div>
228
  </b-container>
229
230
231
</template>

<script>
232
import modalNotes from './ShowManagerModalNotes.vue'
233
import modalShow from './ShowManagerModalShow.vue'
234
import timeslotSort from '../mixins/timeslotSort'
235
import prettyDate from '../mixins/prettyDate'
236
import axios from 'axios'
237
238

export default {
239
  components: {
240
241
    'app-modalNotes': modalNotes,
    'app-modalShow': modalShow
242
  },
243
244
  data () {
    return {
245
246
247
      shows: [],      // an array of objects describing our shows (empty at load, will be populated on created())
      currentShow: 0,   // index of the currently selected show in our shows array
      currentShowID: 0, // actual id of the currently selected show
248
      numUpcoming: 8,
249
      numRecent: 8,
250
251
      numSlots: 10,
      dateSlotsStart: new Date(),
252
      dateSlotsEnd: new Date(new Date().getTime() + 90 * 86400000),
253
254
255
256
257
258
259
260
261
      loaded: {
        shows: false,
        timeslots: false,
        notes: false,
        categories: false,
        hosts: false,
        languages: false,
        topics: false,
        musicfocus: false,
262
        fundingcategory: false,
263
        type: false
264
265
266
267
268
269
270
      },
      current: {
        categories: [],
        hosts: [],
        languages: [],
        topics: [],
        musicfocus: [],
271
        fundingcategory: [],
272
        type: [],
273
274
275
276
277
278
279
280
        timeslots: [],
        timeslotmeta: {    // meta info when pagination is used
          count: 0,
          next: null,
          previous: null
        },
        note: {},
        notes: []
281
      }
282
283
    }
  },
284
  mixins: [ timeslotSort, prettyDate ],
285
  computed: {
286
287
288
289
290
291
292
293
    predecessorName: function () {
      for (var i in this.shows) {
        if (this.shows[i].id === this.shows[this.currentShow].predecessor_id) {
          return this.shows[i].name
        }
      }
      return 'Name of predecessor show not available'
    },
294
295
    notesTableArray: function () {
      var arr = []
296
297
298
      for (var i in this.current.timeslots) {
        var note = this.getNoteByTimeslotID(this.current.timeslots[i].id)
        if (note !== null) note = note.title
299
        arr.push({
300
301
302
          title: note,
          starts: this.prettyDateTime(this.current.timeslots[i].start),
          duration: this.prettyDuration(this.current.timeslots[i].start, this.current.timeslots[i].end) + 'min',
303
          // TODO: find out how to insert images or iconffont icons into b-table rows
304
          // options: '<img src="../assets/16x16/emblem-system.png" alt="edit note" v-on:click="' + this.editTimeslotNote(this.current.timeslots[i].id) + '" />'
305
306
          options: '<span class="timeslotEditLink" onclick="' +
            'document.getElementById(\'app\').children[1].__vue__.' +
307
            'editTimeslotNote(' + this.current.timeslots[i].id + ', ' + this.current.timeslots[i].schedule + ')">edit</span> ' +
308
309
            '<span class="timeslotEditLink" onclick="alert(\'notYetImplemented\')">upload</span>' +
            '<span class="timeslotEditLink" onclick="alert(\'notYetImplemented\')">...</span>'
310
311
312
        })
      }
      return arr
313
314
315
    }
  },
  methods: {
316
    switchShow: function (index) {
317
318
319
      // if we already had some show loaded with timeslots and notes, set these to
      // not loaded, so we don't display old timeslots and notes while already
      // the new show is displayed and new timeslots and notes are still loading
320
321
322
323
324
325
326
327
      this.loaded.timeslots = false
      this.loaded.notes = false
      // also for those settings of the show which are only ids or arrays of ids
      // we have to fetch the corresponding names first
      this.loaded.categories = false
      this.loaded.hosts = false
      this.loaded.languages = false
      this.loaded.musicfocus = false
328
      this.loaded.fundingcategory = false
329
      // set the current show and its ID to whatever we want to switch to now
330
      this.currentShow = index
331
      this.currentShowID = this.shows[this.currentShow].id
332
333
334
335
336
337
      // before we load timeslots and notes, we want to fetch the general settings first
      this.getCategories()
      this.getHosts()
      this.getLanguages()
      this.getTopics()
      this.getMusicfocus()
338
      this.getFundingCategory()
339
      this.getType()
340
341
342
343
344
      // now fetch the timeslots (including notes) for a given show from PV backend
      this.getTimeslots(this.dateSlotsStart, this.dateSlotsEnd, this.numSlots)
    },
    getTimeslots: function (start, end, limit, offset) {
      var uri = process.env.API_STEERING_SHOWS + this.currentShowID + '/timeslots/?'
345
346
      if (typeof start === 'object') uri += 'start=' + this.apiDate(start)
      if (typeof end === 'object') uri += '&end=' + this.apiDate(end)
347
348
      if (typeof limit === 'number') uri += '&limit=' + limit
      if (typeof offset === 'number') uri += '&offset=' + offset
349
350
351
352
      axios.get(uri, {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
      }).then(response => {
353
354
355
        // if we use the limit argument results are paginated and look different
        // than without the limit argument
        if (typeof limit === 'number') {
356
357
358
359
          this.current.timeslots = response.data.results
          this.current.timeslotmeta.count = response.data.count
          this.current.timeslotmeta.next = response.data.next
          this.current.timeslotmeta.previous = response.data.previous
360
        } else {
361
362
363
364
          this.current.timeslots = response.data
          this.current.timeslotmeta.count = response.data.length
          this.current.timeslotmeta.next = null
          this.current.timeslotmeta.previous = null
365
        }
366
        this.loaded.timeslots = true
367
        // now that we have the timeslots we can fetch notes for all those timeslots
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
        uri = process.env.API_STEERING_SHOWS + this.currentShowID + '/notes/?ids='
        // add all note IDs from the timeslots that have existing notes
        var thereIsANote = false
        for (var i in this.current.timeslots) {
          if (typeof this.current.timeslots[i].note_id === 'number') {
            uri += this.current.timeslots[i].note_id + ','
            thereIsANote = true
          }
        }
        // now remove trailing ',' if at least one note already exists
        // and make the api call to fetch them
        if (thereIsANote) {
          uri = uri.slice(0, -1)
          axios.get(uri, {
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
            this.current.notes = response.data
            this.loaded.notes = true
          }).catch(error => {
            alert('There was an error fetching notes from the server' + error)
          })
          // done fetching notes
        } else {
          // if no notes exist that correspond to our selected timeslots, empty
          // the corresponding array
          this.current.notes = []
        }
396
397
      }).catch(error => {
        alert('There was an error fetching timeslots from the server' + error)
398
      })
399
400
      // done fetching timeslots
    },
401
402
    editTimeslotNote: function (timeslotID, scheduleID) {
      this.current.note = null
403
404
405
      for (var i in this.current.notes) {
        if (this.current.notes[i].timeslot === timeslotID) {
          this.current.note = this.current.notes[i]
406
407
408
          break
        }
      }
409
      this.$refs.appModalNotes.showModal(this.current.note, timeslotID, scheduleID)
410
    },
411
412
413
414
    getNoteByTimeslotID: function (timeslotID) {
      for (var i in this.current.notes) {
        if (this.current.notes[i].timeslot === timeslotID && this.current.notes[i].title !== undefined) {
          return this.current.notes[i]
415
416
417
418
        }
      }
      return null
    },
419
    prettyTimeslotNote: function (timeslotID) {
420
      var note = this.getTimeslotNoteTitle(timeslotID)
421
422
423
424
425
426
      if (note !== null) {
        return this.prettyTitle(note)
      } else {
        return ''
      }
    },
427
428
429
430
431
    prettyTitle: function (title) {
      if (title === '') return '...'
      else if (title.length > 25) return title.slice(0, 25) + '...'
      else return title
    },
432
433
434
435
436
437
438
439
440
441
    // TODO: all thos getSomething functions could be probably merged into one
    // generic getItem function. Maybe this.current should be an associative array
    // instead of an object then?
    getCategories: function () {
      this.current.categories = []
      var loadingError = false
      if (this.shows[this.currentShow].category.length === 0) {
        this.loaded.categories = true
      } else {
        for (var i in this.shows[this.currentShow].category) {
442
          axios.get(process.env.API_STEERING + 'categories/' + this.shows[this.currentShow].category[i] + '/', {
443
444
445
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
            this.current.categories.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching categories from the server: ' + error)
          })
        }
        if (!loadingError) this.loaded.categories = true
      }
    },
    getHosts: function () {
      this.current.hosts = []
      var loadingError = false
      if (this.shows[this.currentShow].hosts.length === 0) {
        this.loaded.hosts = true
      } else {
        for (var i in this.shows[this.currentShow].hosts) {
462
463
464
465
          axios.get(process.env.API_STEERING + 'hosts/' + this.shows[this.currentShow].hosts[i] + '/', {
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
466
467
468
469
470
471
472
473
474
475
476
477
478
            this.current.hosts.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching hosts from the server: ' + error)
          })
        }
        if (!loadingError) this.loaded.hosts = true
      }
    },
    getLanguages: function () {
      this.current.languages = []
      var loadingError = false
      if (this.shows[this.currentShow].language.length === 0) {
479
        this.loaded.languages = true
480
481
      } else {
        for (var i in this.shows[this.currentShow].language) {
482
          axios.get(process.env.API_STEERING + 'languages/' + this.shows[this.currentShow].language[i] + '/', {
483
484
485
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
486
487
488
489
490
491
            this.current.languages.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching languages from the server: ' + error)
          })
        }
492
        if (!loadingError) this.loaded.languages = true
493
494
495
496
497
498
499
500
501
      }
    },
    getTopics: function () {
      this.current.topics = []
      var loadingError = false
      if (this.shows[this.currentShow].topic.length === 0) {
        this.loaded.topics = true
      } else {
        for (var i in this.shows[this.currentShow].topic) {
502
          axios.get(process.env.API_STEERING + 'topics/' + this.shows[this.currentShow].topic[i] + '/', {
503
504
505
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
            this.current.topics.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching topics from the server: ' + error)
          })
        }
        if (!loadingError) this.loaded.topics = true
      }
    },
    getMusicfocus: function () {
      this.current.musicfocus = []
      var loadingError = false
      if (this.shows[this.currentShow].musicfocus.length === 0) {
        this.loaded.musicfocus = true
      } else {
        for (var i in this.shows[this.currentShow].musicfocus) {
522
          axios.get(process.env.API_STEERING + 'musicfocus/' + this.shows[this.currentShow].musicfocus[i] + '/', {
523
524
525
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
526
527
528
529
530
531
532
533
534
            this.current.musicfocus.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching musicfocus from the server: ' + error)
          })
        }
      }
      if (!loadingError) this.loaded.musicfocus = true
    },
535
    getFundingCategory: function () {
536
      this.current.fundingcategory = []
537
      var loadingError = false
538
539
      if (typeof this.shows[this.currentShow].fundingcategory !== 'number') {
        this.loaded.fundingcategory = true
540
      } else {
541
        axios.get(process.env.API_STEERING + 'fundingcategories/' + this.shows[this.currentShow].fundingcategory + '/', {
542
543
544
          withCredentials: true,
          headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
        }).then(response => {
545
          this.current.fundingcategory.push(response.data)
546
547
        }).catch(error => {
          loadingError = true
548
          alert('There was an error fetching funding category from the server: ' + error)
549
550
        })
      }
551
      if (!loadingError) this.loaded.fundingcategory = true
552
553
554
555
556
557
558
    },
    getType: function () {
      this.current.type = []
      var loadingError = false
      if (typeof this.shows[this.currentShow].type !== 'number') {
        this.loaded.type = true
      } else {
559
        axios.get(process.env.API_STEERING + 'types/' + this.shows[this.currentShow].type + '/', {
560
561
562
          withCredentials: true,
          headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
        }).then(response => {
563
564
565
566
567
          this.current.type.push(response.data)
        }).catch(error => {
          loadingError = true
          alert('There was an error fetching show type from the server: ' + error)
        })
568
      }
569
      if (!loadingError) this.loaded.type = true
570
    },
571
    notYetImplemented: function () {
572
      alert('By the mighty witchcraftry of the mother of time!\n\nThis feature is not implemented yet.')
573
574
575
    }
  },
  created () {
576
577
578
579
580
    var uri = process.env.API_STEERING_SHOWS
    if (!this.$parent.user.steeringUser.is_superuser) {
      uri += '?owner=' + this.$parent.user.steeringUser.id
    }
    axios.get(uri, {
581
582
583
      withCredentials: true,
      headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
    }).then(response => {
584
585
586
587
      if (response.data.length === 0) {
        alert('There are now shows associated with your account!')
        return
      }
588
589
590
      this.shows = response.data
      this.currentShowID = this.shows[0].id
      this.currentShow = 0
591
      this.loaded.shows = true
592
593
594
      this.switchShow(this.currentShow)
    }).catch(error => {
      alert('There was an error fetching shows from the server: ' + error)
595
596
597
598
599
    })
  }
}
</script>

600
<style>
601
602
603
604
605
606
607
608
609
span.timeslotEditLink {
  color: #8d5f82 !important;
  font-weight: bold;
  font-size: 0.8em;
  padding: 0.25em;
}
span.timeslotEditLink:hover {
  color: #ad7fa8 !important;
}
610
</style>