ShowManagerModalSuperuser.vue 14.5 KB
Newer Older
1
2
<template>
  <div>
3
    <!-- Modal for adding new shows -->
4
5
6
7
8
9
10
11
    <b-modal
      ref="modalAddShow"
      title="Create a new show"
      size="lg"
      @ok="addShow"
    >
      <b-container fluid>
        <b-row>
12
          <b-col cols="3">
13
14
            Name of the show:
          </b-col>
15
          <b-col cols="9">
16
17
18
19
20
21
            <b-form-input
              v-model="newShow.name"
              type="text"
              placeholder="Enter a title for this new show"
            />
          </b-col>
22
23
          <b-col cols="3" />
          <b-col cols="9">
24
25
26
27
            <small class="slug">Slug: {{ temporarySlug }}</small>
          </b-col>
        </b-row>
        <br>
28

29
        <b-row>
30
          <b-col cols="3">
31
32
            Short description:
          </b-col>
33
          <b-col cols="9">
34
35
36
37
38
39
40
            <b-form-input
              v-model="newShow.short_description"
              type="text"
              placeholder="Enter a short description for this show"
            />
          </b-col>
        </b-row>
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
        <br>

        <b-row>
          <b-col cols="3">
            Show type:
          </b-col>
          <b-col cols="9">
            <div v-if="!loaded.types">
              <img
                src="../assets/radio.gif"
                alt="loading data"
              >
            </div>
            <div v-else>
              <b-form-select
                v-model="newShow.type"
                :options="showTypeSelector"
              />
            </div>
          </b-col>
        </b-row>
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
        <b-row>
          <b-col cols="3">
            Funding category:
          </b-col>
          <b-col cols="9">
            <div v-if="!loaded.fundingcategories">
              <img
                src="../assets/radio.gif"
                alt="loading data"
              >
            </div>
            <div v-else>
              <b-form-select
                v-model="newShow.fundingcategory"
                :options="showFundingCategorySelector"
              />
            </div>
          </b-col>
        </b-row>
82
83
      </b-container>
    </b-modal>
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

    <!-- Modal to confirm and delete a show -->
    <b-modal
      ref="modalDeleteShow"
      title="Delete a show"
      size="lg"
      @ok="deleteShow"
    >
      <b-alert
        variant="danger"
        show
      >
        You are about to delete the show <b>{{ deletedShow.name }}</b>!
      </b-alert>
      <div align="center">
        Are you sure you want to continue?
      </div>
    </b-modal>
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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
208
209
210
211
212
213
214
215
216
217
218
219

    <!-- Modal to edit show owners -->
    <b-modal
      ref="modalOwners"
      title="Edit owners of the show"
      size="lg"
      @ok="updateOwners"
    >
      <div v-if="loaded.users">
        <p>
          Users with access to <b>{{ show.name }}</b>:
        </p>
        <div v-if="owners.length === 0">
          <ul>
            <li>
              <small><i>(none set)</i></small>
            </li>
          </ul>
        </div>
        <div v-else>
          <b-table
            striped
            hover
            :items="owners"
            :fields="ownersTableFields"
          >
            <template
              slot="name"
              slot-scope="data"
            >
              {{ data.item.first_name }} {{ data.item.last_name }}
            </template>
            <template
              slot="username"
              slot-scope="data"
            >
              <small>{{ data.value }}</small>
            </template>
            <template
              slot="email"
              slot-scope="data"
            >
              <small>{{ data.value }}</small>
            </template>
            <template
              slot="options"
              slot-scope="data"
            >
              <b-button
                variant="danger"
                size="sm"
                @click="deleteOwner(data.item.id)"
              >
                Delete
              </b-button>
            </template>
          </b-table>
        </div>

        <hr>

        <!-- TODO: as the list of users might be quite large we need some sort
          of pagination and/or a search box. also those users who already have
          access should not be listed (or at least the add button should be disabled)
        -->
        <p>
          You can
          <b-badge variant="success">
            add new users
          </b-badge>
          from the table below:
        </p>
        <b-table
          striped
          hover
          :items="users"
          :fields="ownersTableFields"
        >
          <template
            slot="name"
            slot-scope="data"
          >
            {{ data.item.first_name }} {{ data.item.last_name }}
          </template>
          <template
            slot="username"
            slot-scope="data"
          >
            <small>{{ data.value }}</small>
          </template>
          <template
            slot="email"
            slot-scope="data"
          >
            <small>{{ data.value }}</small>
          </template>
          <template
            slot="options"
            slot-scope="data"
          >
            <b-button
              variant="success"
              size="sm"
              @click="addOwner(data.item.id)"
            >
              Add
            </b-button>
          </template>
        </b-table>
      </div>
      <div v-else>
        <img
          src="../assets/radio.gif"
          height="32px"
          alt="loading user data"
        >
      </div>
    </b-modal>
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  </div>
</template>

<script>
import axios from 'axios'
import slugify from '../mixins/slugify.js'

export default {
  mixins: [ slugify ],
  data () {
    return {
      newShow: {
        name: "",
        slug: "",
        short_description: "",
235
236
        type: 0,
        fundingcategory: 0,
237
238
239
240
241
        category: [],
        hosts: [],
        owners: [],
        language: [],
        topic: [],
242
243
244
245
246
        musicfocus: [],
      },
      deletedShow: {
        id: null,
        name: '',
247
      },
248
      show: null,
249
250
251
      loaded: {
        types: false,
        fundingcategories: false,
252
        users: false,
253
254
255
      },
      types: [],
      fundingcategories: [],
256
257
258
      users: [],
      owners: [],
      ownersTableFields: ['name', 'username', 'email', 'options']
259
260
    }
  },
261

262
263
  computed: {
    temporarySlug: function () {
264
      return this.slugify(this.newShow.name)
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
    },

    showTypeSelector: function () {
      let options = []
      for (let i in this.types) {
        options.push({
          value: this.types[i].id,
          text: this.types[i].type
        })
      }
      return options
    },

    showFundingCategorySelector: function () {
      let options = []
      for (let i in this.fundingcategories) {
        options.push({
          value: this.fundingcategories[i].id,
          text: this.fundingcategories[i].abbrev + ' (' + this.fundingcategories[i].fundingcategory + ')'
        })
      }
      return options
    },
288
  },
289

290
  methods: {
291
292
293
294
295
    // create a new show and POST it to the steering API
    // new shows have to at least contain a name, a slug and a short-description.
    // also a valide show type and funding category have to be choosen.
    // for all other categories we can use an empty array and let the user fill
    // it out through the existing show manager modals, after the show is created
296
297
298
    addShow (event) {
      // prevent the modal from closing automatically on click
      event.preventDefault()
299

300
301
302
303
      // only try to add a new show if name and short description are filled out
      if (this.newShow.name.trim() === '' || this.newShow.short_description.trim() === '' ) {
        // TODO: make this nicer UI-wise (red text annotations next to input fields instead of simple alert)
        alert('Please provide at least a title and a short description for this show.')
304
305
306
307
308
309
310
311
312
313
314
315
        return
      }
      // also the type and funding category have to be set
      if (this.types.findIndex(type => type.id === this.newShow.type) === -1) {
        // TODO: make this nicer UI-wise (red text annotations next to input fields instead of simple alert)
        alert('Please choose a type for this show.')
        return
      }
      if (this.fundingcategories.findIndex(cat => cat.id === this.newShow.fundingcategory) === -1) {
        // TODO: make this nicer UI-wise (red text annotations next to input fields instead of simple alert)
        alert('Please choose a funding category for this show.')
        return
316
      }
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

      // as the slug is a computed property we have to assign it to the new show's slug property
      this.newShow.slug = this.temporarySlug

      // ready to go, let's POST this new show
      let uri = process.env.VUE_APP_API_STEERING_SHOWS
      axios.post(uri, this.newShow, {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.$parent.user.access_token }
      }).then(response => {
        // everything was fine, we can close the modal now
        this.$refs.modalAddShow.hide()
        this.$parent.loadAndSwitch(response.data.id)
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not add new show. See console for details.')
        // and we leave the modal open, so no call to its .hide function here
      })
336
    },
337

338
    // delete a show by sending a DELETE to the steering API
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    deleteShow (event) {
      // prevent the modal from closing automatically on click
      event.preventDefault()
      let uri = process.env.VUE_APP_API_STEERING_SHOWS + this.deletedShow.id
      axios.delete(uri, {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.$parent.user.access_token }
      }).then(() => {
        this.$refs.modalDeleteShow.hide()
        this.$parent.loadAndSwitch(null)
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not delete show. See console for details.')
        // and we leave the modal open, so no call to its .hide function here
      })
    },

357
358
359
360
361
362
363
364
365
366
367
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
396
397
398
399
400
    // remove an owner from the list of show owners
    deleteOwner (id) {
      // we only have to find the item in our array and splice it out
      // saving is done when the updateOwners method is called
      let i = this.owners.findIndex(o => o.id === id)
      this.owners.splice(i, 1)
    },

    // add a user as an owner to the list of show owners
    addOwner (id) {
      // we only have to push the user object to our owners array, if it is
      // not already there. saving is done by the updateOwners method.
      if (this.owners.findIndex(o => o.id === id) >= 0) {
        alert('This user already has access to the show.')
      } else {
        this.owners.push(this.users.find(u => u.id === id))
      }
    },

    // set new list of show owners by updating the show
    updateOwners (event) {
      // prevent the modal from closing automatically on click
      event.preventDefault()
      // now we have to fill the show's owner list anew with the selected owners
      this.show.owners = []
      for (let i in this.owners) {
        this.show.owners.push(this.owners[i].id)
      }
      // ready to update the show
      let uri = process.env.VUE_APP_API_STEERING_SHOWS + this.show.id + '/'
      axios.put(uri, this.show, {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.$parent.user.access_token }
      }).then(() => {
        this.$refs.modalOwners.hide()
        this.$parent.loadAndSwitch(this.show.id)
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not update show owners. See console for details.')
        // and we leave the modal open, so no call to its .hide function here
      })
    },

401
    // clear and fetch modal data and open the modal to add new shows
402
403
404
405
    showModalAddShow () {
      this.newShow.name = ''
      this.newShow.slug = ''
      this.newShow.short_description = ''
406
407
      this.loadTypes()
      this.loadFundingCategories()
408
      this.$refs.modalAddShow.show()
409
410
    },

411
    // open the deletion confirmation modal
412
413
414
415
    showModalDeleteShow (id, name) {
      this.deletedShow.id = id
      this.deletedShow.name = name
      this.$refs.modalDeleteShow.show()
416
417
    },

418
419
420
421
422
423
    // open the modal to edit a show's owners
    showModalOwners (show) {
      this.show = show
      this.owners = []
      this.loadUsers()
      this.$refs.modalOwners.show()
424
425
    },

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
    // fetch all available (that is: active) show type from steering
    loadTypes () {
      this.loaded.types = false
      axios.get(process.env.VUE_APP_API_STEERING + 'types/?active=true', {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.$parent.user.access_token }
      }).then(response => {
        this.types = response.data
        this.loaded.types = true
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not load available show types. See console for details.')
      })
    },

    // fetch all available (that is: active) funding categories from steering
    loadFundingCategories () {
      this.loaded.fundingcategories = false
      axios.get(process.env.VUE_APP_API_STEERING + 'fundingcategories/?active=true', {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.$parent.user.access_token }
      }).then(response => {
        this.fundingcategories = response.data
        this.loaded.fundingcategories = true
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not load available funding categories. See console for details.')
      })
    },
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

    // fetch all users from steering
    loadUsers () {
      this.loaded.users = false
      axios.get(process.env.VUE_APP_API_STEERING + 'users', {
        withCredentials: true,
        headers: { 'Authorization': 'Bearer ' + this.$parent.$parent.user.access_token }
      }).then(response => {
        this.users = response.data
        for (let i in this.show.owners) {
          this.owners.push(this.users.find(user => user.id === this.show.owners[i]))
        }
        this.loaded.users = true
      }).catch(error => {
        this.$log.error(error.response.status + ' ' + error.response.statusText)
        this.$log.error(error.response)
        alert('Error: could not load users. See console for details.')
      })
    },
476
477
478
479
480
481
482
483
484
  }
}
</script>

<style scoped>
.slug {
  color: gray;
}
</style>