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

    <b-jumbotron>
      <template slot="header">
24
25
        <span v-if="loaded.shows">
          {{ shows[currentShow].name }}
26
27
28
29
30
          <img
            src="../assets/16x16/emblem-system.png"
            alt="edit name of show"
            @click="$refs.appModalShow.showName()"
          >
31
        </span>
32
33
34
        <span v-else>Shows are being loaded</span>
      </template>
      <template slot="lead">
35
        <span v-if="loaded.shows">{{ shows[currentShow].short_description }}</span>
36
37
38
39
40
        <img
          src="../assets/16x16/emblem-system.png"
          alt="edit short description"
          @click="$refs.appModalShow.showShortDescription()"
        >
41
      </template>
42
      <div v-if="loaded.shows">
43
44
45
46
47
        <b>Description:</b> <img
          src="../assets/16x16/emblem-system.png"
          alt="edit description"
          @click="$refs.appModalShow.showDescription()"
        >
48
        <div v-if="loaded.shows">
49
50
51
52
53
54
          <!--
          we are disabling the linter warning for the next line, because, while it
          generally is not advisible to use v-html, in this case we took thorough
          steps to sanitize the date before inserting it into the DOM
          -->
          <!-- eslint-disable-next-line vue/no-v-html -->
55
          <p v-html="sanitizedShowDescription" />
56
57
          <!-- TODO: add image and logo here? -->
        </div>
58
      </div>
59
60
    </b-jumbotron>

61
    <div v-if="!loaded.shows">
62
63
      <b-row>
        <b-col align="center">
64
65
66
67
          <img
            src="../assets/radio.gif"
            alt="loading data"
          >
68
69
        </b-col>
      </b-row>
70
71
    </div>
    <div v-else>
72
      <!-- include the modals to edit show and timeslot entries from the modal compontents -->
73
74
75
76
77
78
79
80
81
      <app-modalShow
        ref="appModalShow"
        :show="shows[currentShow]"
      />
      <app-modalNotes
        ref="appModalNotes"
        :show="shows[currentShow]"
        :show-aggregate="current"
      />
82

83
      <!-- here we show our table of timeslots -->
84
      <b-card>
85
86
87
        <b-btn v-b-toggle.timeslotFilterCollapse>
          Toggle timeslot filters
        </b-btn>
88
        <b-collapse id="timeslotFilterCollapse">
89
          <br>
90
          <b-row>
91
92
93
94
95
96
97
98
99
100
            <b-col sm="3">
              <label for="inputNumSlots">Number of slots to show:</label>
            </b-col>
            <b-col sm="9">
              <b-form-input
                id="inputNumSlots"
                v-model="numSlots"
                type="number"
              />
            </b-col>
101
102
          </b-row>
          <b-row>
103
104
105
106
107
108
109
110
111
112
            <b-col sm="3">
              <label for="inputDateStart">From:</label>
            </b-col>
            <b-col sm="9">
              <b-form-input
                id="inputDateStart"
                v-model="dateStart"
                type="date"
              />
            </b-col>
113
114
          </b-row>
          <b-row>
115
116
117
118
119
120
121
122
123
124
            <b-col sm="3">
              <label for="inputNumSlots">Until (exclusive):</label>
            </b-col>
            <b-col sm="9">
              <b-form-input
                id="inputDateEnd"
                v-model="dateEnd"
                type="date"
              />
            </b-col>
125
          </b-row>
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
          <br>
          <b-container
            fluid
            class="text-right"
          >
            <b-btn
              variant="outline-danger"
              @click="resetFilter()"
            >
              Reset filter
            </b-btn> &nbsp;
            <b-btn
              variant="info"
              @click="applyFilter()"
            >
              Apply filter
            </b-btn>
143
144
145
146
          </b-container>
        </b-collapse>
      </b-card>

147
      <br>
148

149
      <div v-if="loaded.timeslots">
150
151
152
153
154
155
156
157
158
159
160
        <b-table
          striped
          hover
          outlined
          :fields="notesTableArrayFields"
          :items="notesTableArray"
        >
          <template
            slot="title"
            slot-scope="data"
          >
161
162
163
            <span v-if="data.value">{{ data.value }}</span>
            <span v-else><small><i>(none set)</i></small></span>
          </template>
164
165
166
167
          <template
            slot="starts"
            slot-scope="data"
          >
168
169
            {{ data.value }}
          </template>
170
171
172
173
          <template
            slot="duration"
            slot-scope="data"
          >
174
175
            {{ data.value }}
          </template>
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
          <template
            slot="options"
            slot-scope="data"
          >
            <span
              class="timeslotEditLink"
              @click="editTimeslotNote(data.item.options.id, data.item.options.schedule)"
            ><img
              src="../assets/16x16/emblem-system.png"
              alt="Edit description"
              title="Edit description"
            ></span>
            <span
              class="timeslotEditLink"
              @click="notYetImplemented()"
            ><img
              src="../assets/16x16/media-eject.png"
              alt="Upload audio file / Create playlist"
              title="Upload audio file / Create playlist"
            ></span>
            <span
              class="timeslotEditLink"
              @click="notYetImplemented()"
            ><img
              src="../assets/16x16/media-playback-start.png"
              alt="Play audio file / playlist"
              title="Play audio file / playlist"
            ></span>
            <span
              class="timeslotEditLink"
              @click="notYetImplemented()"
            >...</span>
208
209
          </template>
        </b-table>
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
        <b-pagination
          v-model="current.timeslotmeta.page"
          align="center"
          :total-rows="current.timeslotmeta.count"
          :per-page="current.timeslotmeta.perpage"
          @change="timeslotsPage"
        />
      </div>
      <div
        v-else
        style="text-align: center;"
      >
        <img
          src="../assets/radio.gif"
          alt="loading data"
        ><br>
226
227
      </div>

228
      <hr>
229

230
231
232
233
      <h2>Allgemeine Einstellungen zur Sendereihe:</h2>
      <b-row>
        <b-col lg="6">
          <p>
234
235
236
            <b-badge variant="light">
              E-Mail:
            </b-badge>
237
238
            <span v-if="shows[currentShow].email === null"><small><i>(none set)</i></small></span>
            <span v-else>{{ shows[currentShow].email }}</span>
239
240
241
242
243
            <img
              src="../assets/16x16/emblem-system.png"
              alt="edit contact e-mail"
              @click="$refs.appModalShow.showEmail()"
            >
244
245
          </p>
        </b-col>
246

247
248
        <b-col lg="6">
          <p>
249
250
251
            <b-badge variant="light">
              Website:
            </b-badge>
252
253
            <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>
254
255
256
257
258
            <img
              src="../assets/16x16/emblem-system.png"
              alt="edit website"
              @click="$refs.appModalShow.showWebsite()"
            >
259
260
          </p>
        </b-col>
261

262
263
        <b-col lg="6">
          <p>
264
265
266
            <b-badge variant="light">
              Show type:
            </b-badge>
267
268
269
270
            <!-- 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>
271
272
273
274
275
              <img
                src="../assets/16x16/emblem-system.png"
                alt="edit"
                @click="$refs.appModalShow.showType()"
              >
276
            </span>
277
278
279
280
281
            <span v-else><img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ></span>
282
283
          </p>
        </b-col>
284

285
286
        <b-col lg="6">
          <p>
287
288
289
            <b-badge variant="light">
              Funding category (eg. for RTR):
            </b-badge>
290
            <!-- TODO: discuss: should this be visible to show owners or only to administrators? -->
291
292
293
            <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>
294
295
296
297
298
              <img
                src="../assets/16x16/emblem-system.png"
                alt="edit"
                @click="$refs.appModalShow.showFundingCategory()"
              >
299
            </span>
300
301
302
303
304
            <span v-else><img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ></span>
305
306
          </p>
        </b-col>
307

308
309
310
        <b-col lg="6">
          <p>
            <!-- TODO: discuss: should this be visible to show owners or only to administrators? -->
311
            <!-- TODO: fetch name for predecessor from steering api -->
312
313
314
            <b-badge variant="light">
              Predecessor:
            </b-badge>
315
            <span v-if="shows[currentShow].predecessor === null"><small><i>This show has no predecessor show.</i></small></span>
316
            <span v-else>{{ predecessorName }}</span>
317
318
319
320
321
            <img
              src="../assets/16x16/emblem-system.png"
              alt="edit"
              @click="$refs.appModalShow.showPredecessor()"
            >
322
323
          </p>
        </b-col>
324

325
326
        <b-col lg="6">
          <p>
327
328
329
            <b-badge variant="light">
              CBA Series ID:
            </b-badge>
330
331
            <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>
332
333
334
335
336
            <img
              src="../assets/16x16/emblem-system.png"
              alt="edit CBA series ID"
              @click="$refs.appModalShow.showCBAid()"
            >
337
338
          </p>
        </b-col>
339

340
341
        <b-col lg="6">
          <p>
342
343
344
            <b-badge variant="light">
              Fallback List/Pool:
            </b-badge>
345
346
            <span v-if="shows[currentShow].fallback_id === ''"><small><i>(none set)</i></small></span>
            <span v-else>ID: {{ shows[currentShow].fallback_id }}</span>
347
348
349
350
351
            <img
              src="../assets/16x16/emblem-system.png"
              alt="edit"
              @click="notYetImplemented"
            >
352
353
354
          </p>
        </b-col>
      </b-row>
355

356
357
      <b-row>
        <b-col lg="2">
358
359
360
361
362
363
364
          <b-badge style="width:80%;">
            Categories:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showCategories()"
          >
365
366
367
368
369
370
371
372
        </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>
373
374
375
376
377
378
                <li
                  v-for="cat in current.categories"
                  :key="cat.id"
                >
                  {{ cat.category }}
                </li>
379
380
381
              </ul>
            </p>
          </div>
382
383
384
385
386
387
388
          <div v-else>
            <img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ><br>
          </div>
389
        </b-col>
390

391
        <b-col lg="2">
392
393
394
395
396
397
398
          <b-badge style="width:80%;">
            Topics:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showTopics()"
          >
399
400
401
402
403
404
405
406
        </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>
407
408
409
410
411
412
                <li
                  v-for="topic in current.topics"
                  :key="topic.id"
                >
                  {{ topic.topic }}
                </li>
413
414
415
              </ul>
            </p>
          </div>
416
417
418
419
420
421
422
          <div v-else>
            <img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ><br>
          </div>
423
        </b-col>
424

425
        <b-col lg="2">
426
427
428
429
430
431
432
          <b-badge style="width:80%;">
            Musicfocus:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showMusicFocus()"
          >
433
434
435
436
437
438
439
440
        </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>
441
442
443
444
445
446
                <li
                  v-for="focus in current.musicfocus"
                  :key="focus.id"
                >
                  {{ focus.focus }}
                </li>
447
448
449
              </ul>
            </p>
          </div>
450
451
452
453
454
455
456
          <div v-else>
            <img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ><br>
          </div>
457
        </b-col>
458

459
        <b-col lg="2">
460
461
462
463
464
465
466
          <b-badge style="width:80%;">
            Languages:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showLanguages()"
          >
467
468
469
470
471
472
473
474
        </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>
475
476
477
478
479
480
                <li
                  v-for="lang in current.languages"
                  :key="lang.id"
                >
                  {{ lang.name }}
                </li>
481
482
483
              </ul>
            </p>
          </div>
484
485
486
487
488
489
490
          <div v-else>
            <img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ><br>
          </div>
491
        </b-col>
492

493
        <b-col lg="2">
494
495
496
497
498
499
500
          <b-badge style="width:80%;">
            Hosts:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showHosts()"
          >
501
502
503
504
505
506
507
508
509
        </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>
510
511
512
513
514
515
                <li
                  v-for="host in current.hosts"
                  :key="host.id"
                >
                  {{ host.name }}
                </li>
516
517
518
              </ul>
            </p>
          </div>
519
520
521
522
523
524
525
          <div v-else>
            <img
              src="../assets/radio.gif"
              height="24px"
              alt="loading data"
            ><br>
          </div>
526
527
        </b-col>
      </b-row>
528
529
530

      <b-row>
        <b-col lg="2">
531
532
533
534
535
536
537
          <b-badge style="width:80%;">
            Logo:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showLogo()"
          >
538
539
        </b-col>
        <b-col lg="4">
540
          <div v-if="current.logo.length === 0">
541
542
543
            <small><i>(none set)</i></small>
          </div>
          <div v-else>
544
545
546
547
548
549
550
            <br>
            <b-img
              thumbnail
              :src="current.logo"
              fluid
              @click="$refs.appModalShow.showLogo()"
            />
551
552
553
554
          </div>
        </b-col>

        <b-col lg="2">
555
556
557
558
559
560
561
          <b-badge style="width:80%;">
            Image:
          </b-badge> <img
            src="../assets/16x16/emblem-system.png"
            alt="edit"
            @click="$refs.appModalShow.showImage()"
          >
562
563
        </b-col>
        <b-col lg="4">
564
          <div v-if="current.image.length === 0">
565
566
567
            <small><i>(none set)</i></small>
          </div>
          <div v-else>
568
569
570
571
572
573
574
            <br>
            <b-img
              thumbnail
              :src="current.image"
              fluid
              @click="$refs.appModalShow.showImage()"
            />
575
576
577
578
          </div>
        </b-col>
      </b-row>

579
      <hr>
580
    </div>
581
  </b-container>
582
583
584
</template>

<script>
585
import modalNotes from './ShowManagerModalNotes.vue'
586
import modalShow from './ShowManagerModalShow.vue'
587
import timeslotSort from '../mixins/timeslotSort'
588
import prettyDate from '../mixins/prettyDate'
589
import axios from 'axios'
590
import DOMPurify from 'dompurify'
591
592

export default {
593
  components: {
594
595
    'app-modalNotes': modalNotes,
    'app-modalShow': modalShow
596
  },
597
  mixins: [ timeslotSort, prettyDate ],
598
599
  data () {
    return {
600
601
602
      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
603
      numSlots: process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_NUMSLOTS, // all form input values are provided as strings
604
      dateStart: this.apiDate(new Date()),
605
      dateEnd: this.apiDate(new Date(new Date().getTime() + process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_DAYS * 86400000)),
606
607
608
609
610
611
612
613
614
      loaded: {
        shows: false,
        timeslots: false,
        notes: false,
        categories: false,
        hosts: false,
        languages: false,
        topics: false,
        musicfocus: false,
615
        fundingcategory: false,
616
        type: false
617
618
619
620
621
622
623
      },
      current: {
        categories: [],
        hosts: [],
        languages: [],
        topics: [],
        musicfocus: [],
624
        fundingcategory: [],
625
        type: [],
626
627
628
629
        timeslots: [],
        timeslotmeta: {    // meta info when pagination is used
          count: 0,
          next: null,
630
631
632
          previous: null,
          page: 1,   // page indexes start at 1 for <b-pagination> components
          perpage: 10
633
634
        },
        note: {},
635
636
637
        notes: [],
        image: '',
        logo: ''
638
639
640
641
642
643
644
      },
      notesTableArrayFields: [
        { key: 'title', label: 'Title of emission' },
        { key: 'starts', label: 'Emission start' },
        { key: 'duration', label: 'Duration' },
        { key: 'options', label: 'Edit' }
      ]
645
646
647
    }
  },
  computed: {
648
649
650
651
    sanitizedShowDescription: function () {
      //return this.shows[this.currentShow].description.replace(/<[^>]*>/g, '')
      return DOMPurify.sanitize(this.shows[this.currentShow].description)
    },
652
653
    predecessorName: function () {
      for (var i in this.shows) {
654
        if (this.shows[i].id === this.shows[this.currentShow].predecessor) {
655
656
657
658
659
          return this.shows[i].name
        }
      }
      return 'Name of predecessor show not available'
    },
660
661
    notesTableArray: function () {
      var arr = []
662
663
      for (var i in this.current.timeslots) {
        var note = this.getNoteByTimeslotID(this.current.timeslots[i].id)
664
        if (note !== null) { note = note.title }
665
        arr.push({
666
667
          title: note,
          starts: this.prettyDateTime(this.current.timeslots[i].start),
668
          duration: this.prettyDuration(this.current.timeslots[i].start, this.current.timeslots[i].end),
669
670
671
672
          options: {
            id: this.current.timeslots[i].id,
            schedule: this.current.timeslots[i].schedule
          }
673
674
675
        })
      }
      return arr
676
677
    }
  },
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  created () {
    var uri = process.env.VUE_APP_API_STEERING_SHOWS
    if (!this.$parent.user.steeringUser.is_superuser) {
      uri += '?owner=' + this.$parent.user.steeringUser.id
    }
    axios.get(uri, {
      withCredentials: true,
      headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
    }).then(response => {
      if (response.data.length === 0) {
        alert('There are now shows associated with your account!')
        return
      }
      this.shows = response.data
      this.currentShowID = this.shows[0].id
      this.currentShow = 0
      this.loaded.shows = true
      this.switchShow(this.currentShow)
    }).catch(error => {
      alert('There was an error fetching shows from the server: ' + error)
    })
  },
700
  methods: {
701
702
703
704
705
    applyFilter: function () {
      this.current.timeslotmeta.page = 1
      this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots)
    },
    resetFilter: function () {
706
      this.numSlots = process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_NUMSLOTS
707
      this.dateStart = this.apiDate(new Date())
708
      this.dateEnd = this.apiDate(new Date(new Date().getTime() + process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_DAYS * 86400000))
709
710
711
712
713
714
715
716
717
      this.current.timeslotmeta.page = 1
      this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots)
    },
    timeslotsPage: function (page) {
      if (this.current.timeslotmeta.page !== page) {
        this.current.timeslotmeta.page = page
        this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots, (page - 1) * this.numSlots)
      }
    },
718
    switchShow: function (index) {
719
720
721
      // 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
722
723
724
725
726
727
728
729
      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
730
      this.loaded.fundingcategory = false
731
      // set the current show and its ID to whatever we want to switch to now
732
      this.currentShow = index
733
      this.currentShowID = this.shows[this.currentShow].id
734
735
      // and check if images are available and set image strings, because we
      // cannot use them directly inside the b-img if they are null
736
737
738
739
      if (this.shows[this.currentShow].logo === null) { this.current.logo = '' }
      else { this.current.logo = this.shows[this.currentShow].logo }
      if (this.shows[this.currentShow].image === null) { this.current.image = '' }
      else { this.current.image = this.shows[this.currentShow].image }
740
741
742
743
744
745
      // before we load timeslots and notes, we want to fetch the general settings first
      this.getCategories()
      this.getHosts()
      this.getLanguages()
      this.getTopics()
      this.getMusicfocus()
746
      this.getFundingCategory()
747
      this.getType()
748
      // now fetch the timeslots (including notes) for a given show from PV backend
749
      this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots)
750
751
    },
    getTimeslots: function (start, end, limit, offset) {
752
      var dateRegex = new RegExp('^\\d{4}-\\d{2}-\\d{2}$')
753
      var uri = process.env.VUE_APP_API_STEERING_SHOWS + this.currentShowID + '/timeslots/?'
754
755
756
757
      if (dateRegex.test(start)) { uri += 'start=' + start + '&' }
      if (dateRegex.test(end)) { uri += 'end=' + end + '&' }
      if (!isNaN(parseInt(limit))) { uri += 'limit=' + parseInt(limit) + '&' }
      if (!isNaN(parseInt(offset))) { uri += 'offset=' + parseInt(offset) }
758
759
      this.loaded.timeslots = false
      this.loaded.notes = false
760
761
762
763
      axios.get(uri, {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
      }).then(response => {
764
765
        // if we use the limit argument results are paginated and look different
        // than without the limit argument
766
        if (!isNaN(parseInt(limit))) {
767
768
769
770
          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
771
          this.current.timeslotmeta.perpage = parseInt(limit)
772
        } else {
773
774
775
776
          this.current.timeslots = response.data
          this.current.timeslotmeta.count = response.data.length
          this.current.timeslotmeta.next = null
          this.current.timeslotmeta.previous = null
777
          this.current.timeslotmeta.perpage = response.data.length
778
        }
779
        this.loaded.timeslots = true
780
        // now that we have the timeslots we can fetch notes for all those timeslots
781
        uri = process.env.VUE_APP_API_STEERING_SHOWS + this.currentShowID + '/notes/?ids='
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
        // 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 = []
        }
809
      }).catch(error => {
810
811
        console.log(error)
        alert('There was an error fetching timeslots from the server\n' + error)
812
      })
813
814
      // done fetching timeslots
    },
815
816
    editTimeslotNote: function (timeslotID, scheduleID) {
      this.current.note = null
817
818
819
      for (var i in this.current.notes) {
        if (this.current.notes[i].timeslot === timeslotID) {
          this.current.note = this.current.notes[i]
820
821
822
          break
        }
      }
823
      this.$refs.appModalNotes.showModal(this.current.note, timeslotID, scheduleID)
824
    },
825
826
827
828
    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]
829
830
831
832
        }
      }
      return null
    },
833
    prettyTimeslotNote: function (timeslotID) {
834
      var note = this.getTimeslotNoteTitle(timeslotID)
835
836
837
838
839
840
      if (note !== null) {
        return this.prettyTitle(note)
      } else {
        return ''
      }
    },
841
    prettyTitle: function (title) {
842
843
844
      if (title === '') { return '...' }
      else if (title.length > 25) { return title.slice(0, 25) + '...' }
      else { return title }
845
    },
846
847
848
849
850
851
852
853
854
855
    // 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) {
856
          axios.get(process.env.VUE_APP_API_STEERING + 'categories/' + this.shows[this.currentShow].category[i] + '/', {
857
858
859
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
860
861
862
863
864
865
            this.current.categories.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching categories from the server: ' + error)
          })
        }
866
        if (!loadingError) { this.loaded.categories = true }
867
868
869
870
871
872
873
874
875
      }
    },
    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) {
876
          axios.get(process.env.VUE_APP_API_STEERING + 'hosts/' + this.shows[this.currentShow].hosts[i] + '/', {
877
878
879
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
880
881
882
883
884
885
            this.current.hosts.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching hosts from the server: ' + error)
          })
        }
886
        if (!loadingError) { this.loaded.hosts = true }
887
888
889
890
891
892
      }
    },
    getLanguages: function () {
      this.current.languages = []
      var loadingError = false
      if (this.shows[this.currentShow].language.length === 0) {
893
        this.loaded.languages = true
894
895
      } else {
        for (var i in this.shows[this.currentShow].language) {
896
          axios.get(process.env.VUE_APP_API_STEERING + 'languages/' + this.shows[this.currentShow].language[i] + '/', {
897
898
899
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
900
901
902
903
904
905
            this.current.languages.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching languages from the server: ' + error)
          })
        }
906
        if (!loadingError) { this.loaded.languages = true }
907
908
909
910
911
912
913
914
915
      }
    },
    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) {
916
          axios.get(process.env.VUE_APP_API_STEERING + 'topics/' + this.shows[this.currentShow].topic[i] + '/', {
917
918
919
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
920
921
922
923
924
925
            this.current.topics.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching topics from the server: ' + error)
          })
        }
926
        if (!loadingError) { this.loaded.topics = true }
927
928
929
930
931
932
933
934
935
      }
    },
    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) {
936
          axios.get(process.env.VUE_APP_API_STEERING + 'musicfocus/' + this.shows[this.currentShow].musicfocus[i] + '/', {
937
938
939
            withCredentials: true,
            headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
          }).then(response => {
940
941
942
943
944
945
946
            this.current.musicfocus.push(response.data)
          }).catch(error => {
            loadingError = true
            alert('There was an error fetching musicfocus from the server: ' + error)
          })
        }
      }
947
      if (!loadingError) { this.loaded.musicfocus = true }
948
    },
949
    getFundingCategory: function () {
950
      this.current.fundingcategory = []
951
      var loadingError = false
952
953
      if (typeof this.shows[this.currentShow].fundingcategory !== 'number') {
        this.loaded.fundingcategory = true
954
      } else {
955
        axios.get(process.env.VUE_APP_API_STEERING + 'fundingcategories/' + this.shows[this.currentShow].fundingcategory + '/', {
956
957
958
          withCredentials: true,
          headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
        }).then(response => {
959
          this.current.fundingcategory.push(response.data)
960
961
        }).catch(error => {
          loadingError = true
962
          alert('There was an error fetching funding category from the server: ' + error)
963
964
        })
      }
965
      if (!loadingError) { this.loaded.fundingcategory = true }
966
967
968
969
970
971
972
    },
    getType: function () {
      this.current.type = []
      var loadingError = false
      if (typeof this.shows[this.currentShow].type !== 'number') {
        this.loaded.type = true
      } else {
973
        axios.get(process.env.VUE_APP_API_STEERING + 'types/' + this.shows[this.currentShow].type + '/', {
974
975
976
          withCredentials: true,
          headers: { 'Authorization': 'Bearer ' + this.$parent.user.access_token }
        }).then(response => {
977
978
979
980
981
          this.current.type.push(response.data)
        }).catch(error => {
          loadingError = true
          alert('There was an error fetching show type from the server: ' + error)
        })
982
      }
983
      if (!loadingError) { this.loaded.type = true }
984
    },
985
    notYetImplemented: function () {
986
      alert('By the mighty witchcraftry of the mother of time!\n\nThis feature is not implemented yet.')
987
988
989
990
991
    }
  }
}
</script>

992
<style>
993
994
995
996
997
998
999
1000
span.timeslotEditLink {
  color: #8d5f82 !important;
  font-weight: bold;
  font-size: 0.8em;
  padding: 0.25em;
}
span.timeslotEditLink:hover {
  color: #ad7fa8 !important;