Commit cae7bd40 authored by Richard Blechinger's avatar Richard Blechinger
Browse files

Add image to note, show said image in emission listing

parent 6f4ba6d5
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# API URLs for the other AuRa modules # API URLs for the other AuRa modules
# =================================== # ===================================
VUE_APP_BASEURI_STEERING = http://127.0.0.1:8000 VUE_APP_BASEURI_STEERING = http://127.0.0.1:8000
VUE_APP_BASEURI_MEDIA = http://localhost:8000/site_media/
VUE_APP_API_STEERING = http://127.0.0.1:8000/api/v1/ VUE_APP_API_STEERING = http://127.0.0.1:8000/api/v1/
VUE_APP_API_STEERING_SHOWS = http://127.0.0.1:8000/api/v1/shows/ VUE_APP_API_STEERING_SHOWS = http://127.0.0.1:8000/api/v1/shows/
VUE_APP_API_TANK = http://127.0.0.1:8040/api/v1/ VUE_APP_API_TANK = http://127.0.0.1:8040/api/v1/
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# These are the REST API endpoints of your aura/steering module # These are the REST API endpoints of your aura/steering module
VUE_APP_BASEURI_STEERING = https://YOUR.STEERING.DOMAIN VUE_APP_BASEURI_STEERING = https://YOUR.STEERING.DOMAIN
VUE_APP_BASEURI_MEDIA = http://localhost:8000/site_media/
VUE_APP_API_STEERING = http://YOUR.STEERING.DOMAIN/api/v1/ VUE_APP_API_STEERING = http://YOUR.STEERING.DOMAIN/api/v1/
VUE_APP_API_STEERING_SHOWS = http://YOUR.STEERING.DOMAIN/api/v1/shows/ VUE_APP_API_STEERING_SHOWS = http://YOUR.STEERING.DOMAIN/api/v1/shows/
......
...@@ -68,6 +68,25 @@ ...@@ -68,6 +68,25 @@
/> />
</b-col> </b-col>
</b-row> </b-row>
<b-row>
<b-col cols="2">
Bild:
</b-col>
<b-col cols="10">
<input
accept="image/*"
type="file"
class="mb-3"
@change="setNoteImage"
>
<img
v-if="noteImage"
class="tw-w-full tw-block"
:src="noteImage"
>
</b-col>
</b-row>
</b-container> </b-container>
</b-modal> </b-modal>
</div> </div>
...@@ -92,6 +111,7 @@ export default { ...@@ -92,6 +111,7 @@ export default {
title: '', title: '',
summary: '', summary: '',
content: '', content: '',
image: null,
backuptitle: '', backuptitle: '',
backupsummary: '', backupsummary: '',
backupcontent: '', backupcontent: '',
...@@ -118,6 +138,12 @@ export default { ...@@ -118,6 +138,12 @@ export default {
return hosts return hosts
}, },
noteImage() {
return this.note.image.includes('http')
? this.note.image
: process.env.VUE_APP_BASEURI_STEERING + this.note.image
},
...mapGetters({ ...mapGetters({
selectedShow: 'shows/selectedShow', selectedShow: 'shows/selectedShow',
allHosts: 'shows/hosts', allHosts: 'shows/hosts',
...@@ -129,29 +155,37 @@ export default { ...@@ -129,29 +155,37 @@ export default {
// prevent the modal from closing automatically on click // prevent the modal from closing automatically on click
event.preventDefault() event.preventDefault()
// backup the note contents // backup the note contents
const backupImage = this.note.image
const backupWidth = this.note.width
const backupHeight = this.note.height
this.backuptitle = this.note.title this.backuptitle = this.note.title
this.backupsummary = this.note.summary this.backupsummary = this.note.summary
this.backupcontent = this.note.content this.backupcontent = this.note.content
this.backuphost = this.note.host this.backuphost = this.note.host
// now set the new contents // now set the new contents
this.note.title = this.title this.note.title = this.title
this.note.summary = this.summary this.note.summary = this.summary
this.note.content = this.content this.note.content = this.content
this.note.host = this.host_selected this.note.host = this.host_selected
if (this.image) {
this.note.image = this.image
}
// for new notes we need to set some extras that are not in the UI yet // for new notes we need to set some extras that are not in the UI yet
if (updatemode === SUBMIT_NEW) { if (updatemode === SUBMIT_NEW) {
this.note.show = this.selectedShow.id this.note.show = this.selectedShow.id
this.note.timeslot = this.timeslotID this.note.timeslot = this.timeslotID
this.note.slug = this.slug this.note.slug = this.slug
this.note.ppoi = '(0.5,0.5)' // TODO: implement this.note.ppoi = '(0.5,0.5)' // TODO: implement
this.note.height = null // TODO: implement
this.note.width = null // TODO: implement
this.note.image = null // TODO: implement
this.note.status = 1 // TODO: implement this.note.status = 1 // TODO: implement
this.note.start = '' // TODO: implement this.note.start = '' // TODO: implement
this.note.cba_id = null // TODO: implement this.note.cba_id = 0 // TODO: implement
this.note.audio_url = '' // TODO: implement this.note.audio_url = '' // TODO: implement
} }
let modal = this.$refs.modalNote let modal = this.$refs.modalNote
this.$store.dispatch('shows/submitNote', { this.$store.dispatch('shows/submitNote', {
update: updatemode, update: updatemode,
...@@ -167,15 +201,22 @@ export default { ...@@ -167,15 +201,22 @@ export default {
this.note.summary = this.backupsummary this.note.summary = this.backupsummary
this.note.content = this.backupcontent this.note.content = this.backupcontent
this.note.host = this.backuphost this.note.host = this.backuphost
this.note.image = backupImage;
this.note.width = backupWidth;
this.note.height = backupHeight;
if (updatemode === SUBMIT_NEW) { this.note.start = undefined } if (updatemode === SUBMIT_NEW) { this.note.start = undefined }
// and we leave the modal open, so no call to its .hide function here // and we leave the modal open, so no call to its .hide function here
} }
}) })
}, },
setNoteImage(event) {
this.image = event.target.files.item(0);
},
update (event) { update (event) {
// only try to save if anything has changed // only try to save if anything has changed
if (this.title !== this.note.title || this.summary !== this.note.summary || this.content !== this.note.content || this.host_selected !== this.note.host) { if (this.title !== this.note.title || this.summary !== this.note.summary || this.content !== this.note.content || this.host_selected !== this.note.host || this.image) {
this.submit(event, SUBMIT_UPDATE) this.submit(event, SUBMIT_UPDATE)
} }
// if nothing was changed, just close the modal // if nothing was changed, just close the modal
...@@ -196,8 +237,18 @@ export default { ...@@ -196,8 +237,18 @@ export default {
}, },
saveNote (event) { saveNote (event) {
if (this.note.start === undefined) { this.new(event) } if (this.note.start === undefined) {
else { this.update(event) } this.new(event)
return
}
// If the note image is a string we haven't updated the field
// and thus delete it, so the API doesn't try to update it by mistake.
if (typeof this.note.image === 'string') {
delete this.note.image
}
this.update(event)
}, },
openModal (note, timeslotID, scheduleID) { openModal (note, timeslotID, scheduleID) {
......
...@@ -97,6 +97,13 @@ ...@@ -97,6 +97,13 @@
:fields="notesTableArrayFields" :fields="notesTableArrayFields"
:items="notesTableArray" :items="notesTableArray"
> >
<template v-slot:cell(thumbnail)="data">
<div
:style="`background-image: url(${data.value})`"
:class="{ 'tw-w-12 tw-h-12 rounded-lg tw-bg-cover tw-bg-center': true, 'tw-bg-gray-400': !data.value }"
/>
</template>
<!-- Title of the timeslot (if already set) --> <!-- Title of the timeslot (if already set) -->
<template v-slot:cell(title)="data"> <template v-slot:cell(title)="data">
<span v-if="data.value">{{ data.value }}</span> <span v-if="data.value">{{ data.value }}</span>
...@@ -198,11 +205,12 @@ export default { ...@@ -198,11 +205,12 @@ export default {
// this is used to configure the table with all the filtered timeslots // this is used to configure the table with all the filtered timeslots
notesTableArrayFields: [ notesTableArrayFields: [
{ key: 'title', label: 'Title of emission' }, { key: 'thumbnail', label: '', class: 'align-middle tw-w-16' },
{ key: 'starts', label: 'Emission start' }, { key: 'title', label: 'Title of emission', class: 'align-middle' },
{ key: 'duration', label: 'Duration' }, { key: 'starts', label: 'Emission start', class: 'align-middle' },
{ key: 'options', label: 'Edit' }, { key: 'duration', label: 'Duration', class: 'align-middle' },
{ key: 'playlist', label: 'Playlist' }, { key: 'options', label: 'Edit', class: 'align-middle' },
{ key: 'playlist', label: 'Playlist', class: 'align-middle' },
], ],
} }
}, },
...@@ -222,14 +230,13 @@ export default { ...@@ -222,14 +230,13 @@ export default {
// As we do not have a single object which holds all info we need to display // 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 // in the table with our timeslots, we use this computed array to do that
notesTableArray: function () { notesTableArray: function () {
let rows = [] let rows = [];
for (let i in this.timeslots) { for (const timeslot of this.timeslots) {
let note = this.getNoteByTimeslotID(this.timeslots[i].id) let note = this.getNoteByTimeslotID(timeslot.id)
if (note !== null) { note = note.title }
let playlistTitle = '' let playlistTitle = ''
if (this.timeslots[i].playlist_id !== null) { if (timeslot.playlist_id !== null) {
let playlist = this.playlists.find(list => list.id === this.timeslots[i].playlist_id) let playlist = this.playlists.find(list => list.id === timeslot.playlist_id)
if (playlist) { if (playlist) {
if (playlist.description.length > 0) { if (playlist.description.length > 0) {
playlistTitle = playlist.description playlistTitle = playlist.description
...@@ -240,13 +247,14 @@ export default { ...@@ -240,13 +247,14 @@ export default {
} }
rows.push({ rows.push({
title: note, title: note ? note.title : null,
starts: this.prettyDateTime(this.timeslots[i].start), starts: this.prettyDateTime(timeslot.start),
duration: this.prettyDuration(this.timeslots[i].start, this.timeslots[i].end), duration: this.prettyDuration(timeslot.start, timeslot.end),
thumbnail: note ? process.env.VUE_APP_BASEURI_MEDIA + note.thumbnails[2] : null,
options: { options: {
id: this.timeslots[i].id, id: timeslot.id,
schedule: this.timeslots[i].schedule, schedule: timeslot.schedule,
play: this.timeslots[i].playlist_id !== null play: timeslot.playlist_id !== null
}, },
playlist: playlistTitle playlist: playlistTitle
}) })
......
...@@ -330,6 +330,8 @@ const actions = { ...@@ -330,6 +330,8 @@ const actions = {
}, },
submitNote (ctx, data) { submitNote (ctx, data) {
const NON_UPDATEABLE_PROPERTIES = [ 'thumbnails', 'width', 'height' ];
let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.id + let uri = process.env.VUE_APP_API_STEERING_SHOWS + data.id +
'/schedules/' + data.scheduleID + '/schedules/' + data.scheduleID +
'/timeslots/' + data.timeslotID + '/timeslots/' + data.timeslotID +
...@@ -337,11 +339,20 @@ const actions = { ...@@ -337,11 +339,20 @@ const actions = {
if (data.update) { if (data.update) {
uri += data.note.id + '/' uri += data.note.id + '/'
} }
let method = data.update ? 'put' : 'post' let method = data.update ? 'put' : 'post'
let formData = new FormData();
for (const [key, value] of Object.entries(data.note)) {
if (data.update && NON_UPDATEABLE_PROPERTIES.includes(key)) continue;
formData.append(key, value);
}
axios.request({ axios.request({
url: uri, url: uri,
method: method, method: method,
data: data.note, data: formData,
withCredentials: true, withCredentials: true,
responseType: 'json', // we need this explicitly here, as it does not seem to work automagically as in GET and PUT requests responseType: 'json', // we need this explicitly here, as it does not seem to work automagically as in GET and PUT requests
headers: { 'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token } headers: { 'Authorization': 'Bearer ' + ctx.rootState.auth.user.access_token }
......
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