Skip to content
Snippets Groups Projects
  • Konrad Mohrfeldt's avatar
    7adb359c
    refactor: unify state update routines and remove selectedShow-dependent code · 7adb359c
    Konrad Mohrfeldt authored
    This refactors the existing state helpers (useCopy and
    useUpdatableState) and unifies them to useUpdateBehaviour, useCopy,
    useAPIObjectFieldCopy, useRelation and useRelationList. This eliminates
    a lot of custom code in the show settings page and unifies the behaviour
    of all input fields and save operations making the experience more
    consistent and understandable.
    
    It also enables us to show the save-in-progress state and errors that
    occurred during updates for all fields along with customizable debounce
    and proper v-model support.
    
    We also got rid of the remaining uses of useSelectedShow. The show
    settings page still made use of it despite using a route that
    provides the relevant show that should be edited.
    7adb359c
    History
    refactor: unify state update routines and remove selectedShow-dependent code
    Konrad Mohrfeldt authored
    This refactors the existing state helpers (useCopy and
    useUpdatableState) and unifies them to useUpdateBehaviour, useCopy,
    useAPIObjectFieldCopy, useRelation and useRelationList. This eliminates
    a lot of custom code in the show settings page and unifies the behaviour
    of all input fields and save operations making the experience more
    consistent and understandable.
    
    It also enables us to show the save-in-progress state and errors that
    occurred during updates for all fields along with customizable debounce
    and proper v-model support.
    
    We also got rid of the remaining uses of useSelectedShow. The show
    settings page still made use of it despite using a route that
    provides the relevant show that should be edited.
FallbackSelector.vue 4.07 KiB
<template>
  <b-modal
    ref="modalFallbackSelector"
    :title="$t('playlistSelector.defaultTitle')"
    :cancel-title="$t('cancel')"
    size="lg"
  >
    <p v-if="loaded">
      {{ $t('playlistSelector.currentPlaylistLabel') }}:
      <span v-if="show.defaultPlaylistId === null">
        <i
          ><small>{{ $t('noneSetFeminine') }}</small></i
        >
      </span>
      <span v-else>
        {{ show.defaultPlaylistId }},
        <br />
        <span v-if="currentPlaylistDescription">
          {{ $t('showMeta.description') }}: <b>{{ currentPlaylistDescription }}</b>
        </span>
      </span>
    </p>

    <div v-if="loaded">
      <b-table ref="playlistsTable" striped :fields="playlistsTableFields" :items="playlists">
        <!-- Column: Entries
                This column displays the number of entries of the playlist.
                -->
        <template #cell(entries)="data">
          <span
            v-b-tooltip.html="playlistToolTip(data.value)"
            class="tw-underline hover:tw-no-underline tw-cursor-help"
          >
            {{ $t('playlistTable.items', { smart_count: data.value.length }) }}
          </span>
        </template>

        <!-- Column: Duration
                This column displays the number of entries of the playlist.
                -->
        <template #cell(duration)="data">
          {{ playlistDuration(data.item) }}
        </template>

        <!-- Column: Actions
                This column displays the available buttons for actions the user can
                take on this playlist (e.g. editing and deleting).
                -->
        <template #cell(actions)="data">
          <b-button-group size="sm">
            <b-button
              v-if="data.item.id !== show.defaultPlaylistId"
              variant="info"
              @click="choose(data.item.id)"
            >
              {{ $t('playlistTable.assign') }}
            </b-button>
            <b-button v-else variant="danger" @click="choose(null)">
              {{ $t('playlistTable.unset') }}
            </b-button>
          </b-button-group>
        </template>
      </b-table>
    </div>
    <div v-else>
      <img src="/assets/radio.gif" :alt="$t('loading')" />
    </div>

    <div>
      <b-button :to="'files'">
        {{ $t('playlistSelector.goToFiles') }}
      </b-button>
    </div>
  </b-modal>
</template>

<script>
import { mapGetters } from 'vuex'

import prettyDate from '@/mixins/prettyDate'
import playlist from '@/mixins/playlist'

export default {
  mixins: [prettyDate, playlist],

  props: {
    show: { type: Object, required: true },
  },

  data() {
    return {
      saveFunction: null,
    }
  },

  computed: {
    loaded() {
      return this.$store.state.playlists.loaded.playlists
    },

    playlistsTableFields() {
      return [
        { key: 'id', label: this.$t('playlistTable.index') },
        { key: 'description', label: this.$t('playlistTable.description') },
        { key: 'entries', label: this.$t('playlistTable.entries') },
        { key: 'duration', label: this.$t('playlistTable.duration') },
        { key: 'actions', label: this.$t('playlistTable.actions'), class: 'text-right' },
      ]
    },

    currentPlaylistDescription() {
      let description = false
      if (this.show.defaultPlaylistId !== null) {
        const choosenList = this.playlists.find((list) => list.id === this.show.defaultPlaylistId)
        if (choosenList && choosenList.description.length > 0) {
          description = choosenList.description
        }
      }
      return description
    },

    ...mapGetters({
      playlists: 'playlists/playlists',
    }),
  },

  methods: {
    open(saveFunction) {
      this.saveFunction = saveFunction
      this.$refs.modalFallbackSelector.show()
    },

    hide() {
      this.$refs.modalFallbackSelector.hide()
    },

    choose(id) {
      this.saveFunction(id)
    },

    playlistToolTip(entries) {
      let text = '<div style="white-space: nowrap;" align="left">'
      for (const i in entries) {
        text += i + ': ' + entries[i].uri + '<br>'
      }
      text += '</div>'
      return text
    },
  },
}
</script>