Skip to content
Snippets Groups Projects
NotesModal.vue 10.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •     <div>
            <b-modal
    
                ref="modalNote"
                :title="$t('noteEditor.editNote')"
                :cancel-title="$t('cancel')"
                size="lg"
                @ok="saveNote"
    
            >
                <b-container fluid>
                    <p v-if="typeof note.start !== 'undefined'">
    
                        {{ $t('noteEditor.intro.existing', { date: prettyDateTime(note.start) }) }}
    
                    </p>
                    <p v-else>
    
                        {{ $t('noteEditor.intro.new') }}
    
                    </p>
                    <b-row>
    
                        <b-col cols="3">
                            {{ $t('noteEditor.title') }}:
    
                        </b-col>
    
                        <b-col cols="9">
    
                            <b-form-input
    
                                v-model="title"
                                type="text"
                                :placeholder="$t('noteEditor.titlePlaceholder')"
    
                            />
                        </b-col>
    
                        <b-col cols="3" />
                        <b-col cols="9">
                            <small class="slug">{{ $t('slug') }}: {{ slug }}</small>
    
                        </b-col>
                    </b-row>
                    <br>
                    <b-row>
    
                        <b-col cols="3">
                            {{ $t('noteEditor.summary') }}:
    
                        </b-col>
    
                        <b-col cols="9">
    
                            <b-form-textarea
    
                                v-model="summary"
                                :rows="4"
                                :placeholder="$t('noteEditor.summaryPlaceholder')"
    
                            />
                        </b-col>
                    </b-row>
                    <br>
                    <b-row>
    
                        <b-col cols="3">
                            {{ $t('noteEditor.content') }}:
    
                        </b-col>
    
                        <b-col cols="9">
    
                            <b-form-textarea
    
                                v-model="content"
                                :rows="8"
                                :placeholder="$t('noteEditor.contentPlaceholder')"
    
                            />
                        </b-col>
                    </b-row>
                    <br>
                    <b-row>
    
                        <b-col cols="3">
                            {{ $t('noteEditor.host') }}:
    
                        </b-col>
    
                        <b-col cols="9">
    
                            <b-form-select
    
                                v-model="host_selected"
                                :options="hosts"
                                class="mb-3"
    
                            />
                        </b-col>
                    </b-row>
                    <b-row>
    
                        <b-col cols="3">
                            {{ $t('noteEditor.image') }}:
    
                        </b-col>
    
                        <b-col cols="9">
                            <b-form-file
    
                                accept="image/*"
                                type="file"
                                class="mb-3"
                                :browse-text="$t('browse')"
                                :placeholder="$t('noteEditor.chooseImage')"
                                @change="setNoteImage"
    
                            <img
    
                                v-if="noteImage"
                                class="tw-w-full tw-block"
                                :src="noteImage"
    
                            >
                        </b-col>
                    </b-row>
                </b-container>
            </b-modal>
        </div>
    
        import {mapGetters} from 'vuex'
        import prettyDate from '../../mixins/prettyDate'
        import slugify from '../../mixins/slugify'
    
        const SUBMIT_NEW = false
        const SUBMIT_UPDATE = true
    
        export default {
            mixins: [prettyDate, slugify],
    
            data() {
                return {
                    note: {},
                    scheduleID: 0,
                    timeslotID: 0,
                    title: '',
                    summary: '',
                    content: '',
                    image: null,
                    backuptitle: '',
                    backupsummary: '',
                    backupcontent: '',
                    backuphost: null,
                    host_selected: null
                }
            },
    
            computed: {
                slug() {
                    return this.slugify(this.title)
                },
                hosts() {
                    // for the vue bootstrap select component we need an array of objects
                    // with a value, a text and optionally a disabled element
                    let hosts = []
                    if (!this.$store.state.shows.loaded.hosts) {
                        return hosts
                    }
                    for (let id of this.selectedShow.hosts) {
                        let host = this.allHosts.find(h => h.id === id)
                        hosts.push({
                            value: host.id,
                            text: host.name,
                            disabled: !host.is_active
                        })
                    }
                    return hosts
                },
    
                noteImage() {
                    if (!this.note.image) {
    
                        return ''
    
                    return this.note.image.includes('http')
                        ? this.note.image
    
                        : import.meta.env.VUE_APP_BASEURI_STEERING + this.note.image
    
                ...mapGetters({
                    selectedShow: 'shows/selectedShow',
                    allHosts: 'shows/hosts',
                })
            },
    
            methods: {
                submit(event, updatemode) {
                    // prevent the modal from closing automatically on click
                    event.preventDefault()
                    // 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.backupsummary = this.note.summary
                    this.backupcontent = this.note.content
                    this.backuphost = this.note.host
    
                    // now set the new contents
                    this.note.title = this.title
                    this.note.summary = this.summary
                    this.note.content = this.content
                    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
                    if (updatemode === SUBMIT_NEW) {
                        this.note.show = this.selectedShow.id
                        this.note.timeslot = this.timeslotID
                        this.note.slug = this.slug
                        this.note.ppoi = '(0.5,0.5)' // TODO: implement
                        this.note.status = 1 // TODO: implement
                        this.note.start = '' // TODO: implement
                        this.note.cba_id = 0 // TODO: implement
                        this.note.audio_url = '' // TODO: implement
                    }
    
                    let modal = this.$refs.modalNote
                    this.$store.dispatch('shows/submitNote', {
                        update: updatemode,
                        id: this.selectedShow.id,
                        scheduleID: this.scheduleID,
                        timeslotID: this.timeslotID,
                        note: this.note,
                        callback: () => {
                            modal.hide()
                        },
                        callbackCancel: () => {
                            // as there was an error saving the show, we have to make sure
                            // to restore the initial values of the note object
                            this.note.title = this.backuptitle
                            this.note.summary = this.backupsummary
                            this.note.content = this.backupcontent
                            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
                            }
                            // 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) {
                    // 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 || this.image) {
                        this.submit(event, SUBMIT_UPDATE)
                    }
                    // if nothing was changed, just close the modal
                    else {
                        this.$refs.modalNote.hide()
                    }
                },
    
                new(event) {
                    // title and content are necessary
                    if (this.title.trim() === '' || this.content.trim() === '' || this.host_selected === null) {
                        event.preventDefault()
                        // 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 some content and choose a host!')
                    } else {
                        this.submit(event, SUBMIT_NEW)
                    }
                },
    
                saveNote(event) {
                    if (this.note.start === undefined) {
                        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) {
                    if (note === null) {
                        this.note = {}
                        this.title = ''
                        this.summary = ''
                        this.content = ''
                        // TODO: integrate this into the user's app settings:
                        //   should the field be empty by default or filled with the first host of the show?
                        this.host_selected = null
                    } else {
                        this.note = {...note}
                        this.title = this.note.title
                        this.summary = this.note.summary
                        this.content = this.note.content
                        this.host_selected = this.note.host
                    }
                    this.timeslotID = timeslotID
                    this.scheduleID = scheduleID
    
                    this.$refs.modalNote.show()
                }
            }
    
        .slug {
            color: gray;
        }