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

META: improve ShowManager structure & comments

parent 09efcd58
<template>
<b-container>
<!-- This first row is so far only used to provide a dropdown for
choosing one of the loaded shows (which the user has access to) -->
<b-row>
<b-col>
<h3>Sendungen verwalten</h3>
</b-col>
<b-col align="right">
<b-dropdown
id="ddshows"
......@@ -19,7 +24,10 @@
</b-row>
<hr>
<!-- The jumbotron is used to display the name and description of the
currently selected show -->
<b-jumbotron>
<!-- The show title goes into the jumbotron header -->
<template slot="header">
<span v-if="loaded.shows">
{{ shows[currentShow].name }}
......@@ -31,6 +39,7 @@
</span>
<span v-else>Shows are being loaded</span>
</template>
<!-- The short description of the show goes into the jumbotron lead -->
<template slot="lead">
<span v-if="loaded.shows">{{ shows[currentShow].short_description }}</span>
<img
......@@ -39,6 +48,7 @@
@click="$refs.appModalShow.showShortDescription()"
>
</template>
<!-- The rest of the jumbotron is filled with the show description -->
<div v-if="loaded.shows">
<b>Description:</b> <img
src="../assets/16x16/emblem-system.png"
......@@ -58,6 +68,7 @@
</div>
</b-jumbotron>
<!-- If the shows are not fully loaded yet, we just put the loading sign -->
<div v-if="!loaded.shows">
<b-row>
<b-col align="center">
......@@ -68,6 +79,8 @@
</b-col>
</b-row>
</div>
<!-- When all show data is loaded, here we display all the rest -->
<div v-else>
<!-- include the modals to edit show and timeslot entries from the modal compontents -->
<app-modalShow
......@@ -80,13 +93,14 @@
:show-aggregate="current"
/>
<!-- here we show our table of timeslots -->
<!-- here are the filter settings for our timeslots table -->
<b-card>
<b-btn v-b-toggle.timeslotFilterCollapse>
Toggle timeslot filters
</b-btn>
<b-collapse id="timeslotFilterCollapse">
<br>
<!-- How many slots to show per table page -->
<b-row>
<b-col sm="3">
<label for="inputNumSlots">Number of slots to show:</label>
......@@ -99,6 +113,7 @@
/>
</b-col>
</b-row>
<!-- The start date to display timeslots from (defaults to today) -->
<b-row>
<b-col sm="3">
<label for="inputDateStart">From:</label>
......@@ -111,6 +126,7 @@
/>
</b-col>
</b-row>
<!-- The end date until to wich to display timeslots -->
<b-row>
<b-col sm="3">
<label for="inputNumSlots">Until (exclusive):</label>
......@@ -124,6 +140,7 @@
</b-col>
</b-row>
<br>
<!-- And finally two buttons, one to reset and one to apply the filter -->
<b-container
fluid
class="text-right"
......@@ -146,6 +163,8 @@
<br>
<!-- here we show our table of timeslots, if the timeslots are already
loaded (otherwise we just show the loading symbol) -->
<div v-if="loaded.timeslots">
<b-table
striped
......@@ -154,6 +173,7 @@
:fields="notesTableArrayFields"
:items="notesTableArray"
>
<!-- Title of the timeslot (if already set) -->
<template
slot="title"
slot-scope="data"
......@@ -161,18 +181,22 @@
<span v-if="data.value">{{ data.value }}</span>
<span v-else><small><i>(none set)</i></small></span>
</template>
<!-- Date and time when this timeslot starts -->
<template
slot="starts"
slot-scope="data"
>
{{ data.value }}
</template>
<!-- The duration of this timeslot -->
<template
slot="duration"
slot-scope="data"
>
{{ data.value }}
</template>
<!-- And here all the buttons for editing and doing other things
with the displayed timeslot -->
<template
slot="options"
slot-scope="data"
......@@ -215,14 +239,15 @@
@change="timeslotsPage"
/>
</div>
<div
v-else
style="text-align: center;"
>
<img
src="../assets/radio.gif"
alt="loading data"
><br>
<!-- If the timeslot data is not loaded, we just show the spinner instead
of the table itself -->
<div v-else>
<div style="text-align: center;">
<img
src="../assets/radio.gif"
alt="loading data"
><br>
</div>
</div>
<hr>
......@@ -590,11 +615,18 @@ import axios from 'axios'
import DOMPurify from 'dompurify'
export default {
// all modals to edit a show and its timeslots/notes, are importet as separate
// components, to make it a tiny lickle bit less messy here
components: {
'app-modalNotes': modalNotes,
'app-modalShow': modalShow
},
// generic functions that we want to use from our mixins folder
mixins: [ timeslotSort, prettyDate ],
// this component will be handling a lot of data - probably the component can
// be refactored to get rid of some redundancy here
data () {
return {
shows: [], // an array of objects describing our shows (empty at load, will be populated on created())
......@@ -603,6 +635,9 @@ export default {
numSlots: process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_NUMSLOTS, // all form input values are provided as strings
dateStart: this.apiDate(new Date()),
dateEnd: this.apiDate(new Date(new Date().getTime() + process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_DAYS * 86400000)),
// the loaded object holds flags for the different things we will fetch
// from the AuRa steering module
loaded: {
shows: false,
timeslots: false,
......@@ -615,6 +650,9 @@ export default {
fundingcategory: false,
type: false
},
// the current object is used to hold all the necessary data to describe
// the show which is currently selected by the user in the frontend
current: {
categories: [],
hosts: [],
......@@ -636,6 +674,8 @@ export default {
image: '',
logo: ''
},
// this is used to configure the table with all the filtered timeslots
notesTableArrayFields: [
{ key: 'title', label: 'Title of emission' },
{ key: 'starts', label: 'Emission start' },
......@@ -644,11 +684,26 @@ export default {
]
}
},
// Some of the info we need in the tempalte are not easily and directly
// retrievable, so we are computing them on the fly, when they are needed
computed: {
// As the show description should allow to be html-formatted, we have to
// make sure no malicous code can be inserted into the DOM. For that the
// DOMPurify library (https://github.com/cure53/DOMPurify) does us a much
// better service than trying to sanitize it with some RegExp.
sanitizedShowDescription: function () {
//return this.shows[this.currentShow].description.replace(/<[^>]*>/g, '')
return DOMPurify.sanitize(this.shows[this.currentShow].description)
},
// In order to not only just show the predecessor of a show as an ID. we
// have to find it in our shows array to then output the predecessors name.
// This currently assumes that a user has access to all the predecessors
// of the shows as well.
// TODO/discuss: if all predecessor names should be accessible, independent
// of access rights, then we would need to load all predecessors show after
// loading our initial shows as well.
predecessorName: function () {
for (var i in this.shows) {
if (this.shows[i].id === this.shows[this.currentShow].predecessor) {
......@@ -657,6 +712,9 @@ export default {
}
return 'Name of predecessor show not available'
},
// As we do not have a single object which holds all info we need to display
// in the table with our timeslots, we use this computed array to do that
notesTableArray: function () {
var arr = []
for (var i in this.current.timeslots) {
......@@ -675,6 +733,9 @@ export default {
return arr
}
},
// Right after this component is set up, we want to fetch all available shows
// from the AuRa steering module.
created () {
var uri = process.env.VUE_APP_API_STEERING_SHOWS
if (!this.$parent.user.steeringUser.is_superuser) {
......@@ -697,11 +758,18 @@ export default {
alert('There was an error fetching shows from the server: ' + error)
})
},
// Now for our hotchpotch of methods, mostly used for fetching data from the
// AuRa steering API (updateing will be done in the imported modal components)
methods: {
// Apply the newly set filter parameters for our timeslot table
applyFilter: function () {
this.current.timeslotmeta.page = 1
this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots)
},
// Reset the filter parameters for our timeslot table to config defaults
resetFilter: function () {
this.numSlots = process.env.VUE_APP_TIMESLOT_FILTER_DEFAULT_NUMSLOTS
this.dateStart = this.apiDate(new Date())
......@@ -709,12 +777,22 @@ export default {
this.current.timeslotmeta.page = 1
this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots)
},
// Load a different page of timeslots for the timeslots table
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)
}
},
// Every time the user switches to another show, we will load all related
// data (as e.g. categories, hosts, etc.) from the AuRa steering API, in case
// something changed.
// TODO/discuss: maybe this is too inefficient and we could only load this
// data just in the beginning after shows are loaded and assume they do not
// change throughout a session or put it into the user's responsibility to
// reload the show manager page after relevant changes.
switchShow: function (index) {
// 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
......@@ -748,6 +826,8 @@ export default {
// now fetch the timeslots (including notes) for a given show from PV backend
this.getTimeslots(this.dateStart, this.dateEnd, this.numSlots)
},
// Fetch timeslots for the current show and use filter variables if provided
getTimeslots: function (start, end, limit, offset) {
var dateRegex = new RegExp('^\\d{4}-\\d{2}-\\d{2}$')
var uri = process.env.VUE_APP_API_STEERING_SHOWS + this.currentShowID + '/timeslots/?'
......@@ -812,6 +892,8 @@ export default {
})
// done fetching timeslots
},
// Open the modal to edit a timeslot's note, given its ID and schedule ID
editTimeslotNote: function (timeslotID, scheduleID) {
this.current.note = null
for (var i in this.current.notes) {
......@@ -822,6 +904,8 @@ export default {
}
this.$refs.appModalNotes.showModal(this.current.note, timeslotID, scheduleID)
},
// For a given timeslot ID return the corresponding note, if there is one
getNoteByTimeslotID: function (timeslotID) {
for (var i in this.current.notes) {
if (this.current.notes[i].timeslot === timeslotID && this.current.notes[i].title !== undefined) {
......@@ -830,6 +914,8 @@ export default {
}
return null
},
// For a given timeslot ID, check if there is a note and return it
prettyTimeslotNote: function (timeslotID) {
var note = this.getTimeslotNoteTitle(timeslotID)
if (note !== null) {
......@@ -838,14 +924,17 @@ export default {
return ''
}
},
// Limiting display of strings up to 25 characters plus "..."
prettyTitle: function (title) {
if (title === '') { return '...' }
else if (title.length > 25) { return title.slice(0, 25) + '...' }
else { return title }
},
// 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?
// TODO: all those getSomething functions could be probably merged into one
// generic getItem function. Maybe this.current should be implemented
// in a dictionary kind of way then?
getCategories: function () {
this.current.categories = []
var loadingError = false
......@@ -866,6 +955,7 @@ export default {
if (!loadingError) { this.loaded.categories = true }
}
},
getHosts: function () {
this.current.hosts = []
var loadingError = false
......@@ -886,6 +976,7 @@ export default {
if (!loadingError) { this.loaded.hosts = true }
}
},
getLanguages: function () {
this.current.languages = []
var loadingError = false
......@@ -906,6 +997,7 @@ export default {
if (!loadingError) { this.loaded.languages = true }
}
},
getTopics: function () {
this.current.topics = []
var loadingError = false
......@@ -926,6 +1018,7 @@ export default {
if (!loadingError) { this.loaded.topics = true }
}
},
getMusicfocus: function () {
this.current.musicfocus = []
var loadingError = false
......@@ -946,6 +1039,7 @@ export default {
}
if (!loadingError) { this.loaded.musicfocus = true }
},
getFundingCategory: function () {
this.current.fundingcategory = []
var loadingError = false
......@@ -964,6 +1058,7 @@ export default {
}
if (!loadingError) { this.loaded.fundingcategory = true }
},
getType: function () {
this.current.type = []
var loadingError = false
......@@ -982,6 +1077,9 @@ export default {
}
if (!loadingError) { this.loaded.type = true }
},
// Just a placeholder function we can use in the UI, to signal if something
// is not yet implemented
notYetImplemented: function () {
alert('By the mighty witchcraftry of the mother of time!\n\nThis feature is not implemented yet.')
}
......
Markdown is supported
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